From 11e2010aebedf9f495a5c295635df096de7252f7 Mon Sep 17 00:00:00 2001 From: Benoit Tigeot Date: Mon, 31 Aug 2026 21:43:42 +0200 Subject: [PATCH 01/11] refactor: remove per-file decompression size limit (#31748) * refactor: remove per-file decompression size limit Remove MaxDecompressedFileSize as it's no longer necessary after migrating to a maintained JSON schema library (santhosh-tekuri/jsonschema/v6). The original limit was added to protect against vulnerabilities in an unmaintained library. The total decompressed chart size limit (MaxDecompressedChartSize) remains to protect against other attack vectors. Partially resolves #30738 Related: - https://github.com/helm/helm/pull/30743 Signed-off-by: Benoit Tigeot * fix: deprecate MaxDecompressedFileSize instead of removing As Matt suggested we should keep the variable until v5 as it can be used because it is public. Related: - https://github.com/helm/helm/pull/31748#discussion_r2738518696 Signed-off-by: Benoit Tigeot * fix: enforce aggregate size budget on directory loading Directory-based chart loading (`LoadDir`) used unbounded `os.ReadFile` calls with no total size check. Archive loading already enforces `MaxDecompressedChartSize` via a remaining-byte budget but directory loading did not, leaving local charts and `file://` dependencies as an unbounded memory path. Add `ReadFileWithBudget` in the archive package and use it in both v2 and v3 directory loaders so they track the same aggregate budget. Ref: https://github.com/helm/helm/pull/31748#issuecomment-4138927643 Signed-off-by: Benoit Tigeot * fix: cap directory budget reads with LimitReader Use `os.Open` + `io.LimitReader` instead of `os.ReadFile` in `ReadFileWithBudget` so a file that grows between stat and read cannot allocate unbounded memory. Also fix `MaxDecompressedFileSize` doc comment to reflect it is unused/deprecated, add nil guard on remaining, and check `os.Stat` errors in tests. Signed-off-by: Benoit Tigeot * test: add v3 directory loader budget test Mirror the v2 `TestLoadDirExceedsBudget` test for the v3 loader to prevent budget enforcement regressions in either path. Signed-off-by: Benoit Tigeot * refactor(loader): make read budget configurable Follow recommendations from https://github.com/helm/helm/pull/31748#discussion_r3058581419 Signed-off-by: Benoit Tigeot * fix(loader): export BudgetedReader for cross-package use Signed-off-by: Benoit Tigeot * fix(loader): rename max param to avoid shadowing built-in Signed-off-by: Benoit Tigeot --------- Signed-off-by: Benoit Tigeot --- internal/chart/v3/loader/directory.go | 11 +- internal/chart/v3/loader/load_test.go | 10 ++ pkg/chart/loader/archive/archive.go | 10 +- pkg/chart/loader/archive/budget.go | 74 ++++++++++++++ pkg/chart/loader/archive/budget_test.go | 128 ++++++++++++++++++++++++ pkg/chart/v2/loader/directory.go | 11 +- pkg/chart/v2/loader/load_test.go | 10 ++ 7 files changed, 238 insertions(+), 16 deletions(-) create mode 100644 pkg/chart/loader/archive/budget.go create mode 100644 pkg/chart/loader/archive/budget_test.go diff --git a/internal/chart/v3/loader/directory.go b/internal/chart/v3/loader/directory.go index 7cf343568..535468dd1 100644 --- a/internal/chart/v3/loader/directory.go +++ b/internal/chart/v3/loader/directory.go @@ -43,6 +43,10 @@ func (l DirLoader) Load() (*chart.Chart, error) { // // This loads charts only from directories. func LoadDir(dir string) (*chart.Chart, error) { + return loadDir(dir, archive.MaxDecompressedChartSize) +} + +func loadDir(dir string, budget int64) (*chart.Chart, error) { topdir, err := filepath.Abs(dir) if err != nil { return nil, err @@ -64,6 +68,7 @@ func LoadDir(dir string) (*chart.Chart, error) { files := []*archive.BufferedFile{} topdir += string(filepath.Separator) + budgetReader := archive.NewBudgetedReader(budget) walk := func(name string, fi os.FileInfo, err error) error { n := strings.TrimPrefix(name, topdir) @@ -100,11 +105,7 @@ func LoadDir(dir string) (*chart.Chart, error) { return fmt.Errorf("cannot load irregular file %s as it has file mode type bits set", name) } - if fi.Size() > archive.MaxDecompressedFileSize { - return fmt.Errorf("chart file %q is larger than the maximum file size %d", fi.Name(), archive.MaxDecompressedFileSize) - } - - data, err := os.ReadFile(name) + data, err := budgetReader.ReadFileWithBudget(name, fi.Size()) if err != nil { return fmt.Errorf("error reading %s: %w", n, err) } diff --git a/internal/chart/v3/loader/load_test.go b/internal/chart/v3/loader/load_test.go index e34364f39..2163cf4e2 100644 --- a/internal/chart/v3/loader/load_test.go +++ b/internal/chart/v3/loader/load_test.go @@ -50,6 +50,16 @@ func TestLoadDir(t *testing.T) { verifyDependenciesLock(t, c) } +func TestLoadDirExceedsBudget(t *testing.T) { + _, err := loadDir("testdata/frobnitz", 1) + if err == nil { + t.Fatal("expected error when chart directory exceeds budget") + } + if !strings.Contains(err.Error(), "chart exceeds maximum decompressed size") { + t.Fatalf("unexpected error: %v", err) + } +} + func TestLoadDirWithDevNull(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("test only works on unix systems with /dev/null present") diff --git a/pkg/chart/loader/archive/archive.go b/pkg/chart/loader/archive/archive.go index a35c0152d..633871bcc 100644 --- a/pkg/chart/loader/archive/archive.go +++ b/pkg/chart/loader/archive/archive.go @@ -37,8 +37,10 @@ import ( // The default value is 100 MiB. var MaxDecompressedChartSize int64 = 100 * 1024 * 1024 // Default 100 MiB -// MaxDecompressedFileSize is the size of the largest file that Helm will attempt to load. -// The size of the file is the decompressed version of it when it is stored in an archive. +// MaxDecompressedFileSize was the per-file size limit enforced during chart loading. +// It is no longer used internally; aggregate chart size is enforced via MaxDecompressedChartSize. +// +// Deprecated: Retained for backward compatibility with external callers. Will be removed in Helm v5. var MaxDecompressedFileSize int64 = 5 * 1024 * 1024 // Default 5 MiB var drivePathPattern = regexp.MustCompile(`^[a-zA-Z]:/`) @@ -128,10 +130,6 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) { return nil, fmt.Errorf("decompressed chart is larger than the maximum size %d", MaxDecompressedChartSize) } - if hd.Size > MaxDecompressedFileSize { - return nil, fmt.Errorf("decompressed chart file %q is larger than the maximum file size %d", hd.Name, MaxDecompressedFileSize) - } - limitedReader := io.LimitReader(tr, remainingSize) bytesWritten, err := io.Copy(b, limitedReader) diff --git a/pkg/chart/loader/archive/budget.go b/pkg/chart/loader/archive/budget.go new file mode 100644 index 000000000..3f9b90e4a --- /dev/null +++ b/pkg/chart/loader/archive/budget.go @@ -0,0 +1,74 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package archive + +import ( + "fmt" + "io" + "math" + "os" +) + +// BudgetedReader tracks cumulative file reads against a size limit. +type BudgetedReader struct { + max int64 + remaining int64 +} + +// NewBudgetedReader creates a BudgetedReader with the given maximum total size. +// The remaining budget is initialized to the maximum. +func NewBudgetedReader(limit int64) *BudgetedReader { + return &BudgetedReader{ + max: limit, + remaining: limit, + } +} + +// ReadFileWithBudget reads a file and decrements the remaining budget by the bytes read. +// It returns an error if the total would exceed the configured maximum. +// The read is capped via io.LimitReader so a file that grows between stat +// and read cannot cause unbounded memory allocation. +func (r *BudgetedReader) ReadFileWithBudget(path string, size int64) ([]byte, error) { + if size > r.remaining { + return nil, fmt.Errorf("chart exceeds maximum decompressed size of %d bytes", r.max) + } + + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + // Read at most r.remaining+1 bytes so we can detect over-budget without + // allocating unbounded memory if the file grew since stat. + // Clamp to avoid int64 overflow when r.remaining is near math.MaxInt64. + limit := r.remaining + if limit < math.MaxInt64 { + limit++ + } + data, err := io.ReadAll(io.LimitReader(f, limit)) + if err != nil { + return nil, err + } + + if int64(len(data)) > r.remaining { + return nil, fmt.Errorf("chart exceeds maximum decompressed size of %d bytes", r.max) + } + + r.remaining -= int64(len(data)) + return data, nil +} diff --git a/pkg/chart/loader/archive/budget_test.go b/pkg/chart/loader/archive/budget_test.go new file mode 100644 index 000000000..f37f78687 --- /dev/null +++ b/pkg/chart/loader/archive/budget_test.go @@ -0,0 +1,128 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package archive + +import ( + "fmt" + "os" + "path/filepath" + "testing" +) + +func TestReadFileWithBudget(t *testing.T) { + dir := t.TempDir() + + writeFile := func(t *testing.T, name string, size int) string { + t.Helper() + p := filepath.Join(dir, name) + if err := os.WriteFile(p, make([]byte, size), 0644); err != nil { + t.Fatal(err) + } + return p + } + + tcs := []struct { + name string + check func(t *testing.T) + }{ + { + name: "reads file and decrements budget", + check: func(t *testing.T) { + t.Helper() + p := writeFile(t, "small.txt", 100) + fi, err := os.Stat(p) + if err != nil { + t.Fatalf("failed to stat %s: %v", p, err) + } + limit := int64(1000) + + br := NewBudgetedReader(limit) + data, err := br.ReadFileWithBudget(p, fi.Size()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(data) != 100 { + t.Fatalf("expected 100 bytes, got %d", len(data)) + } + if br.remaining != 900 { + t.Fatalf("expected remaining=900, got %d", br.remaining) + } + }, + }, + { + name: "rejects file exceeding budget", + check: func(t *testing.T) { + t.Helper() + p := writeFile(t, "big.txt", 500) + fi, err := os.Stat(p) + if err != nil { + t.Fatalf("failed to stat %s: %v", p, err) + } + limit := int64(100) + + br := NewBudgetedReader(limit) + _, err = br.ReadFileWithBudget(p, fi.Size()) + if err == nil { + t.Fatal("expected error for file exceeding budget") + } + expectedErr := fmt.Sprintf("chart exceeds maximum decompressed size of %d bytes", limit) + if err.Error() != expectedErr { + t.Fatalf("expected %q, got %q", expectedErr, err.Error()) + } + if br.remaining != 100 { + t.Fatalf("budget should not change on rejection, got %d", br.remaining) + } + }, + }, + { + name: "tracks budget across multiple reads", + check: func(t *testing.T) { + t.Helper() + remaining := int64(250) + + br := NewBudgetedReader(remaining) + for i := range 3 { + p := writeFile(t, fmt.Sprintf("f%d.txt", i), 80) + fi, err := os.Stat(p) + if err != nil { + t.Fatalf("failed to stat %s: %v", p, err) + } + if _, err := br.ReadFileWithBudget(p, fi.Size()); err != nil { + t.Fatalf("read %d: unexpected error: %v", i, err) + } + } + if br.remaining != 10 { + t.Fatalf("expected remaining=10, got %d", br.remaining) + } + + p := writeFile(t, "over.txt", 20) + fi, err := os.Stat(p) + if err != nil { + t.Fatalf("failed to stat %s: %v", p, err) + } + _, err = br.ReadFileWithBudget(p, fi.Size()) + if err == nil { + t.Fatal("expected error when cumulative reads exceed budget") + } + }, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, tc.check) + } +} diff --git a/pkg/chart/v2/loader/directory.go b/pkg/chart/v2/loader/directory.go index a609ecbbf..bfc649f2a 100644 --- a/pkg/chart/v2/loader/directory.go +++ b/pkg/chart/v2/loader/directory.go @@ -43,6 +43,10 @@ func (l DirLoader) Load() (*chart.Chart, error) { // // This loads charts only from directories. func LoadDir(dir string) (*chart.Chart, error) { + return loadDir(dir, archive.MaxDecompressedChartSize) +} + +func loadDir(dir string, budget int64) (*chart.Chart, error) { topdir, err := filepath.Abs(dir) if err != nil { return nil, err @@ -64,6 +68,7 @@ func LoadDir(dir string) (*chart.Chart, error) { files := []*archive.BufferedFile{} topdir += string(filepath.Separator) + budgetReader := archive.NewBudgetedReader(budget) walk := func(name string, fi os.FileInfo, err error) error { n := strings.TrimPrefix(name, topdir) @@ -100,11 +105,7 @@ func LoadDir(dir string) (*chart.Chart, error) { return fmt.Errorf("cannot load irregular file %s as it has file mode type bits set", name) } - if fi.Size() > archive.MaxDecompressedFileSize { - return fmt.Errorf("chart file %q is larger than the maximum file size %d", fi.Name(), archive.MaxDecompressedFileSize) - } - - data, err := os.ReadFile(name) + data, err := budgetReader.ReadFileWithBudget(name, fi.Size()) if err != nil { return fmt.Errorf("error reading %s: %w", n, err) } diff --git a/pkg/chart/v2/loader/load_test.go b/pkg/chart/v2/loader/load_test.go index ae1da1130..5af88b341 100644 --- a/pkg/chart/v2/loader/load_test.go +++ b/pkg/chart/v2/loader/load_test.go @@ -50,6 +50,16 @@ func TestLoadDir(t *testing.T) { verifyDependenciesLock(t, c) } +func TestLoadDirExceedsBudget(t *testing.T) { + _, err := loadDir("testdata/frobnitz", 1) + if err == nil { + t.Fatal("expected error when chart directory exceeds budget") + } + if !strings.Contains(err.Error(), "chart exceeds maximum decompressed size") { + t.Fatalf("unexpected error: %v", err) + } +} + func TestLoadDirWithDevNull(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("test only works on unix systems with /dev/null present") From 9a3c040369361678aef1ab251e83a38b455f5159 Mon Sep 17 00:00:00 2001 From: Aaron Mark <64331623+amarkdotdev@users.noreply.github.com> Date: Mon, 31 Aug 2026 22:50:46 +0300 Subject: [PATCH 02/11] fix(template): regression - route registry messages to stderr in template and show (#32217) * fix: route registry messages to stderr in template and show When pulling an OCI chart, the registry client prints "Pulled: ..." and "Digest: ..." status lines (and deprecation/underscore warnings) to its configured output writer. Since v4.2.1 (introduced by #32056), these messages leaked into the stdout output of helm template and helm show, breaking downstream consumers such as cdk8s and other YAML parsers. Fix by passing the command's stderr to the registry client in the template and show commands instead of stdout. This keeps stdout clean for machine-readable YAML while still surfacing registry warnings and status messages on stderr for troubleshooting, rather than discarding them. The pull/push commands continue to print these messages on their normal output writer. The show command's addRegistryClient writer parameter is renamed to registryOut and wired through to the registry client, so it is no longer a no-op. Fixes #32215 Signed-off-by: amarkdotdev * test(cmd): cover registry client stderr routing via OCI pull Exercise helm template and helm show against an in-process OCI registry (repotest.NewOCIServer) and assert Pulled:/Digest: status lines appear on stderr only, keeping stdout free of registry noise. Signed-off-by: amarkdotdev * test(cmd): drop weak addRegistryClient unit test OCI pull coverage already asserts Pulled/Digest land on stderr, not stdout. Signed-off-by: amarkdotdev --------- Signed-off-by: amarkdotdev Co-authored-by: amarkdotdev --- pkg/cmd/registry_output_test.go | 109 ++++++++++++++++++++++++++++++++ pkg/cmd/show.go | 24 +++---- pkg/cmd/template.go | 2 +- 3 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 pkg/cmd/registry_output_test.go diff --git a/pkg/cmd/registry_output_test.go b/pkg/cmd/registry_output_test.go new file mode 100644 index 000000000..77682a4c4 --- /dev/null +++ b/pkg/cmd/registry_output_test.go @@ -0,0 +1,109 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "bytes" + "fmt" + "io" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "helm.sh/helm/v4/pkg/action" + "helm.sh/helm/v4/pkg/chart/common" + kubefake "helm.sh/helm/v4/pkg/kube/fake" + "helm.sh/helm/v4/pkg/repo/v1/repotest" +) + +func TestTemplateOCIRegistryMessagesNotOnStdout(t *testing.T) { + defer resetEnv()() + + stdout, stderr := runOCIChartCommand(t, func(ref, registryConfig, contentCache string) []string { + return []string{ + "template", "release-name", ref, + "--version", "0.1.0", + "--plain-http", + "--registry-config", registryConfig, + "--content-cache", contentCache, + } + }) + + require.NotEmpty(t, stdout) + require.NotContains(t, stdout, "Pulled:") + require.NotContains(t, stdout, "Digest:") + require.Contains(t, stderr, "Pulled:") + require.Contains(t, stderr, "Digest:") +} + +func TestShowOCIRegistryMessagesNotOnStdout(t *testing.T) { + defer resetEnv()() + + stdout, stderr := runOCIChartCommand(t, func(ref, registryConfig, contentCache string) []string { + return []string{ + "show", "chart", ref, + "--version", "0.1.0", + "--plain-http", + "--registry-config", registryConfig, + "--content-cache", contentCache, + } + }) + + require.NotEmpty(t, stdout) + require.Contains(t, stdout, "name: oci-dependent-chart") + require.NotContains(t, stdout, "Pulled:") + require.NotContains(t, stdout, "Digest:") + require.Contains(t, stderr, "Pulled:") + require.Contains(t, stderr, "Digest:") +} + +func runOCIChartCommand(t *testing.T, argsFn func(ref, registryConfig, contentCache string) []string) (string, string) { + t.Helper() + + srv := repotest.NewTempServer( + t, + repotest.WithChartSourceGlob("testdata/testcharts/*.tgz*"), + ) + t.Cleanup(func() { srv.Stop() }) + + ociSrv, err := repotest.NewOCIServer(t, srv.Root()) + require.NoError(t, err) + ociSrv.Run(t) + + ref := fmt.Sprintf("oci://%s/u/ocitestuser/oci-dependent-chart", ociSrv.RegistryURL) + registryConfig := filepath.Join(srv.Root(), "config.json") + contentCache := t.TempDir() + args := argsFn(ref, registryConfig, contentCache) + + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + actionConfig := &action.Configuration{ + Releases: storageFixture(), + KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard}, + Capabilities: common.DefaultCapabilities, + } + + root, err := newRootCmdWithConfig(actionConfig, stdout, args, SetupLogging) + require.NoError(t, err) + root.SetOut(stdout) + root.SetErr(stderr) + root.SetArgs(args) + + require.NoError(t, root.Execute(), "stdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String()) + return stdout.String(), stderr.String() +} diff --git a/pkg/cmd/show.go b/pkg/cmd/show.go index 8252d933e..161a38723 100644 --- a/pkg/cmd/show.go +++ b/pkg/cmd/show.go @@ -82,9 +82,9 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Long: showAllDesc, Args: require.ExactArgs(1), ValidArgsFunction: validArgsFunc, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { client.OutputFormat = action.ShowAll - err := addRegistryClient(out, client) + err := addRegistryClient(cmd.ErrOrStderr(), client) if err != nil { return err } @@ -103,9 +103,9 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Long: showValuesDesc, Args: require.ExactArgs(1), ValidArgsFunction: validArgsFunc, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { client.OutputFormat = action.ShowValues - err := addRegistryClient(out, client) + err := addRegistryClient(cmd.ErrOrStderr(), client) if err != nil { return err } @@ -124,9 +124,9 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Long: showChartDesc, Args: require.ExactArgs(1), ValidArgsFunction: validArgsFunc, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { client.OutputFormat = action.ShowChart - err := addRegistryClient(out, client) + err := addRegistryClient(cmd.ErrOrStderr(), client) if err != nil { return err } @@ -145,9 +145,9 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Long: readmeChartDesc, Args: require.ExactArgs(1), ValidArgsFunction: validArgsFunc, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { client.OutputFormat = action.ShowReadme - err := addRegistryClient(out, client) + err := addRegistryClient(cmd.ErrOrStderr(), client) if err != nil { return err } @@ -166,9 +166,9 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Long: showCRDsDesc, Args: require.ExactArgs(1), ValidArgsFunction: validArgsFunc, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { client.OutputFormat = action.ShowCRDs - err := addRegistryClient(out, client) + err := addRegistryClient(cmd.ErrOrStderr(), client) if err != nil { return err } @@ -224,8 +224,8 @@ func runShow(args []string, client *action.Show) (string, error) { return client.Run(cp) } -func addRegistryClient(out io.Writer, client *action.Show) error { - registryClient, err := newRegistryClient(out, client.CertFile, client.KeyFile, client.CaFile, +func addRegistryClient(registryOut io.Writer, client *action.Show) error { + registryClient, err := newRegistryClient(registryOut, client.CertFile, client.KeyFile, client.CaFile, client.InsecureSkipTLSVerify, client.PlainHTTP, client.Username, client.Password) if err != nil { return fmt.Errorf("missing registry client: %w", err) diff --git a/pkg/cmd/template.go b/pkg/cmd/template.go index 29839b871..bb0f9036a 100644 --- a/pkg/cmd/template.go +++ b/pkg/cmd/template.go @@ -85,7 +85,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client.KubeVersion = parsedKubeVersion } - registryClient, err := newRegistryClient(out, client.CertFile, client.KeyFile, client.CaFile, + registryClient, err := newRegistryClient(cmd.ErrOrStderr(), client.CertFile, client.KeyFile, client.CaFile, client.InsecureSkipTLSVerify, client.PlainHTTP, client.Username, client.Password) if err != nil { return fmt.Errorf("missing registry client: %w", err) From 4dfbaa40c6cd67e1df345889113a7879ec66136c Mon Sep 17 00:00:00 2001 From: George Jenkins Date: Mon, 31 Aug 2026 12:58:34 -0700 Subject: [PATCH 03/11] Remove deprecated `internal/chart/v3/` code (#32365) Signed-off-by: George Jenkins --- internal/chart/v3/util/create.go | 11 +- internal/chart/v3/util/create_test.go | 10 +- internal/chart/v3/util/validate_name.go | 110 ------------------- internal/chart/v3/util/validate_name_test.go | 93 ---------------- pkg/cmd/create.go | 5 +- 5 files changed, 11 insertions(+), 218 deletions(-) delete mode 100644 internal/chart/v3/util/validate_name.go delete mode 100644 internal/chart/v3/util/validate_name_test.go diff --git a/internal/chart/v3/util/create.go b/internal/chart/v3/util/create.go index dcb5bbb39..0c143615e 100644 --- a/internal/chart/v3/util/create.go +++ b/internal/chart/v3/util/create.go @@ -18,7 +18,7 @@ package util import ( "fmt" - "io" + "log/slog" "os" "path/filepath" "regexp" @@ -642,12 +642,6 @@ spec: restartPolicy: Never ` -// Stderr is an io.Writer to which error messages can be written -// -// In Helm 4, this will be replaced. It is needed in Helm 3 to preserve API backward -// compatibility. -var Stderr io.Writer = os.Stderr - // CreateFrom creates a new chart, but scaffolds it from the src chart. func CreateFrom(chartfile *chart.Metadata, dest, src string) error { schart, err := loader.Load(src) @@ -795,8 +789,7 @@ func Create(name, dir string) (string, error) { for _, file := range files { if _, err := os.Stat(file.path); err == nil { - // There is no handle to a preferred output stream here. - fmt.Fprintf(Stderr, "WARNING: File %q already exists. Overwriting.\n", file.path) + slog.Warn("Overwriting existing file", slog.String("file", file.path)) } if err := writeFile(file.path, file.content); err != nil { return cdir, err diff --git a/internal/chart/v3/util/create_test.go b/internal/chart/v3/util/create_test.go index ddbbf6216..a227e4e7c 100644 --- a/internal/chart/v3/util/create_test.go +++ b/internal/chart/v3/util/create_test.go @@ -18,6 +18,7 @@ package util import ( "bytes" + "log/slog" "os" "path/filepath" "testing" @@ -98,7 +99,11 @@ func TestCreateFrom(t *testing.T) { func TestCreate_Overwrite(t *testing.T) { tdir := t.TempDir() - var errlog bytes.Buffer + prev := slog.Default() + t.Cleanup(func() { slog.SetDefault(prev) }) + + var logBuf bytes.Buffer + slog.SetDefault(slog.New(slog.NewJSONHandler(&logBuf, nil))) _, err := Create("foo", tdir) require.NoError(t, err) @@ -109,7 +114,6 @@ func TestCreate_Overwrite(t *testing.T) { writeFile(tplname, []byte("FOO")) // Now re-run the create - Stderr = &errlog _, err = Create("foo", tdir) require.NoError(t, err) @@ -118,7 +122,7 @@ func TestCreate_Overwrite(t *testing.T) { require.NotEqual(t, "FOO", string(data), "File that should have been modified was not.") - assert.NotEqual(t, 0, errlog.Len(), "Expected warnings about overwriting files.") + assert.NotEqual(t, 0, logBuf.Len(), "Expected warnings about overwriting files.") } func TestValidateChartName(t *testing.T) { diff --git a/internal/chart/v3/util/validate_name.go b/internal/chart/v3/util/validate_name.go deleted file mode 100644 index 7d85a5b88..000000000 --- a/internal/chart/v3/util/validate_name.go +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "errors" - "fmt" - "regexp" -) - -// validName is a regular expression for resource names. -// -// According to the Kubernetes help text, the regular expression it uses is: -// -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// -// This follows the above regular expression (but requires a full string match, not partial). -// -// The Kubernetes documentation is here, though it is not entirely correct: -// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -var validName = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`) - -var ( - // errMissingName indicates that a release (name) was not provided. - errMissingName = errors.New("no name provided") - - // errInvalidName indicates that an invalid release name was provided - errInvalidName = fmt.Errorf( - "invalid release name, must match regex %s and the length must not be longer than 53", - validName.String()) - - // errInvalidKubernetesName indicates that the name does not meet the Kubernetes - // restrictions on metadata names. - errInvalidKubernetesName = fmt.Errorf( - "invalid metadata name, must match regex %s and the length must not be longer than 253", - validName.String()) -) - -const ( - // According to the Kubernetes docs (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#rfc-1035-label-names) - // some resource names have a max length of 63 characters while others have a max - // length of 253 characters. As we cannot be sure the resources used in a chart, we - // therefore need to limit it to 63 chars and reserve 10 chars for additional part to name - // of the resource. The reason is that chart maintainers can use release name as part of - // the resource name (and some additional chars). - maxReleaseNameLen = 53 - // maxMetadataNameLen is the maximum length Kubernetes allows for any name. - maxMetadataNameLen = 253 -) - -// ValidateReleaseName performs checks for an entry for a Helm release name -// -// For Helm to allow a name, it must be below a certain character count (53) and also match -// a regular expression. -// -// According to the Kubernetes help text, the regular expression it uses is: -// -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// -// This follows the above regular expression (but requires a full string match, not partial). -// -// The Kubernetes documentation is here, though it is not entirely correct: -// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -func ValidateReleaseName(name string) error { - // This case is preserved for backwards compatibility - if name == "" { - return errMissingName - } - if len(name) > maxReleaseNameLen || !validName.MatchString(name) { - return errInvalidName - } - return nil -} - -// ValidateMetadataName validates the name field of a Kubernetes metadata object. -// -// Empty strings, strings longer than 253 chars, or strings that don't match the regexp -// will fail. -// -// According to the Kubernetes help text, the regular expression it uses is: -// -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// -// This follows the above regular expression (but requires a full string match, not partial). -// -// The Kubernetes documentation is here, though it is not entirely correct: -// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -// -// Deprecated: remove in Helm 4. Name validation now uses rules defined in -// pkg/lint/rules.validateMetadataNameFunc() -func ValidateMetadataName(name string) error { - if name == "" || len(name) > maxMetadataNameLen || !validName.MatchString(name) { - return errInvalidKubernetesName - } - return nil -} diff --git a/internal/chart/v3/util/validate_name_test.go b/internal/chart/v3/util/validate_name_test.go deleted file mode 100644 index 3ea768db2..000000000 --- a/internal/chart/v3/util/validate_name_test.go +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -// TestValidateReleaseName is a regression test for ValidateName -// -// Kubernetes has strict naming conventions for resource names. This test represents -// those conventions. -// -// See https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -// -// NOTE: At the time of this writing, the docs above say that names cannot begin with -// digits. However, `kubectl`'s regular expression explicit allows this, and -// Kubernetes (at least as of 1.18) also accepts resources whose names begin with digits. -func TestValidateReleaseName(t *testing.T) { - names := map[string]bool{ - "": false, - "foo": true, - "foo.bar1234baz.seventyone": true, - "FOO": false, - "123baz": true, - "foo.BAR.baz": false, - "one-two": true, - "-two": false, - "one_two": false, - "a..b": false, - "%^&#$%*@^*@&#^": false, - "example:com": false, - "example%%com": false, - "a1111111111111111111111111111111111111111111111111111111111z": false, - } - for input, expectPass := range names { - err := ValidateReleaseName(input) - if expectPass { - assert.NoErrorf(t, err, "Expected release name %q to pass validation", input) - } else { - assert.Errorf(t, err, "Expected release name %q to fail validation, but it passed", input) - } - } -} - -func TestValidateMetadataName(t *testing.T) { - names := map[string]bool{ - "": false, - "foo": true, - "foo.bar1234baz.seventyone": true, - "FOO": false, - "123baz": true, - "foo.BAR.baz": false, - "one-two": true, - "-two": false, - "one_two": false, - "a..b": false, - "%^&#$%*@^*@&#^": false, - "example:com": false, - "example%%com": false, - "a1111111111111111111111111111111111111111111111111111111111z": true, - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z": false, - } - for input, expectPass := range names { - err := ValidateMetadataName(input) - if expectPass { - assert.NoError(t, err, "Expected %q to succeed", input) - } else { - assert.Error(t, err, "Expected %q to fail", input) - } - } -} diff --git a/pkg/cmd/create.go b/pkg/cmd/create.go index b38ce6a12..f7abb20dc 100644 --- a/pkg/cmd/create.go +++ b/pkg/cmd/create.go @@ -104,7 +104,7 @@ func (o *createOptions) run(out io.Writer) error { if !gates.ChartV3.IsEnabled() { return gates.ChartV3.Error() } - return o.createV3Chart(out) + return o.createV3Chart() default: return fmt.Errorf("unsupported chart API version: %s (supported: v2, v3)", o.chartAPIVersion) } @@ -136,7 +136,7 @@ func (o *createOptions) createV2Chart(out io.Writer) error { return err } -func (o *createOptions) createV3Chart(out io.Writer) error { +func (o *createOptions) createV3Chart() error { chartname := filepath.Base(o.name) cfile := &chartv3.Metadata{ Name: chartname, @@ -157,7 +157,6 @@ func (o *createOptions) createV3Chart(out io.Writer) error { return chartutilv3.CreateFrom(cfile, filepath.Dir(o.name), lstarter) } - chartutilv3.Stderr = out _, err := chartutilv3.Create(chartname, filepath.Dir(o.name)) return err } From 28e64bd2ddb5412bff6d94d62b0114bb53f40931 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Mon, 31 Aug 2026 22:06:07 +0200 Subject: [PATCH 04/11] chore: fix gofumpt extra-rules (#32486) * chore: fix gofumpt extra-rules Signed-off-by: Matthieu MOREL * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Matthieu MOREL --------- Signed-off-by: Matthieu MOREL Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .golangci.yml | 4 ++-- internal/plugin/installer/installer.go | 2 +- internal/plugin/installer/plugin_structure.go | 2 +- internal/plugin/runtime_extismv1.go | 2 +- internal/plugin/runtime_subprocess.go | 2 +- internal/plugin/signing_info.go | 2 +- internal/release/v2/util/filter.go | 2 +- internal/release/v2/util/kind_sorter.go | 2 +- internal/test/test.go | 2 +- pkg/action/install.go | 6 +++--- pkg/action/push.go | 2 +- pkg/action/registry_login.go | 2 +- pkg/action/upgrade.go | 4 ++-- pkg/action/validate_test.go | 2 +- pkg/cli/environment.go | 2 +- pkg/cli/output/output.go | 2 +- pkg/cmd/flags.go | 2 +- pkg/cmd/list.go | 2 +- pkg/cmd/pull_test.go | 2 +- pkg/cmd/registry_login.go | 2 +- pkg/cmd/repo_remove_test.go | 4 ++-- pkg/cmd/search_repo.go | 2 +- pkg/cmd/template.go | 2 +- pkg/downloader/manager.go | 17 ++++++----------- pkg/engine/engine.go | 2 +- pkg/engine/funcs.go | 4 ++-- pkg/engine/lookup_func.go | 6 +++--- pkg/kube/client.go | 4 ++-- pkg/kube/ready_test.go | 4 ++-- pkg/registry/chart.go | 2 +- pkg/registry/client.go | 2 +- pkg/registry/plugin.go | 2 +- pkg/release/v1/util/filter.go | 2 +- pkg/release/v1/util/kind_sorter.go | 2 +- pkg/repo/v1/chartrepo.go | 2 +- pkg/storage/driver/labels.go | 2 +- pkg/storage/driver/sql.go | 4 ++-- pkg/storage/driver/sql_test.go | 2 +- 38 files changed, 54 insertions(+), 59 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 9daa85ad5..20036a0b2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,7 +13,7 @@ formatters: gofumpt: module-path: helm.sh/helm/v4 - extra-rules: false + extra-rules: true goimports: local-prefixes: @@ -95,7 +95,6 @@ linters: - exposedSyncMutex - hugeParam - importShadow - - paramTypeCombine - ptrToRefParam - rangeValCopy - todoCommentWithoutDetail @@ -119,6 +118,7 @@ linters: enable-default-rules: true max-open-files: 2048 rules: + - name: bare-return - name: early-return arguments: - "preserve-scope" diff --git a/internal/plugin/installer/installer.go b/internal/plugin/installer/installer.go index 4728879f5..aa43992db 100644 --- a/internal/plugin/installer/installer.go +++ b/internal/plugin/installer/installer.go @@ -153,7 +153,7 @@ func NewForSource(source, version string) (installer Installer, err error) { return installer, fmt.Errorf("cannot get information about plugin source %q (if it's a local directory, does it exist?), last error was: %w", source, err) } - return + return installer, err } // FindSource determines the correct Installer for the given source. diff --git a/internal/plugin/installer/plugin_structure.go b/internal/plugin/installer/plugin_structure.go index 10647141e..ca418ac30 100644 --- a/internal/plugin/installer/plugin_structure.go +++ b/internal/plugin/installer/plugin_structure.go @@ -53,7 +53,7 @@ func detectPluginRoot(extractDir string) (string, error) { // validatePluginName checks if the plugin directory name matches the plugin name // from plugin.yaml when the plugin is in a subdirectory. -func validatePluginName(pluginRoot string, expectedName string) error { +func validatePluginName(pluginRoot, expectedName string) error { // Only validate if plugin is in a subdirectory dirName := filepath.Base(pluginRoot) if dirName == expectedName { diff --git a/internal/plugin/runtime_extismv1.go b/internal/plugin/runtime_extismv1.go index ffa108a08..678fbb564 100644 --- a/internal/plugin/runtime_extismv1.go +++ b/internal/plugin/runtime_extismv1.go @@ -212,7 +212,7 @@ func (p *ExtismV1PluginRuntime) Invoke(ctx context.Context, input *Input) (*Outp return output, nil } -func buildManifest(pluginDir string, tmpDir string, rc *RuntimeConfigExtismV1) (extism.Manifest, error) { +func buildManifest(pluginDir, tmpDir string, rc *RuntimeConfigExtismV1) (extism.Manifest, error) { wasmFile := filepath.Join(pluginDir, ExtismV1WasmBinaryFilename) allowedHosts := rc.AllowedHosts diff --git a/internal/plugin/runtime_subprocess.go b/internal/plugin/runtime_subprocess.go index 9ea69e116..e67d1da9b 100644 --- a/internal/plugin/runtime_subprocess.go +++ b/internal/plugin/runtime_subprocess.go @@ -112,7 +112,7 @@ func (r *SubprocessPluginRuntime) Invoke(ctx context.Context, input *Input) (*Ou // InvokeWithEnv executes a plugin command with custom environment and I/O streams // This method allows execution with different command/args than the plugin's default -func (r *SubprocessPluginRuntime) InvokeWithEnv(main string, argv []string, env []string, stdin io.Reader, stdout, stderr io.Writer) error { +func (r *SubprocessPluginRuntime) InvokeWithEnv(main string, argv, env []string, stdin io.Reader, stdout, stderr io.Writer) error { mainCmdExp := os.ExpandEnv(main) cmd := exec.CommandContext(context.Background(), mainCmdExp, argv...) cmd.Env = slices.Clone(os.Environ()) diff --git a/internal/plugin/signing_info.go b/internal/plugin/signing_info.go index ff27cc02d..8077eb09a 100644 --- a/internal/plugin/signing_info.go +++ b/internal/plugin/signing_info.go @@ -111,7 +111,7 @@ func GetPluginSigningInfo(metadata Metadata) (*SigningInfo, error) { }, nil } -func validateProvenanceHash(blockContent string, tarballPath string) bool { +func validateProvenanceHash(blockContent, tarballPath string) bool { // Parse provenance to get the expected hash _, sums, err := parsePluginMessageBlock([]byte(blockContent)) if err != nil { diff --git a/internal/release/v2/util/filter.go b/internal/release/v2/util/filter.go index 0daf06014..6ad5cce9f 100644 --- a/internal/release/v2/util/filter.go +++ b/internal/release/v2/util/filter.go @@ -41,7 +41,7 @@ func (fn FilterFunc) Filter(rels []*v2.Release) (rets []*v2.Release) { rets = append(rets, rel) } } - return + return rets } // Any returns a FilterFunc that filters a list of releases diff --git a/internal/release/v2/util/kind_sorter.go b/internal/release/v2/util/kind_sorter.go index 950e836fa..4ad1f7fb3 100644 --- a/internal/release/v2/util/kind_sorter.go +++ b/internal/release/v2/util/kind_sorter.go @@ -137,7 +137,7 @@ func sortHooksByKind(hooks []*release.Hook, ordering KindSortOrder) []*release.H return h } -func lessByKind(_ any, _ any, kindA string, kindB string, o KindSortOrder) bool { +func lessByKind(_, _ any, kindA, kindB string, o KindSortOrder) bool { ordering := make(map[string]int, len(o)) for v, k := range o { ordering[k] = v diff --git a/internal/test/test.go b/internal/test/test.go index ba4ea41e7..ceb91ba3a 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -49,7 +49,7 @@ func AssertGoldenString(t TestingT, actual, filename string) { } // AssertGoldenFile asserts that the content of the actual file matches the contents of the expected file -func AssertGoldenFile(t TestingT, actualFileName string, expectedFilename string) { +func AssertGoldenFile(t TestingT, actualFileName, expectedFilename string) { t.Helper() actual, err := os.ReadFile(actualFileName) diff --git a/pkg/action/install.go b/pkg/action/install.go index 605c423bc..6fc919366 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -476,7 +476,7 @@ func (i *Install) RunWithContext(ctx context.Context, ch ci.Charter, vals map[st return rel, err } -func (i *Install) performInstallCtx(ctx context.Context, rel *release.Release, toBeAdopted kube.ResourceList, resources kube.ResourceList) (*release.Release, error) { +func (i *Install) performInstallCtx(ctx context.Context, rel *release.Release, toBeAdopted, resources kube.ResourceList) (*release.Release, error) { type Msg struct { r *release.Release e error @@ -503,7 +503,7 @@ func (i *Install) getGoroutineCount() int32 { return i.goroutineCount.Load() } -func (i *Install) performInstall(rel *release.Release, toBeAdopted kube.ResourceList, resources kube.ResourceList) (*release.Release, error) { +func (i *Install) performInstall(rel *release.Release, toBeAdopted, resources kube.ResourceList) (*release.Release, error) { var err error // pre-install hooks if !i.DisableHooks { @@ -717,7 +717,7 @@ func (i *Install) replaceRelease(rel *release.Release) error { } // write the to /. controls if the file is created or content will be appended -func writeToFile(outputDir string, name string, data string, appendData bool) error { +func writeToFile(outputDir, name, data string, appendData bool) error { outfileName := outputDir + string(filepath.Separator) + name err := ensureDirectoryForFile(outfileName) diff --git a/pkg/action/push.go b/pkg/action/push.go index 0c7148f65..805fdb2dc 100644 --- a/pkg/action/push.go +++ b/pkg/action/push.go @@ -90,7 +90,7 @@ func NewPushWithOpts(opts ...PushOpt) *Push { } // Run executes 'helm push' against the given chart archive. -func (p *Push) Run(chartRef string, remote string) (string, error) { +func (p *Push) Run(chartRef, remote string) (string, error) { var out strings.Builder c := uploader.ChartUploader{ diff --git a/pkg/action/registry_login.go b/pkg/action/registry_login.go index fd9d4bfc6..23bbfd02f 100644 --- a/pkg/action/registry_login.go +++ b/pkg/action/registry_login.go @@ -82,7 +82,7 @@ func NewRegistryLogin(cfg *Configuration) *RegistryLogin { } // Run executes the registry login operation -func (a *RegistryLogin) Run(_ io.Writer, hostname string, username string, password string, opts ...RegistryLoginOpt) error { +func (a *RegistryLogin) Run(_ io.Writer, hostname, username, password string, opts ...RegistryLoginOpt) error { for _, opt := range opts { if err := opt(a); err != nil { return err diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go index 7f66ceefb..85904124b 100644 --- a/pkg/action/upgrade.go +++ b/pkg/action/upgrade.go @@ -453,7 +453,7 @@ func isReleaseApplyMethodClientSideApply(applyMethod string) bool { return applyMethod == "" || applyMethod == string(release.ApplyMethodClientSideApply) } -func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *release.Release, current kube.ResourceList, target kube.ResourceList, originalRelease *release.Release, serverSideApply bool) { +func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *release.Release, current, target kube.ResourceList, originalRelease *release.Release, serverSideApply bool) { // pre-upgrade hooks if !u.DisableHooks { @@ -664,7 +664,7 @@ func mergeCustomLabels(current, desired map[string]string) map[string]string { return labels } -func getUpgradeServerSideValue(serverSideOption string, releaseApplyMethod string) (bool, error) { +func getUpgradeServerSideValue(serverSideOption, releaseApplyMethod string) (bool, error) { switch serverSideOption { case "auto": return releaseApplyMethod == "ssa", nil diff --git a/pkg/action/validate_test.go b/pkg/action/validate_test.go index 8bd9f1916..d33ee683d 100644 --- a/pkg/action/validate_test.go +++ b/pkg/action/validate_test.go @@ -75,7 +75,7 @@ func newMissingDeployment(name, namespace string) *resource.Info { return info } -func newDeploymentWithOwner(name, namespace string, labels map[string]string, annotations map[string]string) *resource.Info { +func newDeploymentWithOwner(name, namespace string, labels, annotations map[string]string) *resource.Info { obj := &appsv1.Deployment{ ObjectMeta: v1.ObjectMeta{ Name: name, diff --git a/pkg/cli/environment.go b/pkg/cli/environment.go index 45d773eb4..b0463d01f 100644 --- a/pkg/cli/environment.go +++ b/pkg/cli/environment.go @@ -219,7 +219,7 @@ func envCSV(name string) (ls []string) { if trimmed != "" { ls = strings.Split(trimmed, ",") } - return + return ls } func envColorMode() string { diff --git a/pkg/cli/output/output.go b/pkg/cli/output/output.go index a9bd846fe..bc4635647 100644 --- a/pkg/cli/output/output.go +++ b/pkg/cli/output/output.go @@ -85,7 +85,7 @@ func ParseFormat(s string) (out Format, err error) { default: out, err = "", ErrInvalidFormatType } - return + return out, err } // Writer is an interface that any type can implement to write supported formats diff --git a/pkg/cmd/flags.go b/pkg/cmd/flags.go index 45da90d0e..61db07883 100644 --- a/pkg/cmd/flags.go +++ b/pkg/cmd/flags.go @@ -268,7 +268,7 @@ func (p *postRendererArgsSlice) GetSlice() []string { return p.options.args } -func compVersionFlag(chartRef string, _ string) ([]string, cobra.ShellCompDirective) { +func compVersionFlag(chartRef, _ string) ([]string, cobra.ShellCompDirective) { chartInfo := strings.Split(chartRef, "/") if len(chartInfo) != 2 { return nil, cobra.ShellCompDirectiveNoFileComp diff --git a/pkg/cmd/list.go b/pkg/cmd/list.go index 54becddca..00465d232 100644 --- a/pkg/cmd/list.go +++ b/pkg/cmd/list.go @@ -155,7 +155,7 @@ type releaseListWriter struct { noColor bool } -func newReleaseListWriter(releases []*release.Release, timeFormat string, noHeaders bool, noColor bool) *releaseListWriter { +func newReleaseListWriter(releases []*release.Release, timeFormat string, noHeaders, noColor bool) *releaseListWriter { // Initialize the array so no results returns an empty array instead of null elements := make([]releaseElement, 0, len(releases)) for _, r := range releases { diff --git a/pkg/cmd/pull_test.go b/pkg/cmd/pull_test.go index a62d6b1b4..aadb63db6 100644 --- a/pkg/cmd/pull_test.go +++ b/pkg/cmd/pull_test.go @@ -268,7 +268,7 @@ func runPullTests(t *testing.T, tests []struct { wantErrorMsg string expectFile string expectDir bool -}, outdir string, additionalFlags string, +}, outdir, additionalFlags string, ) { t.Helper() for _, tt := range tests { diff --git a/pkg/cmd/registry_login.go b/pkg/cmd/registry_login.go index bffc56445..605717e22 100644 --- a/pkg/cmd/registry_login.go +++ b/pkg/cmd/registry_login.go @@ -91,7 +91,7 @@ func newRegistryLoginCmd(cfg *action.Configuration, out io.Writer) *cobra.Comman } // Adapted from https://github.com/oras-project/oras -func getUsernamePassword(usernameOpt string, passwordOpt string, passwordFromStdinOpt bool) (string, string, error) { +func getUsernamePassword(usernameOpt, passwordOpt string, passwordFromStdinOpt bool) (string, string, error) { var err error username := usernameOpt password := passwordOpt diff --git a/pkg/cmd/repo_remove_test.go b/pkg/cmd/repo_remove_test.go index f58bc91d9..2672713a2 100644 --- a/pkg/cmd/repo_remove_test.go +++ b/pkg/cmd/repo_remove_test.go @@ -119,7 +119,7 @@ func TestRepoRemove(t *testing.T) { } } -func createCacheFiles(rootDir string, repoName string) (cacheIndexFile string, cacheChartsFile string) { +func createCacheFiles(rootDir, repoName string) (cacheIndexFile, cacheChartsFile string) { cacheIndexFile = filepath.Join(rootDir, helmpath.CacheIndexFile(repoName)) mf, _ := os.Create(cacheIndexFile) mf.Close() @@ -131,7 +131,7 @@ func createCacheFiles(rootDir string, repoName string) (cacheIndexFile string, c return cacheIndexFile, cacheChartsFile } -func testCacheFiles(t *testing.T, cacheIndexFile string, cacheChartsFile string, repoName string) { +func testCacheFiles(t *testing.T, cacheIndexFile, cacheChartsFile, repoName string) { t.Helper() _, err := os.Stat(cacheIndexFile) require.Errorf(t, err, "Error cache index file was not removed for repository %s", repoName) diff --git a/pkg/cmd/search_repo.go b/pkg/cmd/search_repo.go index 348ca12b6..2d9d967f8 100644 --- a/pkg/cmd/search_repo.go +++ b/pkg/cmd/search_repo.go @@ -268,7 +268,7 @@ func (r *repoSearchWriter) encodeByFormat(out io.Writer, format output.Format) e } // Provides the list of charts that are part of the specified repo, and that starts with 'prefix'. -func compListChartsOfRepo(repoName string, prefix string) []string { +func compListChartsOfRepo(repoName, prefix string) []string { var charts []string path := filepath.Join(settings.RepositoryCache, helmpath.CacheChartsFile(repoName)) diff --git a/pkg/cmd/template.go b/pkg/cmd/template.go index bb0f9036a..5645ab33d 100644 --- a/pkg/cmd/template.go +++ b/pkg/cmd/template.go @@ -238,7 +238,7 @@ func isTestHook(h *release.Hook) bool { // bug introduced by #8156. As part of the todo to refactor renderResources // this duplicate code should be removed. It is added here so that the API // surface area is as minimally impacted as possible in fixing the issue. -func writeToFile(outputDir string, name string, data string, appendData bool) error { +func writeToFile(outputDir, name, data string, appendData bool) error { outfileName := outputDir + string(filepath.Separator) + name err := ensureDirectoryForFile(outfileName) diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index a1fa0ddbd..c4e12e1d2 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -733,22 +733,17 @@ func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]* var entry repo.ChartVersions entry, err = findEntryByName(name, cr) if err != nil { - // TODO: Where linting is skipped in this function we should - // refactor to remove naked returns while ensuring the same - // behavior - //nolint:nakedret - return + // TODO: Consider refactoring this function to reduce the number of returned values while preserving behavior. + return url, username, password, insecureSkipTLSVerify, passCredentialsAll, caFile, certFile, keyFile, err } var ve *repo.ChartVersion ve, err = findVersionedEntry(version, entry) if err != nil { - //nolint:nakedret - return + return url, username, password, insecureSkipTLSVerify, passCredentialsAll, caFile, certFile, keyFile, err } url, err = repo.ResolveReferenceURL(repoURL, ve.URLs[0]) if err != nil { - //nolint:nakedret - return + return url, username, password, insecureSkipTLSVerify, passCredentialsAll, caFile, certFile, keyFile, err } username = cr.Config.Username password = cr.Config.Password @@ -757,8 +752,8 @@ func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]* caFile = cr.Config.CAFile certFile = cr.Config.CertFile keyFile = cr.Config.KeyFile - //nolint:nakedret - return + + return url, username, password, insecureSkipTLSVerify, passCredentialsAll, caFile, certFile, keyFile, err } url, err = repo.FindChartInRepoURL(repoURL, name, m.Getters, repo.WithChartVersion(version), repo.WithClientTLS(certFile, keyFile, caFile)) if err == nil { diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 00bb4be9d..cc5917da2 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -413,7 +413,7 @@ func parseTemplateExecErrorString(s string) (TraceableError, bool) { // Special case: "template: no template %q associated with template %q" // Matches https://cs.opensource.google/go/go/+/refs/tags/go1.23.6:src/text/template/exec.go;l=191 -func parseTemplateNoTemplateError(s string, remainder string) (TraceableError, bool) { +func parseTemplateNoTemplateError(s, remainder string) (TraceableError, bool) { if strings.HasPrefix(remainder, "no template ") { return TraceableError{message: s}, true } diff --git a/pkg/engine/funcs.go b/pkg/engine/funcs.go index 04a48cad3..e876df6c0 100644 --- a/pkg/engine/funcs.go +++ b/pkg/engine/funcs.go @@ -447,7 +447,7 @@ func durationWeeks(v any) float64 { // // v and m accept the same forms as asDuration (e.g. "2h13m", "30s"). // On error, it returns time.Duration(0). If m is invalid, it returns v. -func durationRoundTo(v any, m any) time.Duration { +func durationRoundTo(v, m any) time.Duration { d, err := asDuration(v) if err != nil { return 0 @@ -463,7 +463,7 @@ func durationRoundTo(v any, m any) time.Duration { // Returns a time.Duration. // // On error, it returns time.Duration(0). If m is invalid, it returns v. -func durationTruncateTo(v any, m any) time.Duration { +func durationTruncateTo(v, m any) time.Duration { d, err := asDuration(v) if err != nil { return 0 diff --git a/pkg/engine/lookup_func.go b/pkg/engine/lookup_func.go index b0d0224be..df4925f05 100644 --- a/pkg/engine/lookup_func.go +++ b/pkg/engine/lookup_func.go @@ -30,7 +30,7 @@ import ( "k8s.io/client-go/rest" ) -type lookupFunc = func(apiversion string, resource string, namespace string, name string) (map[string]any, error) +type lookupFunc = func(apiversion, resource, namespace, name string) (map[string]any, error) // NewLookupFunction returns a function for looking up objects in the cluster. // @@ -55,7 +55,7 @@ func (c clientProviderFromConfig) GetClientFor(apiVersion, kind string) (dynamic } func newLookupFunction(ctx context.Context, clientProvider ClientProvider) lookupFunc { - return func(apiversion string, kind string, namespace string, name string) (map[string]any, error) { + return func(apiversion, kind, namespace, name string) (map[string]any, error) { var client dynamic.ResourceInterface c, namespaced, err := clientProvider.GetClientFor(apiversion, kind) if err != nil { @@ -105,7 +105,7 @@ func newLookupFunction(ctx context.Context, clientProvider ClientProvider) looku } // getDynamicClientOnKind returns a dynamic client on an Unstructured type. This client can be further namespaced. -func getDynamicClientOnKind(apiversion string, kind string, config *rest.Config) (dynamic.NamespaceableResourceInterface, bool, error) { +func getDynamicClientOnKind(apiversion, kind string, config *rest.Config) (dynamic.NamespaceableResourceInterface, bool, error) { gvk := schema.FromAPIVersionAndKind(apiversion, kind) apiRes, err := getAPIResourceForGVK(gvk, config) if err != nil { diff --git a/pkg/kube/client.go b/pkg/kube/client.go index ba881c560..03a2761f3 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -1237,8 +1237,8 @@ func upgradeClientSideFieldManager(info *resource.Info, dryRun bool, fieldValida return patched, err } -// Patch reource using server-side apply -func patchResourceServerSide(target *resource.Info, dryRun bool, forceConflicts bool, fieldValidationDirective FieldValidationDirective) error { +// Patch resource using server-side apply +func patchResourceServerSide(target *resource.Info, dryRun, forceConflicts bool, fieldValidationDirective FieldValidationDirective) error { helper := resource.NewHelper( target.Client, target.Mapping). diff --git a/pkg/kube/ready_test.go b/pkg/kube/ready_test.go index c40ad1d4d..f160db75a 100644 --- a/pkg/kube/ready_test.go +++ b/pkg/kube/ready_test.go @@ -1444,7 +1444,7 @@ func newReplicationController(name string, generationInSync bool) *corev1.Replic } } -func newReplicaSet(name string, replicas int, readyReplicas int, generationInSync bool) *appsv1.ReplicaSet { +func newReplicaSet(name string, replicas, readyReplicas int, generationInSync bool) *appsv1.ReplicaSet { d := newDeployment(name, replicas, 0, 0, generationInSync) return &appsv1.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ @@ -1503,7 +1503,7 @@ func newPersistentVolumeClaim(name string, phase corev1.PersistentVolumeClaimPha } } -func newJob(name string, backoffLimit int, completions *int32, succeeded int, failed int) *batchv1.Job { +func newJob(name string, backoffLimit int, completions *int32, succeeded, failed int) *batchv1.Job { return &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: name, diff --git a/pkg/registry/chart.go b/pkg/registry/chart.go index b8b0d88b6..d0f138b18 100644 --- a/pkg/registry/chart.go +++ b/pkg/registry/chart.go @@ -108,7 +108,7 @@ func generateChartOCIAnnotations(meta *chart.Metadata, creationTime string) map[ } // addToMap takes an existing map and adds an item if the value is not empty -func addToMap(inputMap map[string]string, newKey string, newValue string) map[string]string { +func addToMap(inputMap map[string]string, newKey, newValue string) map[string]string { // Add item to map if its if strings.TrimSpace(newValue) != "" { inputMap[newKey] = newValue diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 672f5603a..786342c07 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -276,7 +276,7 @@ func (c *Client) Login(host string, options ...LoginOption) error { } // LoginOptBasicAuth returns a function that sets the username/password settings on login -func LoginOptBasicAuth(username string, password string) LoginOption { +func LoginOptBasicAuth(username, password string) LoginOption { return func(o *loginOperation) { o.client.username = username o.client.password = password diff --git a/pkg/registry/plugin.go b/pkg/registry/plugin.go index 959faaa7d..fa33de60a 100644 --- a/pkg/registry/plugin.go +++ b/pkg/registry/plugin.go @@ -49,7 +49,7 @@ type PluginPullResult struct { } // PullPlugin downloads a plugin from an OCI registry using artifact type -func (c *Client) PullPlugin(ref string, pluginName string, options ...PluginPullOption) (*PluginPullResult, error) { +func (c *Client) PullPlugin(ref, pluginName string, options ...PluginPullOption) (*PluginPullResult, error) { operation := &pluginPullOperation{ pluginName: pluginName, } diff --git a/pkg/release/v1/util/filter.go b/pkg/release/v1/util/filter.go index 88ac995d7..a746a9712 100644 --- a/pkg/release/v1/util/filter.go +++ b/pkg/release/v1/util/filter.go @@ -41,7 +41,7 @@ func (fn FilterFunc) Filter(rels []*rspb.Release) (rets []*rspb.Release) { rets = append(rets, rel) } } - return + return rets } // Any returns a FilterFunc that filters a list of releases diff --git a/pkg/release/v1/util/kind_sorter.go b/pkg/release/v1/util/kind_sorter.go index 01f1f801e..f112fb16e 100644 --- a/pkg/release/v1/util/kind_sorter.go +++ b/pkg/release/v1/util/kind_sorter.go @@ -137,7 +137,7 @@ func sortHooksByKind(hooks []*release.Hook, ordering KindSortOrder) []*release.H return h } -func lessByKind(_ any, _ any, kindA string, kindB string, o KindSortOrder) bool { +func lessByKind(_, _ any, kindA, kindB string, o KindSortOrder) bool { ordering := make(map[string]int, len(o)) for v, k := range o { ordering[k] = v diff --git a/pkg/repo/v1/chartrepo.go b/pkg/repo/v1/chartrepo.go index 42ed52f75..8945528f1 100644 --- a/pkg/repo/v1/chartrepo.go +++ b/pkg/repo/v1/chartrepo.go @@ -172,7 +172,7 @@ func WithInsecureSkipTLSVerify(insecureSkipTLSVerify bool) FindChartInRepoURLOpt // FindChartInRepoURL finds chart in chart repository pointed by repoURL // without adding repo to repositories -func FindChartInRepoURL(repoURL string, chartName string, getters getter.Providers, options ...FindChartInRepoURLOption) (string, error) { +func FindChartInRepoURL(repoURL, chartName string, getters getter.Providers, options ...FindChartInRepoURLOption) (string, error) { opts := findChartInRepoURLOptions{} for _, option := range options { option(&opts) diff --git a/pkg/storage/driver/labels.go b/pkg/storage/driver/labels.go index eb7118fe5..be8262b81 100644 --- a/pkg/storage/driver/labels.go +++ b/pkg/storage/driver/labels.go @@ -27,7 +27,7 @@ func (lbs labels) keys() (ls []string) { for key := range lbs { ls = append(ls, key) } - return + return ls } func (lbs labels) match(set labels) bool { diff --git a/pkg/storage/driver/sql.go b/pkg/storage/driver/sql.go index db076da98..6602f2ee3 100644 --- a/pkg/storage/driver/sql.go +++ b/pkg/storage/driver/sql.go @@ -281,7 +281,7 @@ type SQLReleaseCustomLabelWrapper struct { } // NewSQL initializes a new sql driver. -func NewSQL(connectionString string, namespace string) (*SQL, error) { +func NewSQL(connectionString, namespace string) (*SQL, error) { db, err := sqlx.Connect(postgreSQLDialect, connectionString) if err != nil { return nil, err @@ -690,7 +690,7 @@ func (s *SQL) Delete(key string) (release.Releaser, error) { } // Get release custom labels from database -func (s *SQL) getReleaseCustomLabels(key string, _ string) (map[string]string, error) { +func (s *SQL) getReleaseCustomLabels(key, _ string) (map[string]string, error) { query, args, err := s.statementBuilder. Select(sqlCustomLabelsTableKeyColumn, sqlCustomLabelsTableValueColumn). From(sqlCustomLabelsTableName). diff --git a/pkg/storage/driver/sql_test.go b/pkg/storage/driver/sql_test.go index 044e9df7b..e5fde405b 100644 --- a/pkg/storage/driver/sql_test.go +++ b/pkg/storage/driver/sql_test.go @@ -493,7 +493,7 @@ func TestSqlDelete(t *testing.T) { assert.Equalf(t, rel, deletedRelease, "Expected release {%v}, got {%v}", rel, deletedRelease) } -func mockGetReleaseCustomLabels(mock sqlmock.Sqlmock, key string, namespace string, labels map[string]string) { +func mockGetReleaseCustomLabels(mock sqlmock.Sqlmock, key, namespace string, labels map[string]string) { query := fmt.Sprintf( regexp.QuoteMeta("SELECT %s, %s FROM %s WHERE %s = $1 AND %s = $2"), sqlCustomLabelsTableKeyColumn, From 37752b70b2f9c49dc6ac2f01e2a0aca1f32f0529 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Mon, 31 Aug 2026 22:09:13 +0200 Subject: [PATCH 05/11] refactor(repo): Use byte buffer to build index file (#32579) The string returned by the string builder was cast to a byte slice anyways. Remove this indirection. Also, write directly to the buffer instead of using fmt.Fprintln(...). Signed-off-by: Tom Wieczorek --- pkg/repo/v1/chartrepo.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/repo/v1/chartrepo.go b/pkg/repo/v1/chartrepo.go index 8945528f1..da42128bf 100644 --- a/pkg/repo/v1/chartrepo.go +++ b/pkg/repo/v1/chartrepo.go @@ -104,14 +104,15 @@ func (r *ChartRepository) DownloadIndexFile() (string, error) { } // Create the chart list file in the cache directory - var charts strings.Builder + var charts bytes.Buffer for name := range indexFile.Entries { - fmt.Fprintln(&charts, name) + charts.WriteString(name) + charts.WriteByte('\n') // Terminate each entry with a newline } chartsFile := filepath.Join(r.CachePath, helmpath.CacheChartsFile(r.Config.Name)) os.MkdirAll(filepath.Dir(chartsFile), 0o755) - fileutil.AtomicWriteFile(chartsFile, bytes.NewReader([]byte(charts.String())), 0o644) + fileutil.AtomicWriteFile(chartsFile, &charts, 0o644) // Create the index file in the cache directory fname := filepath.Join(r.CachePath, helmpath.CacheIndexFile(r.Config.Name)) From ca6681ca55d39913b880871b6aa259efdf15e0b9 Mon Sep 17 00:00:00 2001 From: George Jenkins Date: Mon, 31 Aug 2026 13:35:39 -0700 Subject: [PATCH 06/11] chore: Fix independent-merge lint issues Signed-off-by: George Jenkins --- .golangci.yml | 3 ++- pkg/chart/loader/archive/budget_test.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 20036a0b2..ac8a81f0f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,7 +13,8 @@ formatters: gofumpt: module-path: helm.sh/helm/v4 - extra-rules: true + extra: + group-params: true goimports: local-prefixes: diff --git a/pkg/chart/loader/archive/budget_test.go b/pkg/chart/loader/archive/budget_test.go index f37f78687..f8fc6776f 100644 --- a/pkg/chart/loader/archive/budget_test.go +++ b/pkg/chart/loader/archive/budget_test.go @@ -29,7 +29,7 @@ func TestReadFileWithBudget(t *testing.T) { writeFile := func(t *testing.T, name string, size int) string { t.Helper() p := filepath.Join(dir, name) - if err := os.WriteFile(p, make([]byte, size), 0644); err != nil { + if err := os.WriteFile(p, make([]byte, size), 0o644); err != nil { t.Fatal(err) } return p From babae796e3000e03d465366b988477af44beba98 Mon Sep 17 00:00:00 2001 From: George Jenkins Date: Tue, 14 Jul 2026 19:20:33 -0700 Subject: [PATCH 07/11] chore: Cleanup deprecated and TODO comments Signed-off-by: George Jenkins --- internal/chart/v3/chart.go | 2 +- internal/monocular/search.go | 4 ++++ internal/plugin/installer/extractor.go | 2 +- internal/plugin/runtime_subprocess.go | 2 +- pkg/action/action.go | 4 ++-- pkg/action/dependency.go | 14 +++++++++----- pkg/chart/common/capabilities.go | 4 +++- pkg/chart/v2/chart.go | 2 +- pkg/chart/v2/loader/load.go | 7 ++++--- pkg/chart/v2/util/create.go | 2 +- pkg/chart/v2/util/save.go | 2 +- pkg/chart/v2/util/validate_name.go | 7 +++++-- pkg/cmd/install.go | 2 +- pkg/downloader/manager.go | 9 +++++---- pkg/engine/engine.go | 20 +++++++++++++++++--- pkg/kube/interface.go | 4 ++-- pkg/repo/v1/index.go | 21 +++++++++++---------- 17 files changed, 69 insertions(+), 39 deletions(-) diff --git a/internal/chart/v3/chart.go b/internal/chart/v3/chart.go index 71a90c855..e8e03b17e 100644 --- a/internal/chart/v3/chart.go +++ b/internal/chart/v3/chart.go @@ -141,7 +141,7 @@ func (ch *Chart) AppVersion() string { // CRDs returns a list of File objects in the 'crds/' directory of a Helm chart. // -// Deprecated: use CRDObjects() +// Deprecated: Use CRDObjects instead. func (ch *Chart) CRDs() []*common.File { files := []*common.File{} // Find all resources in the crds/ directory diff --git a/internal/monocular/search.go b/internal/monocular/search.go index 29cc7f1a4..d64d6397a 100644 --- a/internal/monocular/search.go +++ b/internal/monocular/search.go @@ -101,11 +101,15 @@ type ChartVersion struct { // Search performs a search against the monocular search API // // Deprecated: Use SearchWithContext instead. +// +//go:fix inline func (c *Client) Search(term string) ([]SearchResult, error) { return c.SearchWithContext(context.Background(), term) } // SearchWithContext performs a search against the monocular search API +// +// TODO Helm v5: Rename this to Search (remove the current deprecated Search method) and 'go:fix inline' SearchWithContext method to call Search. func (c *Client) SearchWithContext(ctx context.Context, term string) ([]SearchResult, error) { // Create the URL to the search endpoint // Note, this is currently an internal API for the Hub. This should be diff --git a/internal/plugin/installer/extractor.go b/internal/plugin/installer/extractor.go index 6cd45e2d8..4588976c4 100644 --- a/internal/plugin/installer/extractor.go +++ b/internal/plugin/installer/extractor.go @@ -48,7 +48,7 @@ var Extractors = map[string]Extractor{ // Convert a media type to an extractor extension. // -// This should be refactored in Helm 4, combined with the extension-based mechanism. +// TODO Helm v5: refactor this, combined with the extension-based mechanism. func mediaTypeToExtension(mt string) (string, bool) { switch strings.ToLower(mt) { case "application/gzip", "application/x-gzip", "application/x-tgz", "application/x-gtar": diff --git a/internal/plugin/runtime_subprocess.go b/internal/plugin/runtime_subprocess.go index e67d1da9b..2fcbcfb33 100644 --- a/internal/plugin/runtime_subprocess.go +++ b/internal/plugin/runtime_subprocess.go @@ -47,7 +47,7 @@ type RuntimeConfigSubprocess struct { PlatformHooks PlatformHooks `yaml:"platformHooks"` // ProtocolCommands allows the plugin to specify protocol specific commands // - // Obsolete/deprecated: This is a compatibility hangover from the old plugin downloader mechanism, which was extended + // Deprecated: This is an obsolete compatibility hangover from the old plugin downloader mechanism, which was extended // to support multiple protocols in a given plugin. The command supplied in PlatformCommand should implement protocol // specific logic by inspecting the download URL ProtocolCommands []SubprocessProtocolCommand `yaml:"protocolCommands,omitempty"` diff --git a/pkg/action/action.go b/pkg/action/action.go index bcc91816c..e93d6181f 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -508,8 +508,8 @@ func (cfg *Configuration) renderResources(ctx context.Context, ch *chart.Chart, newDir = filepath.Join(outputDir, releaseName) } // NOTE: We do not have to worry about the post-renderer because - // output dir is only used by `helm template`. In the next major - // release, we should move this logic to template only as it is not + // output dir is only used by `helm template`. + // TODO Helm v5: move this logic to template only as it is not // used by install or upgrade err = writeToFile(newDir, m.Name, m.Content, fileWritten[m.Name]) if err != nil { diff --git a/pkg/action/dependency.go b/pkg/action/dependency.go index 895c11e63..49f3b5f14 100644 --- a/pkg/action/dependency.go +++ b/pkg/action/dependency.go @@ -77,12 +77,14 @@ func (d *Dependency) dependencyStatus(chartpath string, dep *chart.Dependency, p filename := fmt.Sprintf("%s-%s.tgz", dep.Name, "*") // If a chart is unpacked, this will check the unpacked chart's `charts/` directory for tarballs. - // Technically, this is COMPLETELY unnecessary, and should be removed in Helm 4. It is here - // to preserved backward compatibility. In Helm 2/3, there is a "difference" between + // + // Technically, this is COMPLETELY unnecessary. It is here to preserve backward + // compatibility. In Helm 2/3, there is a "difference" between // the tgz version (which outputs "ok" if it unpacks) and the loaded version (which outputs // "unpacked"). Early in Helm 2's history, this would have made a difference. But it no - // longer does. However, since this code shipped with Helm 3, the output must remain stable - // until Helm 4. + // longer does. However, since this code shipped with Helm 3, the output must remain stable. + // + // TODO Helm v5: remove this. switch archives, err := filepath.Glob(filepath.Join(chartpath, "charts", filename)); { case err != nil: return "bad pattern" @@ -156,7 +158,9 @@ func (d *Dependency) dependencyStatus(chartpath string, dep *chart.Dependency, p // stat an archive and return a message if the stat is successful // // This is a refactor of the code originally in dependencyStatus. It is here to -// support legacy behavior, and should be removed in Helm 4. +// support legacy behavior. +// +// TODO Helm v5: remove this. func statArchiveForStatus(archive string, dep *chart.Dependency) string { if _, err := os.Stat(archive); err == nil { c, err := loader.Load(archive) diff --git a/pkg/chart/common/capabilities.go b/pkg/chart/common/capabilities.go index a9374a86f..c7217a503 100644 --- a/pkg/chart/common/capabilities.go +++ b/pkg/chart/common/capabilities.go @@ -87,7 +87,9 @@ func (kv *KubeVersion) String() string { // GitVersion returns the full Kubernetes version string. // -// Deprecated: use KubeVersion.Version. +// Deprecated: Use KubeVersion.Version. +// +//go:fix inline func (kv *KubeVersion) GitVersion() string { return kv.Version } // ParseKubeVersion parses kubernetes version from string diff --git a/pkg/chart/v2/chart.go b/pkg/chart/v2/chart.go index ccfe84f51..114667001 100644 --- a/pkg/chart/v2/chart.go +++ b/pkg/chart/v2/chart.go @@ -144,7 +144,7 @@ func (ch *Chart) AppVersion() string { // CRDs returns a list of File objects in the 'crds/' directory of a Helm chart. // -// Deprecated: use CRDObjects() +// Deprecated: Use CRDObjects instead. func (ch *Chart) CRDs() []*common.File { files := []*common.File{} // Find all resources in the crds/ directory diff --git a/pkg/chart/v2/loader/load.go b/pkg/chart/v2/loader/load.go index feaa28f12..fc57190ec 100644 --- a/pkg/chart/v2/loader/load.go +++ b/pkg/chart/v2/loader/load.go @@ -113,8 +113,8 @@ func LoadFiles(files []*archive.BufferedFile) (*chart.Chart, error) { c.Schema = f.Data c.SchemaModTime = f.ModTime - // Deprecated: requirements.yaml is deprecated use Chart.yaml. - // We will handle it for you because we are nice people + // requirements.yaml is deprecated; dependencies are declared in Chart.yaml since + // apiVersion v2. Handled here for backwards compatibility. case f.Name == "requirements.yaml": if c.Metadata == nil { c.Metadata = new(chart.Metadata) @@ -128,7 +128,8 @@ func LoadFiles(files []*archive.BufferedFile) (*chart.Chart, error) { if c.Metadata.APIVersion == chart.APIVersionV1 { c.Files = append(c.Files, &common.File{Name: f.Name, ModTime: f.ModTime, Data: f.Data}) } - // Deprecated: requirements.lock is deprecated use Chart.lock. + // requirements.lock is deprecated; use Chart.lock. Handled here for backwards + // compatibility. case f.Name == "requirements.lock": c.Lock = new(chart.Lock) if err := yaml.Unmarshal(f.Data, &c.Lock); err != nil { diff --git a/pkg/chart/v2/util/create.go b/pkg/chart/v2/util/create.go index 82e32d90d..65546e21b 100644 --- a/pkg/chart/v2/util/create.go +++ b/pkg/chart/v2/util/create.go @@ -643,7 +643,7 @@ spec: // Stderr is an io.Writer to which error messages can be written // -// In Helm 4, this will be replaced. It is needed in Helm 3 to preserve API backward +// TODO Helm v5: replace this. It is needed in Helm 3 to preserve API backward // compatibility. var Stderr io.Writer = os.Stderr diff --git a/pkg/chart/v2/util/save.go b/pkg/chart/v2/util/save.go index 53c952421..3dd570e1c 100644 --- a/pkg/chart/v2/util/save.go +++ b/pkg/chart/v2/util/save.go @@ -183,7 +183,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error { } // Save Chart.lock - // TODO: remove the APIVersion check when APIVersionV1 is not used anymore + // TODO Helm v5: remove the APIVersion check when APIVersionV1 is not used anymore if c.Metadata.APIVersion == chart.APIVersionV2 { if c.Lock != nil { ldata, err := yaml.Marshal(c.Lock) diff --git a/pkg/chart/v2/util/validate_name.go b/pkg/chart/v2/util/validate_name.go index 7d85a5b88..1304923dd 100644 --- a/pkg/chart/v2/util/validate_name.go +++ b/pkg/chart/v2/util/validate_name.go @@ -100,8 +100,11 @@ func ValidateReleaseName(name string) error { // The Kubernetes documentation is here, though it is not entirely correct: // https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names // -// Deprecated: remove in Helm 4. Name validation now uses rules defined in -// pkg/lint/rules.validateMetadataNameFunc() +// Deprecated: ValidateMetadataName is no longer used by Helm. Metadata name +// validation is now performed by the lint rule validateMetadataNameFunc (see +// pkg/chart/v2/lint/rules). +// +// TODO Helm v5: remove this function. func ValidateMetadataName(name string) error { if name == "" || len(name) > maxMetadataNameLen || !validName.MatchString(name) { return errInvalidKubernetesName diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index b6cee5843..182b4a7ff 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -214,7 +214,7 @@ func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Instal // For `helm template`, these notes flags are legacy, unused, and should not show in help, but // must remain accepted for backwards compatibility in Helm 4. Deprecate and hide them for now - // TODO remove these from template command in Helm 5 + // TODO Helm v5: remove these from template command if cmd.Name() == "template" { if err := cmd.Flags().MarkDeprecated("hide-notes", "this flag has no effect for 'helm template' and will be removed in Helm 5"); err != nil { log.Fatal(err) diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index c4e12e1d2..2e94d26ae 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -177,10 +177,11 @@ func (m *Manager) Update() error { // For the repositories Helm is not configured to know about, ensure Helm // has some information about them and, when possible, the index files // locally. - // TODO(mattfarina): Repositories should be explicitly added by end users - // rather than automatic. In Helm v4 require users to add repositories. They - // should have to add them in order to make sure they are aware of the - // repositories and opt-in to any locations, for security. + // + // TODO Helm v5: require users to add repositories explicitly rather than + // adding them automatically. They should have to add them in order to make + // sure they are aware of the repositories and opt-in to any locations, for + // security. repoNames, err = m.ensureMissingRepos(repoNames, req) if err != nil { return err diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index cc5917da2..9763bc005 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -79,6 +79,8 @@ func New(config *rest.Config) Engine { // bar chart during render time. // // Deprecated: Use RenderWithContext instead. +// +//go:fix inline func (e Engine) Render(chrt ci.Charter, values common.Values) (map[string]string, error) { return e.RenderWithContext(context.Background(), chrt, values) } @@ -102,6 +104,8 @@ func (e Engine) Render(chrt ci.Charter, values common.Values) (map[string]string // that section of the values will be passed into the "foo" chart. And if that // section contains a value named "bar", that value will be passed on to the // bar chart during render time. +// +// TODO Helm v5: Rename this to Render (remove the current deprecated Render method) and 'go:fix inline' RenderWithContext method to call Render. func (e Engine) RenderWithContext(ctx context.Context, chrt ci.Charter, values common.Values) (map[string]string, error) { tmap := allTemplates(chrt, values) return e.render(ctx, tmap) @@ -109,28 +113,38 @@ func (e Engine) RenderWithContext(ctx context.Context, chrt ci.Charter, values c // Render takes a chart, optional values, and value overrides, and attempts to // render the Go templates using the default options. +// +// Deprecated: Instantiate an Engine and call RenderWithContext instead. +// +// TODO Helm v5: Replace with a NewEngine function. +// +//go:fix inline func Render(chrt ci.Charter, values common.Values) (map[string]string, error) { - return new(Engine).Render(chrt, values) + return new(Engine).RenderWithContext(context.Background(), chrt, values) } // RenderWithClient takes a chart, optional values, and value overrides, and attempts to // render the Go templates using the default options. This engine is client aware and so can have template // functions that interact with the client. +// +// TODO Helm v5: Replace with a NewEngine function that accepts a rest.Config option func RenderWithClient(chrt ci.Charter, values common.Values, config *rest.Config) (map[string]string, error) { var clientProvider ClientProvider = clientProviderFromConfig{config} return Engine{ clientProvider: &clientProvider, - }.Render(chrt, values) + }.RenderWithContext(context.Background(), chrt, values) } // RenderWithClientProvider takes a chart, optional values, and value overrides, and attempts to // render the Go templates using the default options. This engine is client aware and so can have template // functions that interact with the client. // This function differs from RenderWithClient in that it lets you customize the way a dynamic client is constructed. +// +// TODO Helm v5: Replace with a NewEngine function that accepts a ClientProvider option func RenderWithClientProvider(chrt ci.Charter, values common.Values, clientProvider ClientProvider) (map[string]string, error) { return Engine{ clientProvider: &clientProvider, - }.Render(chrt, values) + }.RenderWithContext(context.Background(), chrt, values) } // renderable is an object that can be rendered. diff --git a/pkg/kube/interface.go b/pkg/kube/interface.go index 63c784751..c9a6a0184 100644 --- a/pkg/kube/interface.go +++ b/pkg/kube/interface.go @@ -73,7 +73,7 @@ type Interface interface { // by "\n---\n") // // Validates against OpenAPI schema if validate is true. - // TODO Helm 4: Integrate into Build with an argument + // TODO Helm v5: Integrate into Build with an argument BuildTable(reader io.Reader, validate bool) (ResourceList, error) } @@ -103,7 +103,7 @@ type Waiter interface { // InterfaceWaitOptions defines an interface that extends Interface with // methods that accept wait options. // -// TODO Helm 5: Remove InterfaceWaitOptions and integrate its method(s) into the Interface. +// TODO Helm v5: Remove InterfaceWaitOptions and integrate its method(s) into the Interface. type InterfaceWaitOptions interface { // GetWaiter gets the Kube.Waiter with options. GetWaiterWithOptions(ws WaitStrategy, opts ...WaitOption) (Waiter, error) diff --git a/pkg/repo/v1/index.go b/pkg/repo/v1/index.go index 1c1497c5e..99670eac8 100644 --- a/pkg/repo/v1/index.go +++ b/pkg/repo/v1/index.go @@ -151,7 +151,7 @@ func (i IndexFile) MustAdd(md *chart.Metadata, filename, baseURL, digest string) // Add adds a file to the index and logs an error. // -// Deprecated: Use index.MustAdd instead. +// Deprecated: Use IndexFile.MustAdd instead. Add logs errors; MustAdd returns them. func (i IndexFile) Add(md *chart.Metadata, filename, baseURL, digest string) { if err := i.MustAdd(md, filename, baseURL, digest); err != nil { slog.Error("skipping loading invalid entry for chart", "name", md.Name, "version", md.Version, "file", filename, "error", err) @@ -290,21 +290,22 @@ type ChartVersion struct { Removed bool `json:"removed,omitempty"` Digest string `json:"digest,omitempty"` - // ChecksumDeprecated is deprecated in Helm 3, and therefore ignored. Helm 3 replaced - // this with Digest. However, with a strict YAML parser enabled, a field must be - // present on the struct for backwards compatibility. + // Deprecated: ChecksumDeprecated is ignored (Helm 3 replaced it with Digest). It is + // retained only so a strict YAML parser accepts the "checksum" field for backwards + // compatibility; do not use it. ChecksumDeprecated string `json:"checksum,omitempty"` - // EngineDeprecated is deprecated in Helm 3, and therefore ignored. However, with a strict - // YAML parser enabled, this field must be present. + // Deprecated: EngineDeprecated is ignored (removed in Helm 3). It is retained only so a + // strict YAML parser accepts the "engine" field for backwards compatibility; do not use it. EngineDeprecated string `json:"engine,omitempty"` - // TillerVersionDeprecated is deprecated in Helm 3, and therefore ignored. However, with a strict - // YAML parser enabled, this field must be present. + // Deprecated: TillerVersionDeprecated is ignored (removed in Helm 3). It is retained only + // so a strict YAML parser accepts the "tillerVersion" field for backwards compatibility; + // do not use it. TillerVersionDeprecated string `json:"tillerVersion,omitempty"` - // URLDeprecated is deprecated in Helm 3, superseded by URLs. It is ignored. However, - // with a strict YAML parser enabled, this must be present on the struct. + // Deprecated: URLDeprecated is ignored (superseded by URLs). It is retained only so a + // strict YAML parser accepts the "url" field for backwards compatibility; do not use it. URLDeprecated string `json:"url,omitempty"` } From c0039291c1654ea3178ca7aebc449a980b70a719 Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Mon, 31 Aug 2026 19:19:24 -0300 Subject: [PATCH 08/11] bump version to 4.3 (#32605) Signed-off-by: Scott Rigby --- internal/version/version.go | 2 +- pkg/chart/common/capabilities_test.go | 2 +- pkg/cmd/testdata/output/version-short.txt | 2 +- pkg/cmd/testdata/output/version-template.txt | 2 +- pkg/cmd/testdata/output/version.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/version/version.go b/internal/version/version.go index 572938c96..c40e101de 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -34,7 +34,7 @@ var ( // // Increment major number for new feature additions and behavioral changes. // Increment minor number for bug fixes and performance enhancements. - version = "v4.2" + version = "v4.3" // metadata is extra build time data metadata = "" diff --git a/pkg/chart/common/capabilities_test.go b/pkg/chart/common/capabilities_test.go index b099e3193..18ff08fe9 100644 --- a/pkg/chart/common/capabilities_test.go +++ b/pkg/chart/common/capabilities_test.go @@ -46,7 +46,7 @@ func TestDefaultCapabilities(t *testing.T) { assert.Equalf(t, "20", kv.Minor, "Expected default KubeVersion.Minor to be 20, got %q", kv.Minor) hv := caps.HelmVersion - assert.Equalf(t, "v4.2", hv.Version, "Expected default HelmVersion to be v4.2, got %q", hv.Version) + assert.Equalf(t, "v4.3", hv.Version, "Expected default HelmVersion to be v4.3, got %q", hv.Version) } func TestParseKubeVersion(t *testing.T) { diff --git a/pkg/cmd/testdata/output/version-short.txt b/pkg/cmd/testdata/output/version-short.txt index 2fa2c5705..b570a0ac2 100644 --- a/pkg/cmd/testdata/output/version-short.txt +++ b/pkg/cmd/testdata/output/version-short.txt @@ -1 +1 @@ -v4.2 +v4.3 diff --git a/pkg/cmd/testdata/output/version-template.txt b/pkg/cmd/testdata/output/version-template.txt index 8f2491e54..06a6787a8 100644 --- a/pkg/cmd/testdata/output/version-template.txt +++ b/pkg/cmd/testdata/output/version-template.txt @@ -1 +1 @@ -Version: v4.2 \ No newline at end of file +Version: v4.3 \ No newline at end of file diff --git a/pkg/cmd/testdata/output/version.txt b/pkg/cmd/testdata/output/version.txt index 331c6d5e9..4b5678a7f 100644 --- a/pkg/cmd/testdata/output/version.txt +++ b/pkg/cmd/testdata/output/version.txt @@ -1 +1 @@ -version.BuildInfo{Version:"v4.2", GitCommit:"", GitTreeState:"", GoVersion:"", KubeClientVersion:"v1.20"} +version.BuildInfo{Version:"v4.3", GitCommit:"", GitTreeState:"", GoVersion:"", KubeClientVersion:"v1.20"} From 702c67e97dd419142534937974d1b7205ecd2124 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 06:32:38 -0600 Subject: [PATCH 09/11] chore(deps): bump github.com/gofrs/flock from 0.13.0 to 0.13.1 (#32601) Bumps [github.com/gofrs/flock](https://github.com/gofrs/flock) from 0.13.0 to 0.13.1. - [Release notes](https://github.com/gofrs/flock/releases) - [Commits](https://github.com/gofrs/flock/compare/v0.13.0...v0.13.1) --- updated-dependencies: - dependency-name: github.com/gofrs/flock dependency-version: 0.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bf8bb7228..3fd2aa8ce 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/fluxcd/cli-utils v1.2.2 github.com/foxcpp/go-mockdns v1.2.0 github.com/gobwas/glob v0.2.3 - github.com/gofrs/flock v0.13.0 + github.com/gofrs/flock v0.13.1 github.com/gosuri/uitable v0.0.4 github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.12.3 diff --git a/go.sum b/go.sum index b9d8e51fc..7ef64118f 100644 --- a/go.sum +++ b/go.sum @@ -130,8 +130,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= -github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= +github.com/gofrs/flock v0.13.1 h1:jjREztyBeSKBZYAC+mgc1laB+xsgy4kYMf3FbKF2UBo= +github.com/gofrs/flock v0.13.1/go.mod h1:sf4BFiHwnvgxa25DlQoDqXQnwRMEOwqxRq37P6MzzmE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= From 4ba1280837dda7e11d4d1e5019b14c4c94350b08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 06:40:54 -0600 Subject: [PATCH 10/11] chore(deps): bump github.com/gobwas/glob from 0.2.3 to 1.0.0 (#32602) Bumps [github.com/gobwas/glob](https://github.com/gobwas/glob) from 0.2.3 to 1.0.0. - [Release notes](https://github.com/gobwas/glob/releases) - [Commits](https://github.com/gobwas/glob/compare/v0.2.3...v1.0.0) --- updated-dependencies: - dependency-name: github.com/gobwas/glob dependency-version: 1.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3fd2aa8ce..9da20b09a 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/fatih/color v1.19.0 github.com/fluxcd/cli-utils v1.2.2 github.com/foxcpp/go-mockdns v1.2.0 - github.com/gobwas/glob v0.2.3 + github.com/gobwas/glob v1.0.0 github.com/gofrs/flock v0.13.1 github.com/gosuri/uitable v0.0.4 github.com/jmoiron/sqlx v1.4.0 diff --git a/go.sum b/go.sum index 7ef64118f..c4497aa58 100644 --- a/go.sum +++ b/go.sum @@ -128,8 +128,8 @@ github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqw github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/glob v1.0.0 h1:p+FKbLEIsK1yZ39/OINwFvqNb5oyPY4H8xcy6uYu8dg= +github.com/gobwas/glob v1.0.0/go.mod h1:oWCdo522i2P1n/hMXGNWs7yoV4wy/ciZuUIbvKj5rkc= github.com/gofrs/flock v0.13.1 h1:jjREztyBeSKBZYAC+mgc1laB+xsgy4kYMf3FbKF2UBo= github.com/gofrs/flock v0.13.1/go.mod h1:sf4BFiHwnvgxa25DlQoDqXQnwRMEOwqxRq37P6MzzmE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= From 67946bb22e9a2f39ee7ff70effca98630fafd9bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 06:51:47 -0600 Subject: [PATCH 11/11] chore(deps): bump the github-actions group across 1 directory with 4 updates (#32603) Bumps the github-actions group with 4 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action). Updates `github/codeql-action/init` from 4.37.8 to 4.37.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938) Updates `github/codeql-action/autobuild` from 4.37.8 to 4.37.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938) Updates `github/codeql-action/analyze` from 4.37.8 to 4.37.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938) Updates `github/codeql-action/upload-sarif` from 4.37.8 to 4.37.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938) --- updated-dependencies: - dependency-name: github/codeql-action/analyze dependency-version: 4.37.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/autobuild dependency-version: 4.37.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/init dependency-version: 4.37.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/upload-sarif dependency-version: 4.37.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d4d9f5228..37e3e2048 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -48,7 +48,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # pinv4.37.8 + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # pinv4.37.9 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -59,7 +59,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # pinv4.37.8 + uses: github/codeql-action/autobuild@cdf488f595d80d6e07e03d4674febd5ab45fa938 # pinv4.37.9 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -73,4 +73,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # pinv4.37.8 + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # pinv4.37.9 diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 6d5367952..469178ced 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: sarif_file: results.sarif