From a2b1a60d51223254bd9c2f08cf3f411eb9d9fc58 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Sat, 18 Jul 2026 13:28:03 +0200 Subject: [PATCH 1/3] fix: enhance error handling and improve test assertions (#32352) Signed-off-by: Matthieu MOREL --- .golangci.yml | 4 +-- .../chart/v3/lint/rules/deprecations_test.go | 8 ++---- internal/plugin/runtime_subprocess.go | 7 +++-- internal/sympath/walk.go | 9 +++--- pkg/chart/v2/lint/rules/deprecations_test.go | 13 +++++---- pkg/chart/v2/lint/rules/template_test.go | 10 ++++--- pkg/chart/v2/util/dependencies_test.go | 10 +++---- pkg/cmd/plugin_test.go | 28 ++++++------------- pkg/kube/client.go | 7 +++-- pkg/provenance/sign_test.go | 8 ++---- pkg/registry/transport.go | 3 +- pkg/repo/v1/index.go | 4 +-- pkg/strvals/parser.go | 22 +++++++-------- 13 files changed, 63 insertions(+), 70 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 6727d3001..5b6d7cf8e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -74,9 +74,9 @@ linters: errorlint: # Check for plain type assertions and type switches. - asserts: false + asserts: true # Check for plain error comparisons. - comparison: false + comparison: true exhaustive: default-signifies-exhaustive: true diff --git a/internal/chart/v3/lint/rules/deprecations_test.go b/internal/chart/v3/lint/rules/deprecations_test.go index a255abf50..55c454118 100644 --- a/internal/chart/v3/lint/rules/deprecations_test.go +++ b/internal/chart/v3/lint/rules/deprecations_test.go @@ -29,14 +29,12 @@ func TestValidateNoDeprecations(t *testing.T) { Kind: "Deployment", } err := validateNoDeprecations(deprecated, nil) - var depErr deprecatedAPIError require.Error(t, err, "Expected deprecated extension to be flagged") + var depErr deprecatedAPIError require.ErrorAs(t, err, &depErr, "Expected error to be of type deprecatedAPIError") require.NotEmpty(t, depErr.Message, "Expected error message to be non-blank: %v", err) - - err = validateNoDeprecations(&k8sYamlStruct{ + assert.NoError(t, validateNoDeprecations(&k8sYamlStruct{ APIVersion: "v1", Kind: "Pod", - }, nil) - assert.NoError(t, err, "Expected a v1 Pod to not be deprecated") + }, nil), "Expected a v1 Pod to not be deprecated") } diff --git a/internal/plugin/runtime_subprocess.go b/internal/plugin/runtime_subprocess.go index b921587c1..2dbe220d9 100644 --- a/internal/plugin/runtime_subprocess.go +++ b/internal/plugin/runtime_subprocess.go @@ -18,6 +18,7 @@ package plugin import ( "bytes" "context" + "errors" "fmt" "io" "log/slog" @@ -152,7 +153,8 @@ func (r *SubprocessPluginRuntime) InvokeHook(event string) error { slog.Debug("executing plugin hook command", slog.String("pluginName", r.metadata.Name), slog.String("command", cmd.String())) if err := cmd.Run(); err != nil { - if eerr, ok := err.(*exec.ExitError); ok { + var eerr *exec.ExitError + if errors.As(err, &eerr) { os.Stderr.Write(eerr.Stderr) return fmt.Errorf("plugin %s hook for %q exited with error", event, r.metadata.Name) } @@ -166,7 +168,8 @@ func (r *SubprocessPluginRuntime) InvokeHook(event string) error { // then replace the other three with a call to this func func executeCmd(prog *exec.Cmd, pluginName string) error { if err := prog.Run(); err != nil { - if eerr, ok := err.(*exec.ExitError); ok { + var eerr *exec.ExitError + if errors.As(err, &eerr) { slog.Debug( "plugin execution failed", slog.String("pluginName", pluginName), diff --git a/internal/sympath/walk.go b/internal/sympath/walk.go index 812bb68ce..b54b97ad4 100644 --- a/internal/sympath/walk.go +++ b/internal/sympath/walk.go @@ -21,6 +21,7 @@ limitations under the License. package sympath import ( + "errors" "fmt" "log/slog" "os" @@ -40,7 +41,7 @@ func Walk(root string, walkFn filepath.WalkFunc) error { } else { err = symwalk(root, info, walkFn) } - if err == filepath.SkipDir { + if errors.Is(err, filepath.SkipDir) { return nil } return err @@ -75,7 +76,7 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { if info, err = os.Lstat(resolved); err != nil { return err } - if err := symwalk(path, info, walkFn); err != nil && err != filepath.SkipDir { + if err := symwalk(path, info, walkFn); err != nil && !errors.Is(err, filepath.SkipDir) { return err } return nil @@ -98,13 +99,13 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { filename := filepath.Join(path, name) fileInfo, err := os.Lstat(filename) if err != nil { - if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir { + if err := walkFn(filename, fileInfo, err); err != nil && !errors.Is(err, filepath.SkipDir) { return err } } else { err = symwalk(filename, fileInfo, walkFn) if err != nil { - if (!fileInfo.IsDir() && !IsSymlink(fileInfo)) || err != filepath.SkipDir { + if (!fileInfo.IsDir() && !IsSymlink(fileInfo)) || !errors.Is(err, filepath.SkipDir) { return err } } diff --git a/pkg/chart/v2/lint/rules/deprecations_test.go b/pkg/chart/v2/lint/rules/deprecations_test.go index 86643f1c9..fdeb47e91 100644 --- a/pkg/chart/v2/lint/rules/deprecations_test.go +++ b/pkg/chart/v2/lint/rules/deprecations_test.go @@ -16,7 +16,11 @@ limitations under the License. package rules // import "helm.sh/helm/v4/pkg/chart/v2/lint/rules" -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" +) func TestValidateNoDeprecations(t *testing.T) { deprecated := &k8sYamlStruct{ @@ -27,10 +31,9 @@ func TestValidateNoDeprecations(t *testing.T) { if err == nil { t.Fatal("Expected deprecated extension to be flagged") } - depErr := err.(deprecatedAPIError) - if depErr.Message == "" { - t.Fatalf("Expected error message to be non-blank: %v", err) - } + var depErr deprecatedAPIError + require.ErrorAs(t, err, &depErr) + require.NotEmptyf(t, depErr.Message, "Expected error message to be non-blank") if err := validateNoDeprecations(&k8sYamlStruct{ APIVersion: "v1", diff --git a/pkg/chart/v2/lint/rules/template_test.go b/pkg/chart/v2/lint/rules/template_test.go index f0eb008b3..12eec7531 100644 --- a/pkg/chart/v2/lint/rules/template_test.go +++ b/pkg/chart/v2/lint/rules/template_test.go @@ -24,6 +24,9 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "helm.sh/helm/v4/pkg/chart/common" chart "helm.sh/helm/v4/pkg/chart/v2" "helm.sh/helm/v4/pkg/chart/v2/lint/support" @@ -235,10 +238,9 @@ func TestDeprecatedAPIFails(t *testing.T) { t.Fatalf("Expected 1 lint error, got %d", l) } - err := linter.Messages[0].Err.(deprecatedAPIError) - if err.Deprecated != "apps/v1beta1 Deployment" { - t.Errorf("Surprised to learn that %q is deprecated", err.Deprecated) - } + var depErr deprecatedAPIError + require.ErrorAs(t, linter.Messages[0].Err, &depErr) + assert.Equalf(t, "apps/v1beta1 Deployment", depErr.Deprecated, "Surprised to learn that %q is deprecated", depErr.Deprecated) } const manifest = `apiVersion: v1 diff --git a/pkg/chart/v2/util/dependencies_test.go b/pkg/chart/v2/util/dependencies_test.go index 90a8806ec..40a17ac3a 100644 --- a/pkg/chart/v2/util/dependencies_test.go +++ b/pkg/chart/v2/util/dependencies_test.go @@ -21,6 +21,8 @@ import ( "strconv" "testing" + "github.com/stretchr/testify/require" + "helm.sh/helm/v4/pkg/chart/common" chart "helm.sh/helm/v4/pkg/chart/v2" "helm.sh/helm/v4/pkg/chart/v2/loader" @@ -251,12 +253,8 @@ func TestProcessDependencyImportValues(t *testing.T) { if err == nil { t.Error("expect nil value not found but found it") } - switch xerr := err.(type) { - case common.ErrNoValue: - // We found what we expected - default: - t.Errorf("expected an ErrNoValue but got %q instead", xerr) - } + var xerr common.ErrNoValue + require.ErrorAs(t, err, &xerr, "expected an ErrNoValue") c = loadChart(t, "testdata/subpop") if err := processDependencyImportValues(c, true); err != nil { diff --git a/pkg/cmd/plugin_test.go b/pkg/cmd/plugin_test.go index 476997110..5364423a0 100644 --- a/pkg/cmd/plugin_test.go +++ b/pkg/cmd/plugin_test.go @@ -144,16 +144,10 @@ func TestLoadCLIPlugins(t *testing.T) { // tests until this is fixed if runtime.GOOS != "windows" { if err := pluginCmd.RunE(pluginCmd, tt.args); err != nil { - if tt.code > 0 { - cerr, ok := err.(CommandError) - if !ok { - t.Errorf("Expected %s to return pluginError: got %v(%T)", tt.use, err, err) - } - if cerr.ExitCode != tt.code { - t.Errorf("Expected %s to return %d: got %d", tt.use, tt.code, cerr.ExitCode) - } - } else { - t.Errorf("Error running %s: %+v", tt.use, err) + if assert.Positive(t, tt.code, "Error running %s: %+v", tt.use, err) { + var cerr CommandError + require.ErrorAs(t, err, &cerr, "Expected %s to return pluginError: got %v(%T)", tt.use, err, err) + assert.Equalf(t, tt.code, cerr.ExitCode, "Expected %s to return %d: got %d", tt.use, tt.code, cerr.ExitCode) } } assert.Equal(t, tt.expect, out.String(), "expected output for %q", tt.use) @@ -218,16 +212,10 @@ func TestLoadPluginsWithSpace(t *testing.T) { // tests until this is fixed if runtime.GOOS != "windows" { if err := pp.RunE(pp, tt.args); err != nil { - if tt.code > 0 { - cerr, ok := err.(CommandError) - if !ok { - t.Errorf("Expected %s to return pluginError: got %v(%T)", tt.use, err, err) - } - if cerr.ExitCode != tt.code { - t.Errorf("Expected %s to return %d: got %d", tt.use, tt.code, cerr.ExitCode) - } - } else { - t.Errorf("Error running %s: %+v", tt.use, err) + if assert.Positive(t, tt.code, "Error running %s: %+v", tt.use, err) { + var cerr CommandError + require.ErrorAs(t, err, &cerr, "Expected %s to return pluginError: got %v(%T)", tt.use, err, err) + assert.Equalf(t, tt.code, cerr.ExitCode, "Expected %s to return %d: got %d", tt.use, tt.code, cerr.ExitCode) } } assert.Equal(t, tt.expect, out.String(), "expected output for %s", tt.use) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index e363fad61..1dfa88800 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -249,7 +249,7 @@ func (c *Client) getKubeClient() (kubernetes.Interface, error) { // IsReachable tests connectivity to the cluster. func (c *Client) IsReachable() error { client, err := c.getKubeClient() - if err == genericclioptions.ErrEmptyConfig { + if errors.Is(err, genericclioptions.ErrEmptyConfig) { // re-replace kubernetes ErrEmptyConfig error with a friendly error // moar workarounds for Kubernetes API breaking. return errors.New("kubernetes cluster unreachable") @@ -949,11 +949,12 @@ func (c *Client) Delete(resources ResourceList, policy metav1.DeletionPropagatio func isIncompatibleServerError(err error) bool { // 415: Unsupported media type means we're talking to a server which doesn't // support server-side apply. - if _, ok := err.(*apierrors.StatusError); !ok { + var sErr *apierrors.StatusError + if !errors.As(err, &sErr) { // Non-StatusError means the error isn't because the server is incompatible. return false } - return err.(*apierrors.StatusError).Status().Code == http.StatusUnsupportedMediaType + return sErr.Status().Code == http.StatusUnsupportedMediaType } // isServerSideRetryable checks if an error encountered during server-side apply diff --git a/pkg/provenance/sign_test.go b/pkg/provenance/sign_test.go index 3f8e654f9..79b33a970 100644 --- a/pkg/provenance/sign_test.go +++ b/pkg/provenance/sign_test.go @@ -385,11 +385,9 @@ func TestVerify(t *testing.T) { _, err = signer.Verify(archiveData, tamperedSigData, filepath.Base(testChartfile)) require.Errorf(t, err, "Expected %s to fail.", testTamperedSigBlock) - switch err.(type) { - case pgperrors.SignatureError: - t.Logf("Tampered sig block error: %s (%T)", err, err) - default: - t.Errorf("Expected invalid signature error, got %q (%T)", err, err) + var sErr pgperrors.SignatureError + if assert.ErrorAs(t, err, &sErr, "Expected invalid signature error, got %q (%T)", err, err) { + t.Logf("Tampered sig block error: %s (%T)", sErr, sErr) } } diff --git a/pkg/registry/transport.go b/pkg/registry/transport.go index beec43cdd..fa0103ac0 100644 --- a/pkg/registry/transport.go +++ b/pkg/registry/transport.go @@ -18,6 +18,7 @@ package registry import ( "bytes" + "errors" "fmt" "io" "log/slog" @@ -126,7 +127,7 @@ func logResponseBody(resp *http.Response) string { Closer: body, } // read the body up to limit+1 to check if the body exceeds the limit - if _, err := io.CopyN(buf, body, payloadSizeLimit+1); err != nil && err != io.EOF { + if _, err := io.CopyN(buf, body, payloadSizeLimit+1); err != nil && !errors.Is(err, io.EOF) { return fmt.Sprintf(" Error reading response body: %v", err) } diff --git a/pkg/repo/v1/index.go b/pkg/repo/v1/index.go index 839a4cca9..1c1497c5e 100644 --- a/pkg/repo/v1/index.go +++ b/pkg/repo/v1/index.go @@ -421,8 +421,8 @@ func jsonOrYamlUnmarshal(b []byte, i any) error { // And repository indexes may be generated by older/non-compliant software, which doesn't // conform to all validations. func ignoreSkippableChartValidationError(err error) error { - verr, ok := err.(chart.ValidationError) - if !ok { + var verr chart.ValidationError + if !errors.As(err, &verr) { return err } diff --git a/pkg/strvals/parser.go b/pkg/strvals/parser.go index d74e46986..be3b1e71b 100644 --- a/pkg/strvals/parser.go +++ b/pkg/strvals/parser.go @@ -238,16 +238,16 @@ func (t *parser) key(data map[string]any, nestedNameLevel int) (reterr error) { // End of key. Consume =, Get value. // FIXME: Get value list first vl, e := t.valList() - switch e { - case nil: + switch { + case e == nil: set(data, string(k), vl) return nil - case io.EOF: + case errors.Is(e, io.EOF): set(data, string(k), "") return e - case ErrNotList: + case errors.Is(e, ErrNotList): rs, e := t.val() - if e != nil && e != io.EOF { + if e != nil && !errors.Is(e, io.EOF) { return e } v, e := t.reader(rs) @@ -370,14 +370,14 @@ func (t *parser) listItem(list []any, i, nestedNameLevel int) ([]any, error) { return list, err } vl, e := t.valList() - switch e { - case nil: + switch { + case e == nil: return setIndex(list, i, vl) - case io.EOF: + case errors.Is(e, io.EOF): return setIndex(list, i, "") - case ErrNotList: + case errors.Is(e, ErrNotList): rs, e := t.val() - if e != nil && e != io.EOF { + if e != nil && !errors.Is(e, io.EOF) { return list, e } v, e := t.reader(rs) @@ -476,7 +476,7 @@ func (t *parser) valList() ([]any, error) { for { switch rs, last, err := runesUntil(t.sc, stop); { case err != nil: - if err == io.EOF { + if errors.Is(err, io.EOF) { err = errors.New("list must terminate with '}'") } return list, err From 82be04d7f2881f59b3a85483eb248417e1d18fc3 Mon Sep 17 00:00:00 2001 From: Abhay Chaurasiya <44005156+abhay1999@users.noreply.github.com> Date: Sat, 18 Jul 2026 17:12:20 +0530 Subject: [PATCH 2/3] remove legacy import comments from remaining packages (#31933) Pre-Go-modules import path comments (e.g. `// import "helm.sh/helm/v4/..."`) are obsolete since Go 1.11 where go.mod is the authoritative module path. These stale comments cause issues with downstream tooling such as Kythe. Removes the legacy import comments from 64 files across 20 packages: - cmd/helm - internal/chart/v3/lint and sub-packages - internal/plugin and sub-packages - internal/release/v2/util - pkg/chart/v2/lint and sub-packages - pkg/cmd, pkg/engine, pkg/ignore, pkg/provenance - pkg/registry - pkg/release/v1/util - pkg/repo/v1 - pkg/storage and pkg/storage/driver Follows up on #31931 and #31932 which addressed pkg/kube. Fixes #31846 Signed-off-by: abhay1999 Signed-off-by: abhay1999 --- cmd/helm/helm.go | 2 +- internal/chart/v3/lint/lint.go | 2 +- internal/chart/v3/lint/rules/chartfile.go | 2 +- internal/chart/v3/lint/rules/dependencies.go | 2 +- internal/chart/v3/lint/rules/deprecations.go | 2 +- internal/chart/v3/lint/rules/deprecations_test.go | 2 +- internal/chart/v3/lint/support/doc.go | 2 +- internal/plugin/cache/cache.go | 2 +- internal/plugin/installer/base.go | 2 +- internal/plugin/installer/base_test.go | 2 +- internal/plugin/installer/doc.go | 2 +- internal/plugin/installer/extractor.go | 2 +- internal/plugin/installer/http_installer.go | 2 +- internal/plugin/installer/http_installer_test.go | 2 +- internal/plugin/installer/local_installer.go | 2 +- internal/plugin/installer/local_installer_test.go | 2 +- internal/plugin/installer/oci_installer_test.go | 2 +- internal/plugin/installer/vcs_installer.go | 2 +- internal/plugin/installer/vcs_installer_test.go | 2 +- internal/plugin/plugin.go | 2 +- internal/plugin/runtime_subprocess_hooks.go | 2 +- internal/release/v2/util/filter.go | 2 +- internal/release/v2/util/filter_test.go | 2 +- internal/release/v2/util/kind_sorter.go | 2 +- internal/release/v2/util/kind_sorter_test.go | 2 +- internal/release/v2/util/manifest.go | 2 +- internal/release/v2/util/manifest_sorter.go | 2 +- internal/release/v2/util/manifest_sorter_test.go | 2 +- internal/release/v2/util/manifest_test.go | 2 +- internal/release/v2/util/sorter.go | 2 +- internal/release/v2/util/sorter_test.go | 2 +- pkg/chart/v2/lint/lint.go | 2 +- pkg/chart/v2/lint/rules/chartfile.go | 2 +- pkg/chart/v2/lint/rules/dependencies.go | 2 +- pkg/chart/v2/lint/rules/deprecations.go | 2 +- pkg/chart/v2/lint/rules/deprecations_test.go | 2 +- pkg/chart/v2/lint/support/doc.go | 2 +- pkg/cmd/root.go | 2 +- pkg/engine/doc.go | 2 +- pkg/ignore/doc.go | 2 +- pkg/provenance/doc.go | 2 +- pkg/registry/chart.go | 2 +- pkg/registry/chart_test.go | 2 +- pkg/registry/client.go | 2 +- pkg/registry/constants.go | 2 +- pkg/registry/tag.go | 2 +- pkg/release/v1/util/filter.go | 2 +- pkg/release/v1/util/filter_test.go | 2 +- pkg/release/v1/util/manifest_test.go | 2 +- pkg/release/v1/util/sorter.go | 2 +- pkg/release/v1/util/sorter_test.go | 2 +- pkg/repo/v1/chartrepo.go | 2 +- pkg/repo/v1/repo.go | 2 +- pkg/storage/driver/cfgmaps.go | 2 +- pkg/storage/driver/driver.go | 2 +- pkg/storage/driver/labels_test.go | 2 +- pkg/storage/driver/mock_test.go | 2 +- pkg/storage/driver/records.go | 2 +- pkg/storage/driver/records_test.go | 2 +- pkg/storage/driver/secrets.go | 2 +- pkg/storage/driver/sql.go | 2 +- pkg/storage/driver/util.go | 2 +- pkg/storage/storage.go | 2 +- pkg/storage/storage_test.go | 2 +- 64 files changed, 64 insertions(+), 64 deletions(-) diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index 0c4f697b6..60df8a308 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package main // import "helm.sh/helm/v4/cmd/helm" +package main import ( "errors" diff --git a/internal/chart/v3/lint/lint.go b/internal/chart/v3/lint/lint.go index ea8ca3d60..193f0f796 100644 --- a/internal/chart/v3/lint/lint.go +++ b/internal/chart/v3/lint/lint.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package lint // import "helm.sh/helm/v4/internal/chart/v3/lint" +package lint import ( "path/filepath" diff --git a/internal/chart/v3/lint/rules/chartfile.go b/internal/chart/v3/lint/rules/chartfile.go index db7ac61dc..c76654d53 100644 --- a/internal/chart/v3/lint/rules/chartfile.go +++ b/internal/chart/v3/lint/rules/chartfile.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/internal/chart/v3/lint/rules" +package rules import ( "errors" diff --git a/internal/chart/v3/lint/rules/dependencies.go b/internal/chart/v3/lint/rules/dependencies.go index f45153728..2f558aaf0 100644 --- a/internal/chart/v3/lint/rules/dependencies.go +++ b/internal/chart/v3/lint/rules/dependencies.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/internal/chart/v3/lint/rules" +package rules import ( "fmt" diff --git a/internal/chart/v3/lint/rules/deprecations.go b/internal/chart/v3/lint/rules/deprecations.go index 9c73268af..85dddd114 100644 --- a/internal/chart/v3/lint/rules/deprecations.go +++ b/internal/chart/v3/lint/rules/deprecations.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/internal/chart/v3/lint/rules" +package rules import ( "fmt" diff --git a/internal/chart/v3/lint/rules/deprecations_test.go b/internal/chart/v3/lint/rules/deprecations_test.go index 55c454118..920fdc31f 100644 --- a/internal/chart/v3/lint/rules/deprecations_test.go +++ b/internal/chart/v3/lint/rules/deprecations_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/internal/chart/v3/lint/rules" +package rules import ( "testing" diff --git a/internal/chart/v3/lint/support/doc.go b/internal/chart/v3/lint/support/doc.go index 2d54a9b7d..80b1d2169 100644 --- a/internal/chart/v3/lint/support/doc.go +++ b/internal/chart/v3/lint/support/doc.go @@ -20,4 +20,4 @@ Package support contains tools for linting charts. Linting is the process of testing charts for errors or warnings regarding formatting, compilation, or standards compliance. */ -package support // import "helm.sh/helm/v4/internal/chart/v3/lint/support" +package support diff --git a/internal/plugin/cache/cache.go b/internal/plugin/cache/cache.go index f3b737477..1613d4d76 100644 --- a/internal/plugin/cache/cache.go +++ b/internal/plugin/cache/cache.go @@ -14,7 +14,7 @@ limitations under the License. */ // Package cache provides a key generator for vcs urls. -package cache // import "helm.sh/helm/v4/internal/plugin/cache" +package cache import ( "net/url" diff --git a/internal/plugin/installer/base.go b/internal/plugin/installer/base.go index c21a245a8..54d25287a 100644 --- a/internal/plugin/installer/base.go +++ b/internal/plugin/installer/base.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "path/filepath" diff --git a/internal/plugin/installer/base_test.go b/internal/plugin/installer/base_test.go index 6df8ec8a1..b7902e699 100644 --- a/internal/plugin/installer/base_test.go +++ b/internal/plugin/installer/base_test.go @@ -11,7 +11,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "testing" diff --git a/internal/plugin/installer/doc.go b/internal/plugin/installer/doc.go index a4cf384bf..a9d9555c9 100644 --- a/internal/plugin/installer/doc.go +++ b/internal/plugin/installer/doc.go @@ -14,4 +14,4 @@ limitations under the License. */ // Package installer provides an interface for installing Helm plugins. -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer diff --git a/internal/plugin/installer/extractor.go b/internal/plugin/installer/extractor.go index 85d695bd2..6cd45e2d8 100644 --- a/internal/plugin/installer/extractor.go +++ b/internal/plugin/installer/extractor.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "archive/tar" diff --git a/internal/plugin/installer/http_installer.go b/internal/plugin/installer/http_installer.go index 92d3d686e..7be326de2 100644 --- a/internal/plugin/installer/http_installer.go +++ b/internal/plugin/installer/http_installer.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "bytes" diff --git a/internal/plugin/installer/http_installer_test.go b/internal/plugin/installer/http_installer_test.go index cbd868f3a..3235e9796 100644 --- a/internal/plugin/installer/http_installer_test.go +++ b/internal/plugin/installer/http_installer_test.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "archive/tar" diff --git a/internal/plugin/installer/local_installer.go b/internal/plugin/installer/local_installer.go index a7a6caa14..59918401b 100644 --- a/internal/plugin/installer/local_installer.go +++ b/internal/plugin/installer/local_installer.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "bytes" diff --git a/internal/plugin/installer/local_installer_test.go b/internal/plugin/installer/local_installer_test.go index 02d4d7bff..f46fcb44b 100644 --- a/internal/plugin/installer/local_installer_test.go +++ b/internal/plugin/installer/local_installer_test.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "archive/tar" diff --git a/internal/plugin/installer/oci_installer_test.go b/internal/plugin/installer/oci_installer_test.go index c3bebdb52..48eccf6e1 100644 --- a/internal/plugin/installer/oci_installer_test.go +++ b/internal/plugin/installer/oci_installer_test.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "archive/tar" diff --git a/internal/plugin/installer/vcs_installer.go b/internal/plugin/installer/vcs_installer.go index 3601ec7a8..13aba74dc 100644 --- a/internal/plugin/installer/vcs_installer.go +++ b/internal/plugin/installer/vcs_installer.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "errors" diff --git a/internal/plugin/installer/vcs_installer_test.go b/internal/plugin/installer/vcs_installer_test.go index 401f2b921..7e44cc957 100644 --- a/internal/plugin/installer/vcs_installer_test.go +++ b/internal/plugin/installer/vcs_installer_test.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package installer // import "helm.sh/helm/v4/internal/plugin/installer" +package installer import ( "fmt" diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go index 789e583ae..ad2dd7922 100644 --- a/internal/plugin/plugin.go +++ b/internal/plugin/plugin.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package plugin // import "helm.sh/helm/v4/internal/plugin" +package plugin import ( "context" diff --git a/internal/plugin/runtime_subprocess_hooks.go b/internal/plugin/runtime_subprocess_hooks.go index 7b4ff5a38..8d5f3cba6 100644 --- a/internal/plugin/runtime_subprocess_hooks.go +++ b/internal/plugin/runtime_subprocess_hooks.go @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package plugin // import "helm.sh/helm/v4/internal/plugin" +package plugin // Types of hooks const ( diff --git a/internal/release/v2/util/filter.go b/internal/release/v2/util/filter.go index bc568cbdc..0daf06014 100644 --- a/internal/release/v2/util/filter.go +++ b/internal/release/v2/util/filter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( v2 "helm.sh/helm/v4/internal/release/v2" diff --git a/internal/release/v2/util/filter_test.go b/internal/release/v2/util/filter_test.go index 8c7363b87..542510ba3 100644 --- a/internal/release/v2/util/filter_test.go +++ b/internal/release/v2/util/filter_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "testing" diff --git a/internal/release/v2/util/kind_sorter.go b/internal/release/v2/util/kind_sorter.go index dba35b6d2..950e836fa 100644 --- a/internal/release/v2/util/kind_sorter.go +++ b/internal/release/v2/util/kind_sorter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "sort" diff --git a/internal/release/v2/util/kind_sorter_test.go b/internal/release/v2/util/kind_sorter_test.go index dba19e287..06885aa93 100644 --- a/internal/release/v2/util/kind_sorter_test.go +++ b/internal/release/v2/util/kind_sorter_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "bytes" diff --git a/internal/release/v2/util/manifest.go b/internal/release/v2/util/manifest.go index d3296984e..37b9dfbd3 100644 --- a/internal/release/v2/util/manifest.go +++ b/internal/release/v2/util/manifest.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "fmt" diff --git a/internal/release/v2/util/manifest_sorter.go b/internal/release/v2/util/manifest_sorter.go index f269dda6d..3507deed5 100644 --- a/internal/release/v2/util/manifest_sorter.go +++ b/internal/release/v2/util/manifest_sorter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "fmt" diff --git a/internal/release/v2/util/manifest_sorter_test.go b/internal/release/v2/util/manifest_sorter_test.go index eac9c9f36..deb9426ce 100644 --- a/internal/release/v2/util/manifest_sorter_test.go +++ b/internal/release/v2/util/manifest_sorter_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "testing" diff --git a/internal/release/v2/util/manifest_test.go b/internal/release/v2/util/manifest_test.go index 1806368af..e76905a63 100644 --- a/internal/release/v2/util/manifest_test.go +++ b/internal/release/v2/util/manifest_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "testing" diff --git a/internal/release/v2/util/sorter.go b/internal/release/v2/util/sorter.go index 5f13569c1..66b51d873 100644 --- a/internal/release/v2/util/sorter.go +++ b/internal/release/v2/util/sorter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "sort" diff --git a/internal/release/v2/util/sorter_test.go b/internal/release/v2/util/sorter_test.go index 82a53ae66..e151f0790 100644 --- a/internal/release/v2/util/sorter_test.go +++ b/internal/release/v2/util/sorter_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/internal/release/v2/util" +package util import ( "testing" diff --git a/pkg/chart/v2/lint/lint.go b/pkg/chart/v2/lint/lint.go index 23a93c551..204c15861 100644 --- a/pkg/chart/v2/lint/lint.go +++ b/pkg/chart/v2/lint/lint.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package lint // import "helm.sh/helm/v4/pkg/chart/v2/lint" +package lint import ( "path/filepath" diff --git a/pkg/chart/v2/lint/rules/chartfile.go b/pkg/chart/v2/lint/rules/chartfile.go index 08508f46e..f867daa21 100644 --- a/pkg/chart/v2/lint/rules/chartfile.go +++ b/pkg/chart/v2/lint/rules/chartfile.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/pkg/chart/v2/lint/rules" +package rules import ( "errors" diff --git a/pkg/chart/v2/lint/rules/dependencies.go b/pkg/chart/v2/lint/rules/dependencies.go index d944a016d..616984c08 100644 --- a/pkg/chart/v2/lint/rules/dependencies.go +++ b/pkg/chart/v2/lint/rules/dependencies.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/pkg/chart/v2/lint/rules" +package rules import ( "fmt" diff --git a/pkg/chart/v2/lint/rules/deprecations.go b/pkg/chart/v2/lint/rules/deprecations.go index 76626659b..2ed682891 100644 --- a/pkg/chart/v2/lint/rules/deprecations.go +++ b/pkg/chart/v2/lint/rules/deprecations.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/pkg/chart/v2/lint/rules" +package rules import ( "fmt" diff --git a/pkg/chart/v2/lint/rules/deprecations_test.go b/pkg/chart/v2/lint/rules/deprecations_test.go index fdeb47e91..0aa983678 100644 --- a/pkg/chart/v2/lint/rules/deprecations_test.go +++ b/pkg/chart/v2/lint/rules/deprecations_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rules // import "helm.sh/helm/v4/pkg/chart/v2/lint/rules" +package rules import ( "testing" diff --git a/pkg/chart/v2/lint/support/doc.go b/pkg/chart/v2/lint/support/doc.go index 7e050b8c2..80b1d2169 100644 --- a/pkg/chart/v2/lint/support/doc.go +++ b/pkg/chart/v2/lint/support/doc.go @@ -20,4 +20,4 @@ Package support contains tools for linting charts. Linting is the process of testing charts for errors or warnings regarding formatting, compilation, or standards compliance. */ -package support // import "helm.sh/helm/v4/pkg/chart/v2/lint/support" +package support diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index 28798de5c..410a9162c 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd // import "helm.sh/helm/v4/pkg/cmd" +package cmd import ( "context" diff --git a/pkg/engine/doc.go b/pkg/engine/doc.go index e764a829a..9bb1059f2 100644 --- a/pkg/engine/doc.go +++ b/pkg/engine/doc.go @@ -21,4 +21,4 @@ When Helm renders templates it does so with additional functions and different modes (e.g., strict, lint mode). This package handles the helm specific implementation. */ -package engine // import "helm.sh/helm/v4/pkg/engine" +package engine diff --git a/pkg/ignore/doc.go b/pkg/ignore/doc.go index a66066eb2..bba658d41 100644 --- a/pkg/ignore/doc.go +++ b/pkg/ignore/doc.go @@ -65,4 +65,4 @@ Notable differences from .gitignore: - The evaluation of escape sequences has not been tested for compatibility - There is no support for '\!' as a special leading sequence. */ -package ignore // import "helm.sh/helm/v4/pkg/ignore" +package ignore diff --git a/pkg/provenance/doc.go b/pkg/provenance/doc.go index dd14568d9..bd60bc593 100644 --- a/pkg/provenance/doc.go +++ b/pkg/provenance/doc.go @@ -35,4 +35,4 @@ and using `gpg --verify`, `keybase pgp verify`, or similar: gpg: Signature made Mon Jul 25 17:23:44 2016 MDT using RSA key ID 1FC18762 gpg: Good signature from "Helm Testing (This key should only be used for testing. DO NOT TRUST.) " [ultimate] */ -package provenance // import "helm.sh/helm/v4/pkg/provenance" +package provenance diff --git a/pkg/registry/chart.go b/pkg/registry/chart.go index 7c41785c5..b8b0d88b6 100644 --- a/pkg/registry/chart.go +++ b/pkg/registry/chart.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package registry // import "helm.sh/helm/v4/pkg/registry" +package registry import ( "bytes" diff --git a/pkg/registry/chart_test.go b/pkg/registry/chart_test.go index e27c3d619..c80544b5b 100644 --- a/pkg/registry/chart_test.go +++ b/pkg/registry/chart_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package registry // import "helm.sh/helm/v4/pkg/registry" +package registry import ( "testing" diff --git a/pkg/registry/client.go b/pkg/registry/client.go index cba346dea..d1a744f4b 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package registry // import "helm.sh/helm/v4/pkg/registry" +package registry import ( "context" diff --git a/pkg/registry/constants.go b/pkg/registry/constants.go index c455cf314..df31a18c4 100644 --- a/pkg/registry/constants.go +++ b/pkg/registry/constants.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package registry // import "helm.sh/helm/v4/pkg/registry" +package registry const ( // OCIScheme is the URL scheme for OCI-based requests diff --git a/pkg/registry/tag.go b/pkg/registry/tag.go index bfb4b1ef6..7e15d0dd9 100644 --- a/pkg/registry/tag.go +++ b/pkg/registry/tag.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package registry // import "helm.sh/helm/v4/pkg/registry" +package registry import ( "fmt" diff --git a/pkg/release/v1/util/filter.go b/pkg/release/v1/util/filter.go index dc60195cf..88ac995d7 100644 --- a/pkg/release/v1/util/filter.go +++ b/pkg/release/v1/util/filter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/pkg/release/v1/util" +package util import ( "helm.sh/helm/v4/pkg/release/common" diff --git a/pkg/release/v1/util/filter_test.go b/pkg/release/v1/util/filter_test.go index d6bda8f84..57d7e6801 100644 --- a/pkg/release/v1/util/filter_test.go +++ b/pkg/release/v1/util/filter_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/pkg/release/v1/util" +package util import ( "testing" diff --git a/pkg/release/v1/util/manifest_test.go b/pkg/release/v1/util/manifest_test.go index 773723c86..e76905a63 100644 --- a/pkg/release/v1/util/manifest_test.go +++ b/pkg/release/v1/util/manifest_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/pkg/release/v1/util" +package util import ( "testing" diff --git a/pkg/release/v1/util/sorter.go b/pkg/release/v1/util/sorter.go index 47506fbf2..e15b87593 100644 --- a/pkg/release/v1/util/sorter.go +++ b/pkg/release/v1/util/sorter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/pkg/release/v1/util" +package util import ( "sort" diff --git a/pkg/release/v1/util/sorter_test.go b/pkg/release/v1/util/sorter_test.go index 0450b09e6..1a3bb3e6a 100644 --- a/pkg/release/v1/util/sorter_test.go +++ b/pkg/release/v1/util/sorter_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util // import "helm.sh/helm/v4/pkg/release/v1/util" +package util import ( "testing" diff --git a/pkg/repo/v1/chartrepo.go b/pkg/repo/v1/chartrepo.go index c7c4a3e7b..42ed52f75 100644 --- a/pkg/repo/v1/chartrepo.go +++ b/pkg/repo/v1/chartrepo.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package repo // import "helm.sh/helm/v4/pkg/repo/v1" +package repo import ( "bytes" diff --git a/pkg/repo/v1/repo.go b/pkg/repo/v1/repo.go index 199b56ed8..be241a0ab 100644 --- a/pkg/repo/v1/repo.go +++ b/pkg/repo/v1/repo.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package repo // import "helm.sh/helm/v4/pkg/repo/v1" +package repo import ( "fmt" diff --git a/pkg/storage/driver/cfgmaps.go b/pkg/storage/driver/cfgmaps.go index 2636755a9..f71ce44f1 100644 --- a/pkg/storage/driver/cfgmaps.go +++ b/pkg/storage/driver/cfgmaps.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "context" diff --git a/pkg/storage/driver/driver.go b/pkg/storage/driver/driver.go index 6efd1dbaa..a7d194d69 100644 --- a/pkg/storage/driver/driver.go +++ b/pkg/storage/driver/driver.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "errors" diff --git a/pkg/storage/driver/labels_test.go b/pkg/storage/driver/labels_test.go index 81e561c15..848ae8861 100644 --- a/pkg/storage/driver/labels_test.go +++ b/pkg/storage/driver/labels_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "testing" diff --git a/pkg/storage/driver/mock_test.go b/pkg/storage/driver/mock_test.go index e62b02f43..ab7b261cf 100644 --- a/pkg/storage/driver/mock_test.go +++ b/pkg/storage/driver/mock_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "context" diff --git a/pkg/storage/driver/records.go b/pkg/storage/driver/records.go index 6b4efef3a..f78b76b8b 100644 --- a/pkg/storage/driver/records.go +++ b/pkg/storage/driver/records.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "sort" diff --git a/pkg/storage/driver/records_test.go b/pkg/storage/driver/records_test.go index 24e4ccb4e..cd1064342 100644 --- a/pkg/storage/driver/records_test.go +++ b/pkg/storage/driver/records_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "reflect" diff --git a/pkg/storage/driver/secrets.go b/pkg/storage/driver/secrets.go index 5e12684df..a1f3e94fc 100644 --- a/pkg/storage/driver/secrets.go +++ b/pkg/storage/driver/secrets.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "context" diff --git a/pkg/storage/driver/sql.go b/pkg/storage/driver/sql.go index 88d24123d..85e6cbd3f 100644 --- a/pkg/storage/driver/sql.go +++ b/pkg/storage/driver/sql.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "fmt" diff --git a/pkg/storage/driver/util.go b/pkg/storage/driver/util.go index 4bc48db23..08c38585c 100644 --- a/pkg/storage/driver/util.go +++ b/pkg/storage/driver/util.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package driver // import "helm.sh/helm/v4/pkg/storage/driver" +package driver import ( "bytes" diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index d5d2ea317..1d7fb9103 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package storage // import "helm.sh/helm/v4/pkg/storage" +package storage import ( "errors" diff --git a/pkg/storage/storage_test.go b/pkg/storage/storage_test.go index 32f926e08..8ecee447f 100644 --- a/pkg/storage/storage_test.go +++ b/pkg/storage/storage_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package storage // import "helm.sh/helm/v4/pkg/storage" +package storage import ( "context" From 3bcf965f997499c477436515e6ccf5d51ab82e5e Mon Sep 17 00:00:00 2001 From: Zhaofeng Miao <522856232@qq.com> Date: Sat, 18 Jul 2026 21:10:36 +0800 Subject: [PATCH 3/3] perf: enable concurrent status computation to prevent multi-minute delays (#32043) * fix: enable concurrent status computation to prevent multi-minute delays Set StatusComputeWorkers=8 on DefaultStatusWatcher for Wait, WaitWithJobs, and WatchUntilReady. This opts in to the async status computation added in fluxcd/cli-utils#20, preventing the informer notification pipeline from being blocked by slow API calls when many resources are updated simultaneously. Without this, status computation for resources like Deployments (which require additional LIST ReplicaSets/Pods calls) runs serially inside the informer, causing growing delays of 1-3+ minutes when upgrading many resources at once (e.g., ~20 Deployments via Helm). Signed-off-by: maplemiao * refactor(kube): expose StatusComputeWorkers as a WaitOption Replace the package-level DefaultStatusComputeWorkers variable with a WithStatusComputeWorkers WaitOption threaded through waitOptions into the statusWaiter. This removes global mutable state from pkg/kube and lets callers opt in explicitly. SDK consumers (e.g. helm-controller) inherit the zero value, which preserves the upstream cli-utils synchronous behavior and avoids an unexpected fan-out of status-compute goroutines when many releases reconcile concurrently. The Helm CLI continues to enable 8 workers by default via a shared pkg/cmd/flags.go helper, so install/upgrade/ rollback/uninstall/test users still get the fix for multi-minute informer stalls out of the box. Signed-off-by: maplemiao * refactor(kube): clamp negative StatusComputeWorkers values to zero Address review feedback: when a caller passes a negative value to WithStatusComputeWorkers, coerce it to zero rather than propagating it to the underlying cli-utils watcher, where the behavior is undefined. Zero is the safe default and matches the SDK opt-in contract. Signed-off-by: maplemiao --------- Signed-off-by: maplemiao Signed-off-by: Maple Miao Co-authored-by: Cursor --- pkg/cmd/flags.go | 20 ++++++++++++++++++++ pkg/cmd/install.go | 1 + pkg/cmd/release_testing.go | 1 + pkg/cmd/rollback.go | 1 + pkg/cmd/uninstall.go | 1 + pkg/cmd/upgrade.go | 2 ++ pkg/kube/client.go | 17 +++++++++-------- pkg/kube/options.go | 35 +++++++++++++++++++++++++++++------ pkg/kube/statuswait.go | 20 ++++++++++++-------- pkg/kube/statuswait_test.go | 22 ++++++++++++++++++++++ 10 files changed, 98 insertions(+), 22 deletions(-) diff --git a/pkg/cmd/flags.go b/pkg/cmd/flags.go index e7db3dde2..e59487044 100644 --- a/pkg/cmd/flags.go +++ b/pkg/cmd/flags.go @@ -65,6 +65,26 @@ func AddWaitFlag(cmd *cobra.Command, wait *kube.WaitStrategy) { cmd.Flags().Lookup("wait").NoOptDefVal = string(kube.StatusWatcherStrategy) } +// cliDefaultStatusComputeWorkers is the number of concurrent status-compute +// workers the Helm CLI enables by default. This prevents the informer +// notification pipeline from being blocked by slow API calls (e.g. LIST +// ReplicaSets/Pods for Deployments) when many resources are updated +// simultaneously. See https://github.com/fluxcd/cli-utils/pull/20. +// +// SDK consumers (e.g. helm-controller) inherit the zero value and can opt in +// via kube.WithStatusComputeWorkers when they want the same behavior. +const cliDefaultStatusComputeWorkers = 8 + +// defaultCLIWaitOptions returns the set of WaitOptions the Helm CLI applies +// by default to every wait-enabled command. Keeping these in one place keeps +// behavior consistent across install/upgrade/rollback/uninstall and makes the +// CLI-vs-SDK default asymmetry explicit. +func defaultCLIWaitOptions() []kube.WaitOption { + return []kube.WaitOption{ + kube.WithStatusComputeWorkers(cliDefaultStatusComputeWorkers), + } +} + type waitValue kube.WaitStrategy func newWaitValue(defaultValue kube.WaitStrategy, ws *kube.WaitStrategy) *waitValue { diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index b935ed4d0..b6cee5843 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -131,6 +131,7 @@ charts in a repository, use 'helm search'. func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client := action.NewInstall(cfg) + client.WaitOptions = append(client.WaitOptions, defaultCLIWaitOptions()...) valueOpts := &values.Options{} var outfmt output.Format diff --git a/pkg/cmd/release_testing.go b/pkg/cmd/release_testing.go index 5a6159e7d..6be83c966 100644 --- a/pkg/cmd/release_testing.go +++ b/pkg/cmd/release_testing.go @@ -40,6 +40,7 @@ The tests to be run are defined in the chart that was installed. func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client := action.NewReleaseTesting(cfg) + client.WaitOptions = append(client.WaitOptions, defaultCLIWaitOptions()...) outfmt := output.Table var outputLogs bool var filter []string diff --git a/pkg/cmd/rollback.go b/pkg/cmd/rollback.go index 01d8b1866..b716dae10 100644 --- a/pkg/cmd/rollback.go +++ b/pkg/cmd/rollback.go @@ -40,6 +40,7 @@ To see revision numbers, run 'helm history RELEASE'. func newRollbackCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client := action.NewRollback(cfg) + client.WaitOptions = append(client.WaitOptions, defaultCLIWaitOptions()...) cmd := &cobra.Command{ Use: "rollback [REVISION]", diff --git a/pkg/cmd/uninstall.go b/pkg/cmd/uninstall.go index bfecd4741..315c29a8d 100644 --- a/pkg/cmd/uninstall.go +++ b/pkg/cmd/uninstall.go @@ -42,6 +42,7 @@ are fully deleted before the command returns. func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client := action.NewUninstall(cfg) + client.WaitOptions = append(client.WaitOptions, defaultCLIWaitOptions()...) cmd := &cobra.Command{ Use: "uninstall RELEASE_NAME [...]", diff --git a/pkg/cmd/upgrade.go b/pkg/cmd/upgrade.go index c038a2149..d0d0166ba 100644 --- a/pkg/cmd/upgrade.go +++ b/pkg/cmd/upgrade.go @@ -84,6 +84,7 @@ which can contain sensitive values. To hide Kubernetes Secrets use the func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client := action.NewUpgrade(cfg) + client.WaitOptions = append(client.WaitOptions, defaultCLIWaitOptions()...) valueOpts := &values.Options{} var outfmt output.Format var createNamespace bool @@ -139,6 +140,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { instClient.SkipCRDs = client.SkipCRDs instClient.Timeout = client.Timeout instClient.WaitStrategy = client.WaitStrategy + instClient.WaitOptions = client.WaitOptions instClient.WaitForJobs = client.WaitForJobs instClient.Devel = client.Devel instClient.Namespace = client.Namespace diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 1dfa88800..bb26fbcc9 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -167,14 +167,15 @@ func (c *Client) newStatusWatcher(opts ...WaitOption) (*statusWaiter, error) { waitContext = c.WaitContext } sw := &statusWaiter{ - restMapper: restMapper, - client: dynamicClient, - ctx: waitContext, - watchUntilReadyCtx: o.watchUntilReadyCtx, - waitCtx: o.waitCtx, - waitWithJobsCtx: o.waitWithJobsCtx, - waitForDeleteCtx: o.waitForDeleteCtx, - readers: o.statusReaders, + restMapper: restMapper, + client: dynamicClient, + ctx: waitContext, + watchUntilReadyCtx: o.watchUntilReadyCtx, + waitCtx: o.waitCtx, + waitWithJobsCtx: o.waitWithJobsCtx, + waitForDeleteCtx: o.waitForDeleteCtx, + readers: o.statusReaders, + statusComputeWorkers: o.statusComputeWorkers, } sw.SetLogger(c.Logger().Handler()) return sw, nil diff --git a/pkg/kube/options.go b/pkg/kube/options.go index 3326c284b..7853cb63a 100644 --- a/pkg/kube/options.go +++ b/pkg/kube/options.go @@ -72,11 +72,34 @@ func WithKStatusReaders(readers ...engine.StatusReader) WaitOption { } } +// WithStatusComputeWorkers sets the number of concurrent goroutines used to +// compute object status per informer. This prevents the informer notification +// pipeline from being blocked by slow API calls (e.g., LIST ReplicaSets/Pods +// for Deployments) when many resources are updated simultaneously. +// +// A value of 0 (the default) keeps the underlying cli-utils behavior, where +// status is computed synchronously on the informer goroutine. Negative values +// are clamped to 0 so callers cannot propagate invalid counts to the +// underlying watcher. SDK consumers (for example helm-controller) inherit +// this conservative default and can opt in explicitly. The Helm CLI passes +// a non-zero value so that `helm install/upgrade/rollback` users get the +// fix for multi-minute waits out of the box. +// See https://github.com/fluxcd/cli-utils/pull/20. +func WithStatusComputeWorkers(n int) WaitOption { + return func(wo *waitOptions) { + if n < 0 { + n = 0 + } + wo.statusComputeWorkers = n + } +} + type waitOptions struct { - ctx context.Context - watchUntilReadyCtx context.Context - waitCtx context.Context - waitWithJobsCtx context.Context - waitForDeleteCtx context.Context - statusReaders []engine.StatusReader + ctx context.Context + watchUntilReadyCtx context.Context + waitCtx context.Context + waitWithJobsCtx context.Context + waitForDeleteCtx context.Context + statusReaders []engine.StatusReader + statusComputeWorkers int } diff --git a/pkg/kube/statuswait.go b/pkg/kube/statuswait.go index 12c3e95a6..91eec30ef 100644 --- a/pkg/kube/statuswait.go +++ b/pkg/kube/statuswait.go @@ -43,14 +43,15 @@ import ( ) type statusWaiter struct { - client dynamic.Interface - restMapper meta.RESTMapper - ctx context.Context - watchUntilReadyCtx context.Context - waitCtx context.Context - waitWithJobsCtx context.Context - waitForDeleteCtx context.Context - readers []engine.StatusReader + client dynamic.Interface + restMapper meta.RESTMapper + ctx context.Context + watchUntilReadyCtx context.Context + waitCtx context.Context + waitWithJobsCtx context.Context + waitForDeleteCtx context.Context + readers []engine.StatusReader + statusComputeWorkers int logging.LogHolder } @@ -82,6 +83,7 @@ func (w *statusWaiter) WatchUntilReady(resourceList ResourceList, timeout time.D defer cancel() w.Logger().Debug("waiting for resources", "count", len(resourceList), "timeout", timeout) sw := getStatusWatcher(w.client, w.restMapper) + sw.StatusComputeWorkers = w.statusComputeWorkers jobSR := helmStatusReaders.NewCustomJobStatusReader(w.restMapper) podSR := helmStatusReaders.NewCustomPodStatusReader(w.restMapper) // We don't want to wait on any other resources as watchUntilReady is only for Helm hooks. @@ -104,6 +106,7 @@ func (w *statusWaiter) Wait(resourceList ResourceList, timeout time.Duration) er defer cancel() w.Logger().Debug("waiting for resources", "count", len(resourceList), "timeout", timeout) sw := getStatusWatcher(w.client, w.restMapper) + sw.StatusComputeWorkers = w.statusComputeWorkers sw.StatusReader = statusreaders.NewStatusReader(w.restMapper, w.readers...) return w.wait(ctx, resourceList, sw) } @@ -116,6 +119,7 @@ func (w *statusWaiter) WaitWithJobs(resourceList ResourceList, timeout time.Dura defer cancel() w.Logger().Debug("waiting for resources", "count", len(resourceList), "timeout", timeout) sw := getStatusWatcher(w.client, w.restMapper) + sw.StatusComputeWorkers = w.statusComputeWorkers newCustomJobStatusReader := helmStatusReaders.NewCustomJobStatusReader(w.restMapper) readers := append([]engine.StatusReader(nil), w.readers...) readers = append(readers, newCustomJobStatusReader) diff --git a/pkg/kube/statuswait_test.go b/pkg/kube/statuswait_test.go index 14f10124c..21580b57a 100644 --- a/pkg/kube/statuswait_test.go +++ b/pkg/kube/statuswait_test.go @@ -1293,6 +1293,28 @@ func TestWaitOptionFunctions(t *testing.T) { WithWaitForDeleteMethodContext(ctx)(opts) assert.Equal(t, ctx, opts.waitForDeleteCtx) }) + + t.Run("WithStatusComputeWorkers sets statusComputeWorkers", func(t *testing.T) { + t.Parallel() + opts := &waitOptions{} + WithStatusComputeWorkers(8)(opts) + assert.Equal(t, 8, opts.statusComputeWorkers) + }) + + t.Run("WithStatusComputeWorkers clamps negative values to zero", func(t *testing.T) { + t.Parallel() + opts := &waitOptions{} + WithStatusComputeWorkers(-1)(opts) + assert.Equal(t, 0, opts.statusComputeWorkers, + "negative worker counts must not propagate to the underlying watcher") + }) + + t.Run("waitOptions.statusComputeWorkers defaults to zero", func(t *testing.T) { + t.Parallel() + opts := &waitOptions{} + assert.Equal(t, 0, opts.statusComputeWorkers, + "SDK consumers must opt in to concurrent status computation") + }) } func TestMethodSpecificContextCancellation(t *testing.T) {