From c743ef676301bf24f0493a639b78c8bad6eb4431 Mon Sep 17 00:00:00 2001 From: Dhananjay Mishra Date: Tue, 24 Mar 2026 21:34:40 +0530 Subject: [PATCH 1/6] add -check flag to verify generated files are up to date in all gen --- github/gen-accessors.go | 22 ++++++++++++++++++ github/gen-iterators.go | 25 +++++++++++++++++++- github/gen-stringify-test.go | 29 +++++++++++++++++------ script/generate.sh | 45 ++++-------------------------------- 4 files changed, 72 insertions(+), 49 deletions(-) diff --git a/github/gen-accessors.go b/github/gen-accessors.go index 9b47ce0e197..8644332d232 100644 --- a/github/gen-accessors.go +++ b/github/gen-accessors.go @@ -40,6 +40,7 @@ const ( var ( verbose = flag.Bool("v", false, "Print verbose log messages") + check = flag.Bool("check", false, "check whether generated files are up to date") sourceTmpl = template.Must(template.New("source").Parse(source)) testTmpl = template.Must(template.New("test").Parse(test)) @@ -67,6 +68,10 @@ var ( } ) +func isCheck() bool { + return *check || os.Getenv("CHECK") == "1" +} + func logf(fmt string, args ...any) { if *verbose { log.Printf(fmt, args...) @@ -233,6 +238,23 @@ func (t *templateData) dump() error { return fmt.Errorf("format.Source:\n%v\n%v", buf.String(), err) } + if isCheck() { + logf("Checking %v...", filename) + old, err := os.ReadFile(filename) + if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("Missing file: %v\n", t.filename) + } else { + return err + } + } + + if !bytes.Equal(old, clean) { + return fmt.Errorf("Generated files are out of date. Please run go generate ./... and commit the results") + } + return nil + } + logf("Writing %v...", filename) if err := os.Chmod(filename, 0o644); err != nil { return fmt.Errorf("os.Chmod(%q, 0644): %v", filename, err) diff --git a/github/gen-iterators.go b/github/gen-iterators.go index 8460c091d5b..fc6d7f580c9 100644 --- a/github/gen-iterators.go +++ b/github/gen-iterators.go @@ -35,6 +35,7 @@ const ( var ( verbose = flag.Bool("v", false, "Print verbose log messages") + check = flag.Bool("check", false, "check whether generated files are up to date") sourceTmpl = template.Must(template.New("source").Funcs(template.FuncMap{ "hasPrefix": strings.HasPrefix, @@ -43,6 +44,10 @@ var ( testTmpl = template.Must(template.New("test").Parse(test)) ) +func isCheck() bool { + return *check || os.Getenv("CHECK") == "1" +} + func logf(fmt string, args ...any) { if *verbose { log.Printf(fmt, args...) @@ -599,8 +604,26 @@ func (t *templateData) dump() error { if err != nil { return fmt.Errorf("format.Source: %v\n%s", err, buf.String()) } + if isCheck() { + logf("Checking %v...", filename) + old, err := os.ReadFile(filename) + if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("Missing file: %v\n", t.filename) + } else { + return err + } + } + + if !bytes.Equal(old, clean) { + return fmt.Errorf("Generated files are out of date. Please run go generate ./... and commit the results") + } + return nil + } + logf("Writing %v...", filename) - return os.WriteFile(filename, clean, 0o644) + err = os.WriteFile(filename, clean, 0o644) + return err } if err := processTemplate(sourceTmpl, t.filename); err != nil { diff --git a/github/gen-stringify-test.go b/github/gen-stringify-test.go index 3f31caf8a92..1c21ddb8cd8 100644 --- a/github/gen-stringify-test.go +++ b/github/gen-stringify-test.go @@ -37,6 +37,7 @@ const ( var ( verbose = flag.Bool("v", false, "Print verbose log messages") + check = flag.Bool("check", false, "check whether generated files are up to date") // skipStructMethods lists "struct.method" combos to skip. skipStructMethods = map[string]bool{} @@ -83,6 +84,10 @@ var ( sourceTmpl = template.Must(template.New("source").Funcs(funcMap).Parse(source)) ) +func isCheck() bool { + return *check || os.Getenv("CHECK") == "1" +} + func main() { flag.Parse() fset := token.NewFileSet() @@ -353,19 +358,29 @@ func (t *templateData) dump() error { return err } - logf("Writing %v...", t.filename) - if err := os.Chmod(t.filename, 0o644); err != nil { - return fmt.Errorf("os.Chmod(%q, 0644): %v", t.filename, err) + if isCheck() { + logf("Checking %v...", t.filename) + old, err := os.ReadFile(t.filename) + if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("Missing file: %v\n", t.filename) + } else { + return err + } + } + + if !bytes.Equal(old, clean) { + return fmt.Errorf("Generated files are out of date. Please run go generate ./... and commit the results") + } + return nil } + logf("Writing %v...", t.filename) + if err := os.WriteFile(t.filename, clean, 0o444); err != nil { return err } - if err := os.Chmod(t.filename, 0o444); err != nil { - return fmt.Errorf("os.Chmod(%q, 0444): %v", t.filename, err) - } - return nil } diff --git a/script/generate.sh b/script/generate.sh index 2c34e002337..4dfc25cbe1c 100755 --- a/script/generate.sh +++ b/script/generate.sh @@ -1,5 +1,5 @@ #!/bin/sh -#/ `script/generate.sh` runs `go generate` on all modules in this repo. +#/ `script/generate.sh` runs `go generate` on repo. #/ It also runs `script/run-check-structfield-settings.sh -fix` to keep linter #/ exceptions in `.golangci.yml` up to date. #/ `script/generate.sh --check` checks that the generated files are up to date. @@ -9,46 +9,9 @@ set -e CDPATH="" cd -- "$(dirname -- "$0")/.." if [ "$1" = "--check" ]; then - GENTEMP="$(mktemp -d)" - git worktree add -q --detach "$GENTEMP" - trap 'git worktree remove -f "$GENTEMP"; rm -rf "$GENTEMP"' EXIT - git diff --name-only --diff-filter=D --no-renames HEAD | while read -r f; do - rm -f "$GENTEMP/$f" - done - git ls-files -com --exclude-standard | while read -r f; do - target="$GENTEMP/$f" - mkdir -p "$(dirname -- "$target")" - cp "$f" "$target" - done - if [ -f "$(pwd)"/bin ]; then - ln -s "$(pwd)"/bin "$GENTEMP"/bin - fi - ( - cd "$GENTEMP" - git add . - git -c user.name='bot' -c user.email='bot@localhost' -c commit.gpgsign=false commit -m "generate" -q --allow-empty - script/generate.sh - [ -z "$(git status --porcelain)" ] || { - msg="Generated files are out of date. Please run script/generate.sh and commit the results" - if [ -n "$GITHUB_ACTIONS" ]; then - echo "::error ::$msg" - else - echo "$msg" 1>&2 - fi - git diff - exit 1 - } - ) - exit 0 + export CHECK=1 fi -MOD_DIRS="$(git ls-files '*go.mod' | xargs dirname | sort)" +go generate ./... -for dir in $MOD_DIRS; do - ( - cd "$dir" - go generate ./... - go mod tidy - ) -done -script/run-check-structfield-settings.sh -fix +script/run-check-structfield-settings.sh -fix \ No newline at end of file From 31da5e600d934915db888c3b95eaddd6c3cbf291 Mon Sep 17 00:00:00 2001 From: Dhananjay Mishra Date: Tue, 24 Mar 2026 21:38:48 +0530 Subject: [PATCH 2/6] fix --- github/gen-stringify-test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/github/gen-stringify-test.go b/github/gen-stringify-test.go index 1c21ddb8cd8..d81a1b5c2b4 100644 --- a/github/gen-stringify-test.go +++ b/github/gen-stringify-test.go @@ -376,11 +376,18 @@ func (t *templateData) dump() error { } logf("Writing %v...", t.filename) + if err := os.Chmod(t.filename, 0o644); err != nil { + return fmt.Errorf("os.Chmod(%q, 0644): %v", t.filename, err) + } if err := os.WriteFile(t.filename, clean, 0o444); err != nil { return err } + if err := os.Chmod(t.filename, 0o444); err != nil { + return fmt.Errorf("os.Chmod(%q, 0444): %v", t.filename, err) + } + return nil } From d1e963c8a2f2b6640a3a1358e38e0a67c608f26b Mon Sep 17 00:00:00 2001 From: Dhananjay Mishra Date: Wed, 25 Mar 2026 18:30:52 +0530 Subject: [PATCH 3/6] update generate.sh --- script/generate.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/script/generate.sh b/script/generate.sh index 4dfc25cbe1c..f9c00a03119 100755 --- a/script/generate.sh +++ b/script/generate.sh @@ -8,10 +8,28 @@ set -e CDPATH="" cd -- "$(dirname -- "$0")/.." +CHECK_MODE=0 if [ "$1" = "--check" ]; then export CHECK=1 + CHECK_MODE=1 fi go generate ./... +MOD_DIRS="$(git ls-files '*go.mod' | xargs dirname | sort)" + +for dir in $MOD_DIRS; do + ( + cd "$dir" + if [ "$CHECK_MODE" = "1" ]; then + if ! go mod tidy -diff; then + echo "go.mod/go.sum are out of date in $dir" + exit 1 + fi + else + go mod tidy + fi + ) +done + script/run-check-structfield-settings.sh -fix \ No newline at end of file From 0632277deb863ae75a625fa905a90b8975f01b87 Mon Sep 17 00:00:00 2001 From: Dhananjay Mishra Date: Thu, 26 Mar 2026 09:21:28 +0530 Subject: [PATCH 4/6] feedback --- github/gen-accessors.go | 11 ++++++----- github/gen-iterators.go | 11 ++++++----- github/gen-stringify-test.go | 9 +++++---- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/github/gen-accessors.go b/github/gen-accessors.go index 8644332d232..c705f471238 100644 --- a/github/gen-accessors.go +++ b/github/gen-accessors.go @@ -21,12 +21,14 @@ package main import ( "bytes" + "errors" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" + "io/fs" "log" "os" "slices" @@ -40,7 +42,7 @@ const ( var ( verbose = flag.Bool("v", false, "Print verbose log messages") - check = flag.Bool("check", false, "check whether generated files are up to date") + check = flag.Bool("check", false, "Check whether generated files are up to date") sourceTmpl = template.Must(template.New("source").Parse(source)) testTmpl = template.Must(template.New("test").Parse(test)) @@ -242,11 +244,10 @@ func (t *templateData) dump() error { logf("Checking %v...", filename) old, err := os.ReadFile(filename) if err != nil { - if os.IsNotExist(err) { - return fmt.Errorf("Missing file: %v\n", t.filename) - } else { - return err + if errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("Missing file: %v\n", filename) } + return err } if !bytes.Equal(old, clean) { diff --git a/github/gen-iterators.go b/github/gen-iterators.go index fc6d7f580c9..381513e4675 100644 --- a/github/gen-iterators.go +++ b/github/gen-iterators.go @@ -14,12 +14,14 @@ package main import ( "bytes" + "errors" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" + "io/fs" "log" "os" "reflect" @@ -35,7 +37,7 @@ const ( var ( verbose = flag.Bool("v", false, "Print verbose log messages") - check = flag.Bool("check", false, "check whether generated files are up to date") + check = flag.Bool("check", false, "Check whether generated files are up to date") sourceTmpl = template.Must(template.New("source").Funcs(template.FuncMap{ "hasPrefix": strings.HasPrefix, @@ -608,11 +610,10 @@ func (t *templateData) dump() error { logf("Checking %v...", filename) old, err := os.ReadFile(filename) if err != nil { - if os.IsNotExist(err) { - return fmt.Errorf("Missing file: %v\n", t.filename) - } else { - return err + if errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("Missing file: %v\n", filename) } + return err } if !bytes.Equal(old, clean) { diff --git a/github/gen-stringify-test.go b/github/gen-stringify-test.go index d81a1b5c2b4..03663e01a2b 100644 --- a/github/gen-stringify-test.go +++ b/github/gen-stringify-test.go @@ -17,12 +17,14 @@ package main import ( "bytes" + "errors" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" + "io/fs" "log" "os" "strings" @@ -37,7 +39,7 @@ const ( var ( verbose = flag.Bool("v", false, "Print verbose log messages") - check = flag.Bool("check", false, "check whether generated files are up to date") + check = flag.Bool("check", false, "Check whether generated files are up to date") // skipStructMethods lists "struct.method" combos to skip. skipStructMethods = map[string]bool{} @@ -362,11 +364,10 @@ func (t *templateData) dump() error { logf("Checking %v...", t.filename) old, err := os.ReadFile(t.filename) if err != nil { - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { return fmt.Errorf("Missing file: %v\n", t.filename) - } else { - return err } + return err } if !bytes.Equal(old, clean) { From ea5b999f7c89fe5e6542969de7ec622e10c12138 Mon Sep 17 00:00:00 2001 From: Dhananjay Mishra Date: Thu, 26 Mar 2026 17:35:02 +0530 Subject: [PATCH 5/6] add a line --- script/generate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/generate.sh b/script/generate.sh index f9c00a03119..9408ac052b9 100755 --- a/script/generate.sh +++ b/script/generate.sh @@ -32,4 +32,4 @@ for dir in $MOD_DIRS; do ) done -script/run-check-structfield-settings.sh -fix \ No newline at end of file +script/run-check-structfield-settings.sh -fix From b4c6f1445eb807cc0139a8884cc512760cefe21b Mon Sep 17 00:00:00 2001 From: Dhananjay Mishra Date: Thu, 26 Mar 2026 22:52:49 +0530 Subject: [PATCH 6/6] feedback --- github/gen-accessors.go | 2 +- github/gen-iterators.go | 5 ++--- github/gen-stringify-test.go | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/github/gen-accessors.go b/github/gen-accessors.go index c705f471238..aa63bfc16ab 100644 --- a/github/gen-accessors.go +++ b/github/gen-accessors.go @@ -41,8 +41,8 @@ const ( ) var ( - verbose = flag.Bool("v", false, "Print verbose log messages") check = flag.Bool("check", false, "Check whether generated files are up to date") + verbose = flag.Bool("v", false, "Print verbose log messages") sourceTmpl = template.Must(template.New("source").Parse(source)) testTmpl = template.Must(template.New("test").Parse(test)) diff --git a/github/gen-iterators.go b/github/gen-iterators.go index 381513e4675..5830f97ddae 100644 --- a/github/gen-iterators.go +++ b/github/gen-iterators.go @@ -36,8 +36,8 @@ const ( ) var ( - verbose = flag.Bool("v", false, "Print verbose log messages") check = flag.Bool("check", false, "Check whether generated files are up to date") + verbose = flag.Bool("v", false, "Print verbose log messages") sourceTmpl = template.Must(template.New("source").Funcs(template.FuncMap{ "hasPrefix": strings.HasPrefix, @@ -623,8 +623,7 @@ func (t *templateData) dump() error { } logf("Writing %v...", filename) - err = os.WriteFile(filename, clean, 0o644) - return err + return os.WriteFile(filename, clean, 0o644) } if err := processTemplate(sourceTmpl, t.filename); err != nil { diff --git a/github/gen-stringify-test.go b/github/gen-stringify-test.go index 03663e01a2b..ebaea533dfc 100644 --- a/github/gen-stringify-test.go +++ b/github/gen-stringify-test.go @@ -38,8 +38,8 @@ const ( ) var ( - verbose = flag.Bool("v", false, "Print verbose log messages") check = flag.Bool("check", false, "Check whether generated files are up to date") + verbose = flag.Bool("v", false, "Print verbose log messages") // skipStructMethods lists "struct.method" combos to skip. skipStructMethods = map[string]bool{}