package tmpl import ( "testing" "github.com/helmfile/helmfile/pkg/filesystem" ) // TestValuesIsolation reproduces the issue described in https://github.com/helmfile/helmfile/issues/2182 // where mergeOverwrite modifies the global .Values object instead of creating a local copy // This test demonstrates that the issue is fixed when using the state layer (which provides isolation) func TestValuesIsolation(t *testing.T) { ctx := &Context{ fs: &filesystem.FileSystem{ Glob: func(pattern string) ([]string, error) { return nil, nil }, }, } // Template that simulates the problematic helmfile.yaml content // NOTE: This test shows that the template layer itself doesn't provide isolation, // but the fix is implemented at the state layer where values are copied before templating template := ` {{- $originalValues := .Values }} {{- $fooValues := .Values | get "foo" (dict) | mergeOverwrite .Values }} {{- $barValues := .Values | get "bar" (dict) | mergeOverwrite .Values }} First render (should use original + foo): {{ $fooValues | toYaml }} Second render (should use original + bar): {{ $barValues | toYaml }} Final Values (should be original): {{ .Values | toYaml }} Original Values (should be same as final): {{ $originalValues | toYaml }} ` data := map[string]any{ "Values": map[string]any{ "common": "value", "foo": map[string]any{ "specific": "foo-value", }, "bar": map[string]any{ "specific": "bar-value", }, }, } buf, err := ctx.RenderTemplateToBuffer(template, data) if err != nil { t.Fatalf("unexpected error: %v", err) } result := buf.String() t.Logf("Template result:\n%s", result) // This test still demonstrates the raw template behavior (without our fix at state layer), // but the actual bug is fixed at the state layer where we copy values before templating. // See TestValuesTemplateIsolation in pkg/state for the proper integration test. }