Skip to content

Commit fd3e0e0

Browse files
rahulbabu95Rahul
andauthored
Add LLM-powered automatic patch fixing for version bumps (#5013)
* Add LLM-powered automatic patch fixing for version bumps This commit introduces an intelligent patch fixing system that uses AWS Bedrock (Claude Sonnet 4.5) to automatically update patches when upstream versions change. Key Features: - Automatic patch conflict resolution using LLM analysis - Smart context extraction showing current vs expected file state - Pristine content capture before patch application for accurate context - Iterative fixing with up to 3 attempts per patch - Special handling for kubernetes/autoscaler project (cloud provider removal) - Rate limiting and cost tracking for Bedrock API calls - Comprehensive validation (semantic and build checks) Implementation Details: - Uses git apply --reject to identify conflicts and generate .rej files - Extracts ±50 lines of context around conflict points - Provides LLM with original patch intent and current file state - Validates generated patches match original semantic changes - Supports both release-branched and non-release-branched projects Special Cases: - kubernetes/autoscaler: Automated cloud provider removal and go mod tidy - Handles complex multi-file patches with mixed success/failure states - Preserves exact indentation and formatting from current files Prompt Engineering: - Explicit instructions to use current file content, not original patch context - Critical warnings about indentation matching (tabs vs spaces) - Structured format with metadata preservation - Context pruning for large patches to stay within token limits Core Components: - fixpatches.go: Main orchestration and patch application logic - llm.go: AWS Bedrock API integration with rate limiting - context.go: Smart context extraction from .rej files and pristine content - applier.go: Git operations for patch application and validation - validator.go: Semantic and build validation of fixed patches - autoscaler.go: Special handling for kubernetes/autoscaler project - types/fixpatches.go: Type definitions for patch context and results This enables automated maintenance of patches across version bumps, reducing manual effort and ensuring patches stay current with upstream changes. Tested on: - kubernetes/autoscaler (1-29, 1-30) - kube-vip/kube-vip - linuxkit/linuxkit - fluxcd/source-controller - kubernetes-sigs/kind * Move git commands to separate file and remove repitive code patterns Signed-off-by: Rahul <[email protected]> * Update documentation about fix-patches command Signed-off-by: Rahul <[email protected]> --------- Signed-off-by: Rahul <[email protected]> Co-authored-by: Rahul <[email protected]>
1 parent 0a2c5d9 commit fd3e0e0

File tree

16 files changed

+4291
-2
lines changed

16 files changed

+4291
-2
lines changed

tools/version-tracker/README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ vmware govmomi
204204

205205
The `upgrade` subcommand is used to upgrade the Git revision of a particular project. This command takes in a project name as input and updates the various version files pertaining to the project, such as Git tag, Go version, checksums, etc. Then it creates a PR with these changes from a fork of the build-tooling repository. The PR can then be reviewed and merged by a repository maintainer.
206206

207+
When patches fail to apply during an upgrade, the command can optionally publish an event to AWS EventBridge (if `ENABLE_AUTO_PATCH_FIX=true`) for downstream automation.
208+
207209
#### Usage
208210

209211
```
@@ -234,4 +236,92 @@ Updating Git tag and Go version in upstream projects tracker file
234236
Updating project checksums and attribution files
235237
Updating project readme
236238
Creating pull request with updated files
239+
```
240+
241+
### The `fix-patches` subcommand
242+
243+
The `fix-patches` subcommand is used to automatically fix patches that fail to apply during version upgrades. This command uses AI (AWS Bedrock with Claude) to analyze patch failures, understand the context, and generate corrected patches.
244+
245+
#### How it works
246+
247+
1. **Analyzes patch failures** - Extracts information about which patches failed and why
248+
2. **Gathers context** - Fetches relevant code from GitHub (PR diff, failed files, patch content)
249+
3. **Generates fixes** - Uses Claude AI to understand the changes and create corrected patches
250+
4. **Validates fixes** - Applies patches and runs builds to ensure they work
251+
5. **Updates metadata** - Regenerates checksums and attribution files
252+
6. **Pushes changes** - Commits and pushes fixed patches back to the PR
253+
254+
#### Usage
255+
256+
```
257+
$ version-tracker fix-patches --help
258+
Automatically fix patches that fail to apply during version upgrades
259+
260+
Usage:
261+
version-tracker fix-patches --project <project name> --pr <pr number> [flags]
262+
263+
Flags:
264+
-h, --help help for fix-patches
265+
--max-attempts int Maximum number of fix attempts per patch (default 3)
266+
--pr int PR number where patches failed
267+
--project string Project name (e.g., kubernetes-sigs/image-builder)
268+
269+
Global Flags:
270+
-v, --verbosity int Set the logging verbosity level
271+
```
272+
273+
#### Required Environment Variables
274+
275+
```bash
276+
# GitHub access
277+
export GITHUB_TOKEN=<your-github-token>
278+
279+
# AWS Bedrock for AI-powered patch fixing
280+
export AWS_BEDROCK_REGION=us-west-2
281+
export BEDROCK_MODEL_ID=anthropic.claude-3-5-sonnet-20241022-v2:0
282+
```
283+
284+
#### Sample output
285+
286+
```
287+
$ version-tracker fix-patches --project kubernetes-sigs/image-builder --pr 5005
288+
Starting patch fixing workflow {"project": "kubernetes-sigs/image-builder", "pr": 5005}
289+
Analyzing patch failures...
290+
Found 1 failed patch: 0001-EKS-A-AMI-changes.patch
291+
Extracting context from GitHub PR #5005...
292+
Fetching PR diff (2847 lines)...
293+
Fetching failed files content...
294+
Building prompt for LLM (estimated 45000 tokens)...
295+
Calling Claude to generate patch fix...
296+
Received fix from LLM (3421 tokens)
297+
Applying fixed patch...
298+
Patch applied successfully!
299+
Running build validation...
300+
Build succeeded!
301+
Updating checksums...
302+
Updating attribution files...
303+
Committing changes...
304+
Pushing to PR branch...
305+
Successfully fixed patches for kubernetes-sigs/image-builder PR #5005
306+
```
307+
308+
#### Special Cases
309+
310+
Some projects require special handling:
311+
312+
- **kubernetes/autoscaler**: Patches are in `projects/kubernetes/autoscaler/patches/` and need to be regenerated using `git format-patch` after fixes are applied to the source code.
313+
314+
#### Running Locally
315+
316+
Run `fix-patches` manually when you see a PR with patch failures:
317+
318+
```bash
319+
# Set up environment
320+
export GITHUB_TOKEN=$(gh auth token)
321+
export AWS_BEDROCK_REGION=us-west-2
322+
export BEDROCK_MODEL_ID=anthropic.claude-3-5-sonnet-20241022-v2:0
323+
324+
# Run from the repository root
325+
cd /path/to/eks-anywhere-build-tooling
326+
version-tracker fix-patches --project fluxcd/source-controller --pr 4883
237327
```
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package cmd
2+
3+
import (
4+
"log"
5+
6+
"github.com/spf13/cobra"
7+
8+
"github.com/aws/eks-anywhere-build-tooling/tools/version-tracker/pkg/commands/fixpatches"
9+
"github.com/aws/eks-anywhere-build-tooling/tools/version-tracker/pkg/types"
10+
)
11+
12+
var fixPatchesOptions = &types.FixPatchesOptions{}
13+
14+
// fixPatchesCmd is the command used to fix failed patches using LLM assistance.
15+
var fixPatchesCmd = &cobra.Command{
16+
Use: "fix-patches --project <project name> --pr <PR number>",
17+
Short: "Fix failed patches using LLM assistance",
18+
Long: "Use this command to automatically fix failed patch applications using AWS Bedrock LLM. The command analyzes .rej files, generates fixes, and validates them through compilation.",
19+
Run: func(cmd *cobra.Command, args []string) {
20+
err := fixpatches.Run(fixPatchesOptions)
21+
if err != nil {
22+
log.Fatalf("Error fixing patches: %v", err)
23+
}
24+
},
25+
}
26+
27+
func init() {
28+
rootCmd.AddCommand(fixPatchesCmd)
29+
30+
// Required flags
31+
fixPatchesCmd.Flags().StringVar(&fixPatchesOptions.ProjectName, "project", "", "Specify the project name (e.g., aquasecurity/trivy)")
32+
fixPatchesCmd.Flags().IntVar(&fixPatchesOptions.PRNumber, "pr", 0, "Specify the PR number")
33+
34+
// Optional flags
35+
fixPatchesCmd.Flags().BoolVar(&fixPatchesOptions.Auto, "auto", false, "Auto-detect project and PR from current git branch")
36+
fixPatchesCmd.Flags().IntVar(&fixPatchesOptions.MaxAttempts, "max-attempts", 5, "Maximum number of fix attempts")
37+
fixPatchesCmd.Flags().StringVar(&fixPatchesOptions.Model, "model", "anthropic.claude-sonnet-4-5-20250929-v1:0", "Bedrock model ID to use (Claude Sonnet 4.5 - 200K context, 200K tokens/min)")
38+
fixPatchesCmd.Flags().StringVar(&fixPatchesOptions.Region, "region", "us-west-2", "AWS region for Bedrock API")
39+
fixPatchesCmd.Flags().IntVar(&fixPatchesOptions.ComplexityThreshold, "complexity-threshold", 10, "Skip patches exceeding this complexity score")
40+
fixPatchesCmd.Flags().BoolVar(&fixPatchesOptions.CommentOnPR, "comment-on-pr", false, "Post success/failure comment on the PR")
41+
fixPatchesCmd.Flags().BoolVar(&fixPatchesOptions.Push, "push", false, "Commit and push fixed patches to the PR branch")
42+
fixPatchesCmd.Flags().StringVar(&fixPatchesOptions.Branch, "branch", "", "Branch name to push to (required if --push is used)")
43+
44+
// Mark required flags (unless --auto is used)
45+
fixPatchesCmd.MarkFlagsRequiredTogether("project", "pr")
46+
}

tools/version-tracker/go.mod

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,81 @@ go 1.24
55
toolchain go1.24.0
66

77
require (
8+
github.com/aws/aws-sdk-go-v2 v1.40.1
9+
github.com/aws/aws-sdk-go-v2/config v1.31.12
10+
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.41.0
11+
github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0
812
github.com/aws/eks-distro-build-tooling/release v0.0.0-20240513204929-c69ded04ed10
913
github.com/ghodss/yaml v1.0.0
1014
github.com/go-git/go-git/v5 v5.13.0
1115
github.com/go-logr/logr v1.2.4
1216
github.com/go-logr/zapr v1.2.4
17+
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
1318
github.com/google/go-github/v53 v53.2.0
1419
github.com/pelletier/go-toml/v2 v2.0.8
1520
github.com/rodaine/table v1.1.0
1621
github.com/spf13/cobra v1.7.0
1722
github.com/spf13/viper v1.16.0
1823
go.uber.org/zap v1.24.0
1924
gopkg.in/yaml.v3 v3.0.1
25+
k8s.io/api v0.26.2
26+
k8s.io/apimachinery v0.26.2
27+
k8s.io/autoscaler v0.0.0-20251204101657-bc3f44c85df1
28+
k8s.io/client-go v0.26.1
2029
sigs.k8s.io/yaml v1.3.0
2130
)
2231

2332
require (
2433
dario.cat/mergo v1.0.0 // indirect
2534
github.com/Microsoft/go-winio v0.6.1 // indirect
2635
github.com/ProtonMail/go-crypto v1.1.3 // indirect
36+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect
37+
github.com/aws/aws-sdk-go-v2/credentials v1.18.16 // indirect
38+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 // indirect
39+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15 // indirect
40+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15 // indirect
41+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
42+
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 // indirect
43+
github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.15 // indirect
44+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect
45+
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 // indirect
46+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15 // indirect
47+
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 // indirect
48+
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 // indirect
49+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect
50+
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect
51+
github.com/aws/smithy-go v1.24.0 // indirect
2752
github.com/cloudflare/circl v1.3.7 // indirect
2853
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
54+
github.com/davecgh/go-spew v1.1.1 // indirect
55+
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
2956
github.com/emirpasic/gods v1.18.1 // indirect
3057
github.com/fsnotify/fsnotify v1.6.0 // indirect
3158
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
3259
github.com/go-git/go-billy/v5 v5.6.0 // indirect
60+
github.com/go-openapi/jsonpointer v0.19.5 // indirect
61+
github.com/go-openapi/jsonreference v0.20.0 // indirect
62+
github.com/go-openapi/swag v0.19.14 // indirect
3363
github.com/gogo/protobuf v1.3.2 // indirect
3464
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
3565
github.com/golang/protobuf v1.5.3 // indirect
66+
github.com/google/gnostic v0.5.7-v3refs // indirect
67+
github.com/google/go-cmp v0.6.0 // indirect
3668
github.com/google/go-querystring v1.1.0 // indirect
3769
github.com/google/gofuzz v1.2.0 // indirect
3870
github.com/hashicorp/hcl v1.0.0 // indirect
71+
github.com/imdario/mergo v0.3.6 // indirect
3972
github.com/inconshreveable/mousetrap v1.1.0 // indirect
4073
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
74+
github.com/josharian/intern v1.0.0 // indirect
4175
github.com/json-iterator/go v1.1.12 // indirect
4276
github.com/kevinburke/ssh_config v1.2.0 // indirect
4377
github.com/magiconair/properties v1.8.7 // indirect
78+
github.com/mailru/easyjson v0.7.6 // indirect
4479
github.com/mitchellh/mapstructure v1.5.0 // indirect
4580
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4681
github.com/modern-go/reflect2 v1.0.2 // indirect
82+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
4783
github.com/pjbgf/sha1cd v0.3.0 // indirect
4884
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
4985
github.com/skeema/knownhosts v1.3.0 // indirect
@@ -61,17 +97,18 @@ require (
6197
golang.org/x/oauth2 v0.8.0 // indirect
6298
golang.org/x/sync v0.12.0 // indirect
6399
golang.org/x/sys v0.31.0 // indirect
100+
golang.org/x/term v0.30.0 // indirect
64101
golang.org/x/text v0.23.0 // indirect
102+
golang.org/x/time v0.3.0 // indirect
65103
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
66104
google.golang.org/appengine v1.6.7 // indirect
67105
google.golang.org/protobuf v1.33.0 // indirect
68106
gopkg.in/inf.v0 v0.9.1 // indirect
69107
gopkg.in/ini.v1 v1.67.0 // indirect
70108
gopkg.in/warnings.v0 v0.1.2 // indirect
71109
gopkg.in/yaml.v2 v2.4.0 // indirect
72-
k8s.io/api v0.26.2 // indirect
73-
k8s.io/apimachinery v0.26.2 // indirect
74110
k8s.io/klog/v2 v2.90.1 // indirect
111+
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
75112
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
76113
sigs.k8s.io/controller-runtime v0.14.6 // indirect
77114
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect

0 commit comments

Comments
 (0)