From 99b5359db39de62716684e242e18c166ea4342e2 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Thu, 11 Jun 2026 13:28:16 +0200 Subject: [PATCH 1/2] fix(settings-catalog): exclude git-ignored files from catalog scan The scanner walked the filesystem with a hardcoded skip list (.git, bin, vendor) that did not match the repository's .gitignore, so settings.* usages in git-ignored Go files (scratch packages, locally generated code) leaked into the committed catalog and produced non-deterministic diffs referencing ignored paths. Enumerate Go files via `git ls-files --cached --others --exclude-standard` instead, which honours .gitignore. The previous filesystem walk is kept as a fallback for non-git checkouts. Constraint: catalog must be deterministic regardless of untracked artifacts Rejected: parse .gitignore manually | full ignore semantics are error-prone vs deferring to git Confidence: high Scope-risk: narrow Directive: brand-new .go files must be git-added (or not ignored) before their settings appear in the catalog --- cmd/settings-catalog/main.go | 59 ++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/cmd/settings-catalog/main.go b/cmd/settings-catalog/main.go index 55a0a539..5f59531b 100644 --- a/cmd/settings-catalog/main.go +++ b/cmd/settings-catalog/main.go @@ -9,6 +9,7 @@ import ( "go/parser" "go/token" "os" + "os/exec" "path/filepath" "slices" "strconv" @@ -160,6 +161,46 @@ func (s *scanner) scan() (catalog, error) { } func (s *scanner) goFiles() ([]string, error) { + // Prefer git so the catalog never references git-ignored files (the scan + // must be deterministic regardless of untracked artifacts in a working + // copy). Fall back to a filesystem walk when git is unavailable, e.g. when + // scanning a non-git checkout such as a release tarball. + files, err := s.gitGoFiles() + if err != nil { + files, err = s.walkGoFiles() + if err != nil { + return nil, err + } + } + slices.Sort(files) + return files, nil +} + +// gitGoFiles lists the Go files git tracks or would track (excluding files +// matched by .gitignore), honouring the repository's ignore rules. +func (s *scanner) gitGoFiles() ([]string, error) { + // s.root is the -root flag of this developer-run codegen CLI, not untrusted + // input, and the git invocation itself is a fixed argument list. + cmd := exec.Command("git", "-C", s.root, "ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", "*.go") //nolint:gosec // G204: root is an operator-supplied flag, args are fixed + out, err := cmd.Output() + if err != nil { + return nil, err + } + var files []string + for rel := range strings.SplitSeq(string(out), "\x00") { + if rel == "" { + continue + } + path := filepath.Join(s.root, filepath.FromSlash(rel)) + if !s.includeGoFile(path) { + continue + } + files = append(files, path) + } + return files, nil +} + +func (s *scanner) walkGoFiles() ([]string, error) { var files []string err := filepath.WalkDir(s.root, func(path string, d os.DirEntry, err error) error { if err != nil { @@ -173,10 +214,7 @@ func (s *scanner) goFiles() ([]string, error) { } return nil } - if !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") { - return nil - } - if strings.Contains(path, string(filepath.Separator)+"cmd"+string(filepath.Separator)+"settings-catalog"+string(filepath.Separator)) { + if !s.includeGoFile(path) { return nil } files = append(files, path) @@ -185,10 +223,19 @@ func (s *scanner) goFiles() ([]string, error) { if err != nil { return nil, err } - slices.Sort(files) return files, nil } +func (s *scanner) includeGoFile(path string) bool { + if !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") { + return false + } + if strings.Contains(path, string(filepath.Separator)+"cmd"+string(filepath.Separator)+"settings-catalog"+string(filepath.Separator)) { + return false + } + return true +} + func (s *scanner) collectStructs(path string, file *ast.File) { dir := filepath.Dir(path) if _, ok := s.structsByDir[dir]; !ok { @@ -626,7 +673,7 @@ func fieldJSONName(field *ast.Field) string { } func reflectJSONTag(tag string) string { - for _, part := range strings.Split(tag, " ") { + for part := range strings.SplitSeq(tag, " ") { if !strings.HasPrefix(part, `json:"`) { continue } From 9c9aa48f5b2db7b13f1f7c791fe9736dc5fee789 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Thu, 11 Jun 2026 13:32:06 +0200 Subject: [PATCH 2/2] chore: release v3.11.2 Signed-off-by: Sylvain Rabot --- helm/crds/Chart.yaml | 4 ++-- helm/operator/Chart.lock | 6 +++--- helm/operator/Chart.yaml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/helm/crds/Chart.yaml b/helm/crds/Chart.yaml index fd1eab28..28055a65 100644 --- a/helm/crds/Chart.yaml +++ b/helm/crds/Chart.yaml @@ -13,9 +13,9 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: "3.11.1" +version: "3.11.2" # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "v3.11.1" +appVersion: "v3.11.2" diff --git a/helm/operator/Chart.lock b/helm/operator/Chart.lock index 1f569bfe..31246f38 100644 --- a/helm/operator/Chart.lock +++ b/helm/operator/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: operator-crds repository: file://../crds - version: 3.11.1 -digest: sha256:694f9f1a911da70ce22e9602d0225526fdf748052705a8d6eed60bc8a1a0e96d -generated: "2026-05-28T13:59:42.591525+02:00" + version: 3.11.2 +digest: sha256:7e416f7cb4a639f3191c2fac7650dc46e5b578aefe8c574f81f0ec26d31061f9 +generated: "2026-06-11T13:15:41.750876+02:00" diff --git a/helm/operator/Chart.yaml b/helm/operator/Chart.yaml index 4241e2e9..f5f9aef0 100644 --- a/helm/operator/Chart.yaml +++ b/helm/operator/Chart.yaml @@ -13,12 +13,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: "3.11.1" +version: "3.11.2" # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "v3.11.1" +appVersion: "v3.11.2" dependencies: - name: operator-crds version: "3.X"