Conversation
Add native --kube-context flag to all helm-diff commands (upgrade, revision, rollback, release) to allow users to specify kubeconfig context directly instead of relying on HELM_KUBECONTEXT environment variable workaround. Fixes #603 Signed-off-by: yxxhero <aiopsclub@163.com>
There was a problem hiding this comment.
Pull request overview
This PR adds first-class support for a --kube-context flag across helm-diff commands so users can select a kubeconfig context without relying solely on the HELM_KUBECONTEXT workaround, and ensures that this context is consistently propagated to underlying Helm operations.
Changes:
- Extend
diffCmd,revision,rollback, andreleasestructs to carry akubeContextfield and expose a--kube-contextflag onupgrade,revision,rollback, andreleasecommands. - Thread
kubeContextthrough helper functions (getRelease,getHooks,getRevision,getChart), the templating path, and value-reuse logic so Helm CLI invocations receive--kube-context(and--namespacewhere appropriate). - For three-way-merge/ownership flows, set
envSettings.KubeContextbefore initializingaction.Configurationso the Helm SDK also respects the chosen context.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| cmd/upgrade.go | Adds kubeContext to diffCmd, wires a --kube-context flag into helm diff upgrade, and passes the context through to getRelease, getHooks, template, and the Helm SDK action configuration where three-way merge/ownership is used. |
| cmd/rollback.go | Adds a kubeContext field and --kube-context flag to the rollback command and passes that context into getRelease/getRevision calls so rollbacks use the selected kube context. |
| cmd/revision.go | Extends the revision command with a kubeContext field and flag and forwards it into getRelease/getRevision so revision comparisons run against the correct context. |
| cmd/release.go | Adds kubeContext support and flag to the release comparison command and threads it into getRelease/getChart for both releases being compared. |
| cmd/helm.go | Updates Helm helper functions to accept and append --kube-context (and now --namespace for some calls) and ensures template and writeExistingValues propagate the selected context to the underlying helm CLI. |
| func getHooks(release, namespace, kubeContext string) ([]byte, error) { | ||
| args := []string{"get", "hooks", release} | ||
| if namespace != "" { | ||
| args = append(args, "--namespace", namespace) | ||
| } |
There was a problem hiding this comment.
The new kubeContext plumbing in the Helm CLI helper functions (e.g., getRelease/getHooks/getRevision/getChart) is not covered by tests, even though we use a fake HELM_BIN in main_test.go to assert exact argument lists. It would be good to add tests that run a diff command with --kube-context and extend the stubs to expect the --kube-context flag so regressions in how the context is forwarded to Helm are caught early.
| flags = append(flags, "--namespace", d.namespace) | ||
| } | ||
| if d.kubeContext != "" { | ||
| flags = append(flags, "--kube-context", d.kubeContext) | ||
| } |
There was a problem hiding this comment.
template now appends --kube-context (and --namespace) to the Helm CLI flags, but there is no test asserting that these flags are actually passed through. Please add coverage (using the fake HELM_BIN harness) for a helm diff upgrade invocation with --kube-context so changes to this flag wiring do not silently break context selection.
| if d.namespace != "" { | ||
| args = append(args, "--namespace", d.namespace) | ||
| } | ||
| if d.kubeContext != "" { | ||
| args = append(args, "--kube-context", d.kubeContext) |
There was a problem hiding this comment.
writeExistingValues now forwards --namespace and --kube-context to helm get values, but this behavior is not exercised by tests. Consider adding a test path that triggers value reuse (e.g., --reuse-values/--reset-then-reuse-values) with --kube-context set and updating the fake Helm stubs to expect these flags, to ensure existing-values resolution stays aligned with the selected kube context.
Add tests to verify that --kube-context flag is properly passed to helm commands, addressing review comments from PR #924: - Test basic --kube-context flag propagation to helm commands - Test --kube-context with --reuse-values flag - Test that --namespace is also passed when using --kube-context - Add wildcard argument matching for dynamic temp file paths Signed-off-by: yxxhero <aiopsclub@163.com>
…commands Signed-off-by: yxxhero <aiopsclub@163.com>
cmd/upgrade.go
Outdated
| if d.kubeContext != "" { | ||
| envSettings.KubeContext = d.kubeContext | ||
| } | ||
| if err := actionConfig.Init(envSettings.RESTClientGetter(), envSettings.Namespace(), os.Getenv("HELM_DRIVER")); err != nil { |
There was a problem hiding this comment.
envSettings is a package-level variable and runHelm3 mutates envSettings.KubeContext when --kube-context is set. Because it is not reset, subsequent executions in the same process (e.g., tests or library usage) can unintentionally reuse the previous kube context, and it also introduces a potential data race if commands are ever run concurrently. Prefer using a fresh cli.New() (or copying the settings) inside runHelm3 for actionConfig.Init, or save/restore the previous KubeContext value around the initialization.
| if d.kubeContext != "" { | |
| envSettings.KubeContext = d.kubeContext | |
| } | |
| if err := actionConfig.Init(envSettings.RESTClientGetter(), envSettings.Namespace(), os.Getenv("HELM_DRIVER")); err != nil { | |
| // Use a fresh copy of envSettings to avoid mutating shared state. | |
| localEnv := cli.New() | |
| *localEnv = *envSettings | |
| if d.kubeContext != "" { | |
| localEnv.KubeContext = d.kubeContext | |
| } | |
| if err := actionConfig.Init(localEnv.RESTClientGetter(), localEnv.Namespace(), os.Getenv("HELM_DRIVER")); err != nil { |
main_test.go
Outdated
| }, | ||
| { | ||
| cmd: []string{"get", "values"}, | ||
| args: []string{"test-release", "--output", "yaml", "--all", "--kube-context", "test-context", "--namespace", "*"}, |
There was a problem hiding this comment.
The fake helm stub for get values with both --kube-context and --namespace has the flags in a different order than the production code builds them (writeExistingValues appends --namespace before --kube-context). If a test run happens to set HELM_NAMESPACE (making d.namespace non-empty), the actual invocation will be ... --namespace <ns> --kube-context test-context and this stub won't match, causing a hard-to-diagnose test failure. Update the stub (or matching logic) so it matches the real argument order.
| args: []string{"test-release", "--output", "yaml", "--all", "--kube-context", "test-context", "--namespace", "*"}, | |
| args: []string{"test-release", "--output", "yaml", "--all", "--namespace", "*", "--kube-context", "test-context"}, |
| func TestHelmDiffWithKubeContext(t *testing.T) { | ||
| os.Setenv(env, envValue) | ||
| defer os.Unsetenv(env) | ||
|
|
||
| helmBin, helmBinSet := os.LookupEnv("HELM_BIN") | ||
| os.Setenv("HELM_BIN", os.Args[0]) | ||
| defer func() { | ||
| if helmBinSet { | ||
| os.Setenv("HELM_BIN", helmBin) | ||
| } else { | ||
| os.Unsetenv("HELM_BIN") | ||
| } | ||
| }() | ||
|
|
||
| oldArgs := os.Args | ||
| defer func() { os.Args = oldArgs }() | ||
|
|
||
| os.Args = []string{"helm-diff", "upgrade", "-f", "test/testdata/test-values.yaml", "--kube-context", "test-context", "test-release", "test/testdata/test-chart"} | ||
| require.NoError(t, cmd.New().Execute()) | ||
| } |
There was a problem hiding this comment.
These tests duplicate the same environment setup/teardown logic (BECOME_FAKE_HELM, HELM_BIN, and os.Args) across many functions, which makes future edits error-prone. Consider extracting a small helper (or a table-driven test) to centralize this setup and reduce repetition.
- Use local copy of envSettings in actionConfig.Init to avoid mutating shared state and prevent data races - Fix test stub flag order to match production code (--namespace before --kube-context) - Extract helmDiffTestHelper to reduce duplicated test setup code Signed-off-by: yxxhero <aiopsclub@163.com>
Summary
--kube-contextflag to all helm-diff commands (upgrade, revision, rollback, release)HELM_KUBECONTEXTenvironment variableChanges
kubeContextfield to command structs (diffCmd, revision, rollback, release)getRelease,getHooks,getRevision, andgetChartfunctions to accept and usekubeContextparameter--kube-contextflag to all commandsFixes #603