From a8e8b670866d5676f89238d147bbc5d36de5e496 Mon Sep 17 00:00:00 2001 From: yxxhero <11087727+yxxhero@users.noreply.github.com> Date: Sat, 2 May 2026 10:04:28 +0800 Subject: [PATCH] fix: use --post-renderer-args=VALUE format to prevent Helm flag parsing failure (#2570) * fix: use --post-renderer-args=VALUE format to prevent Helm flag parsing failure When postRendererArgs contains values like short flags (e.g. -v), passing --post-renderer-args and the value as separate arguments causes Helm to interpret the value as its own flag. Using the --post-renderer-args=VALUE format unambiguously binds the value to the flag. Fixes #2563 Signed-off-by: yxxhero * fix: update hasFlagWithValue doc/errors and add -v short-flag test cases - Update hasFlagWithValue doc comment to describe both '--flag value' and '--flag=value' forms - Update t.Errorf messages in app_test.go to reflect both accepted formats - Add 'post-renderer-args-short-flag-value' test case (-v) to both TestHelmState_flagsForUpgrade and TestHelmState_flagsForTemplate to verify --post-renderer-args=-v emission (core regression from #2563) Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/dd95f046-358b-4867-9069-9432c1b5318e Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com> --------- Signed-off-by: yxxhero Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- pkg/app/app_test.go | 14 ++++++--- pkg/state/helmx.go | 2 +- pkg/state/state_test.go | 68 +++++++++++++++++++++++++++++++++-------- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index aa792b33..f979544c 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -3100,12 +3100,16 @@ func newPostRendererTestApp(t *testing.T, files map[string]string) (*App, *mockH return app, helm } -// hasFlagWithValue reports whether flags contains "--flagName value" as adjacent entries. +// hasFlagWithValue reports whether flags contains either "--flagName value" as adjacent entries +// or "--flagName=value" as a single entry. func hasFlagWithValue(flags []string, flagName, value string) bool { for i, f := range flags { if f == flagName && i+1 < len(flags) && flags[i+1] == value { return true } + if f == flagName+"="+value { + return true + } } return false } @@ -3162,10 +3166,10 @@ releases: t.Errorf("expected --post-renderer foo in flags, got %v", flags) } if !hasFlagWithValue(flags, "--post-renderer-args", "--arg1") { - t.Errorf("expected --post-renderer-args --arg1 in flags, got %v", flags) + t.Errorf("expected --post-renderer-args=--arg1 or --post-renderer-args --arg1 in flags, got %v", flags) } if !hasFlagWithValue(flags, "--post-renderer-args", "--arg2") { - t.Errorf("expected --post-renderer-args --arg2 in flags, got %v", flags) + t.Errorf("expected --post-renderer-args=--arg2 or --post-renderer-args --arg2 in flags, got %v", flags) } }) } @@ -3219,7 +3223,7 @@ releases: flags := helm.templated[0].flags if !hasFlagWithValue(flags, "--post-renderer-args", "--cli-arg") { - t.Errorf("expected --post-renderer-args --cli-arg in flags (CLI should override helmDefaults), got %v", flags) + t.Errorf("expected --post-renderer-args=--cli-arg or --post-renderer-args --cli-arg in flags (CLI should override helmDefaults), got %v", flags) } if hasFlagWithValue(flags, "--post-renderer-args", "--default-arg") { t.Errorf("unexpected --post-renderer-args --default-arg in flags (CLI should override helmDefaults), got %v", flags) @@ -3276,7 +3280,7 @@ releases: flags := helm.templated[0].flags if !hasFlagWithValue(flags, "--post-renderer-args", "--release-arg") { - t.Errorf("expected --post-renderer-args --release-arg in flags (release should override CLI), got %v", flags) + t.Errorf("expected --post-renderer-args=--release-arg or --post-renderer-args --release-arg in flags (release should override CLI), got %v", flags) } if hasFlagWithValue(flags, "--post-renderer-args", "--cli-arg") { t.Errorf("unexpected --post-renderer-args --cli-arg in flags (release should override CLI), got %v", flags) diff --git a/pkg/state/helmx.go b/pkg/state/helmx.go index f1a2daeb..ada74c88 100644 --- a/pkg/state/helmx.go +++ b/pkg/state/helmx.go @@ -127,7 +127,7 @@ func (st *HelmState) appendPostRenderArgsFlags(flags []string, release *ReleaseS } for _, arg := range postRendererArgsFlags { if arg != "" { - flags = append(flags, "--post-renderer-args", arg) + flags = append(flags, "--post-renderer-args="+arg) } } return flags diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index 0d10624a..8e6f2ba9 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -926,8 +926,8 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--arg1", - "--post-renderer-args", "--arg2", + "--post-renderer-args=--arg1", + "--post-renderer-args=--arg2", "--namespace", "test-namespace", }, }, @@ -949,7 +949,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--release-arg", + "--post-renderer-args=--release-arg", "--namespace", "test-namespace", }, }, @@ -972,7 +972,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--release-arg", + "--post-renderer-args=--release-arg", "--namespace", "test-namespace", }, }, @@ -997,7 +997,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--cli-arg", + "--post-renderer-args=--cli-arg", "--namespace", "test-namespace", }, }, @@ -1022,7 +1022,29 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--release-arg", + "--post-renderer-args=--release-arg", + "--namespace", "test-namespace", + }, + }, + { + name: "post-renderer-args-short-flag-value", + defaults: HelmSpec{ + Verify: false, + CreateNamespace: &enable, + }, + version: semver.MustParse("3.10.0"), + release: &ReleaseSpec{ + Chart: "test/chart", + Version: "0.1", + Verify: &disable, + Name: "test-charts", + Namespace: "test-namespace", + CreateNamespace: &disable, + PostRendererArgs: []string{"-v"}, + }, + want: []string{ + "--version", "0.1", + "--post-renderer-args=-v", "--namespace", "test-namespace", }, }, @@ -1340,8 +1362,8 @@ func TestHelmState_flagsForTemplate(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--arg1", - "--post-renderer-args", "--arg2", + "--post-renderer-args=--arg1", + "--post-renderer-args=--arg2", "--namespace", "test-namespace", }, }, @@ -1363,7 +1385,7 @@ func TestHelmState_flagsForTemplate(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--release-arg", + "--post-renderer-args=--release-arg", "--namespace", "test-namespace", }, }, @@ -1386,7 +1408,7 @@ func TestHelmState_flagsForTemplate(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--release-arg", + "--post-renderer-args=--release-arg", "--namespace", "test-namespace", }, }, @@ -1411,7 +1433,7 @@ func TestHelmState_flagsForTemplate(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--cli-arg", + "--post-renderer-args=--cli-arg", "--namespace", "test-namespace", }, }, @@ -1436,7 +1458,29 @@ func TestHelmState_flagsForTemplate(t *testing.T) { }, want: []string{ "--version", "0.1", - "--post-renderer-args", "--release-arg", + "--post-renderer-args=--release-arg", + "--namespace", "test-namespace", + }, + }, + { + name: "post-renderer-args-short-flag-value", + defaults: HelmSpec{ + Verify: false, + CreateNamespace: &enable, + }, + version: semver.MustParse("3.10.0"), + release: &ReleaseSpec{ + Chart: "test/chart", + Version: "0.1", + Verify: &disable, + Name: "test-charts", + Namespace: "test-namespace", + CreateNamespace: &disable, + PostRendererArgs: []string{"-v"}, + }, + want: []string{ + "--version", "0.1", + "--post-renderer-args=-v", "--namespace", "test-namespace", }, },