test(values): cover subchart-default nil cleanup when parent has unrelated user values#32092
test(values): cover subchart-default nil cleanup when parent has unrelated user values#32092
Conversation
…nrelated user-defined values Signed-off-by: Johannes Lohmer <jojo.dev@lohmer.com>
ffd4a52 to
2911c68
Compare
There was a problem hiding this comment.
Pull request overview
Adds regression test coverage for a values-coalescing edge case where subchart default nil values can survive coalescing when the parent supplies any value under the subchart key, and updates an existing engine render test to exercise the dependency-processing path.
Changes:
- Update
TestRenderSubchartDefaultNilNoStringifyto callProcessDependenciesand inject a subchart user value to follow the “real” coalesce path. - Add new dependency-processing/coalescing tests covering baseline and two regression scenarios around subchart default
nilcleanup. - Introduce small test helpers to build charts and run
ProcessDependencies+ coalescing.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| pkg/engine/engine_test.go | Adjusts an existing render regression test to include dependency processing and a subchart user value. |
| pkg/chart/v2/util/dependencies_test.go | Adds unit tests and helpers to cover subchart default nil cleanup behavior across coalescing scenarios. |
Comments suppressed due to low confidence (1)
pkg/engine/engine_test.go:1577
- This test now injects a value under the
childkey, which forces the child-chart merge path (merge=true) during coalescing; with the current implementation that bypassescleanNilValues, the rendered template is expected to include%!s(<nil>), so the test will fail until the underlying coalesce behavior is fixed. If this PR is intended to be mergeable on its own, these assertions need to be skipped/adjusted or the functional fix needs to land together with the test.
injValues := map[string]any{
"child": map[string]any{
"someOtherKey": "someValue",
},
}
if err := chartutil.ProcessDependencies(parent, injValues); err != nil {
t.Fatalf("Failed to process dependencies: %s", err)
}
tmp, err := util.CoalesceValues(parent, injValues)
if err != nil {
t.Fatalf("Failed to coalesce values: %s", err)
}
inject := common.Values{
"Values": tmp,
"Chart": parent.Metadata,
"Release": common.Values{
"Name": "test-release",
},
}
out, err := Render(parent, inject)
if err != nil {
t.Fatalf("Failed to render templates: %s", err)
}
rendered := out["parent/charts/child/templates/test.yaml"]
if strings.Contains(rendered, "%!s(<nil>)") {
t.Errorf("Rendered output contains %%!s(<nil>), got: %q", rendered)
}
expected := "subPath: fallback"
if rendered != expected {
t.Errorf("Expected %q, got %q", expected, rendered)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func processAndCoalesce(t *testing.T, parent *chart.Chart, vals common.Values) common.Values { | ||
| t.Helper() | ||
| require.NoError(t, ProcessDependencies(parent, vals)) | ||
| coalesced, err := commonutil.CoalesceValues(parent, vals) |
There was a problem hiding this comment.
commonutil.CoalesceValues expects a map[string]any, but this helper passes vals as common.Values (a distinct defined type), which won’t compile. Convert with vals.AsMap() (or map[string]any(vals)) when calling CoalesceValues.
| coalesced, err := commonutil.CoalesceValues(parent, vals) | |
| coalesced, err := commonutil.CoalesceValues(parent, vals.AsMap()) |
| // Any user value under "child" routes coalescing through merge=true and | ||
| // bypasses cleanNilValues. Covers #31919 and #31971. | ||
| func TestProcessDependenciesNilCleanedWithUnrelatedSubchartVals(t *testing.T) { | ||
| is := assert.New(t) | ||
| coalesced := processAndCoalesce(t, newParentWithNilSubchart(), common.Values{ | ||
| "child": map[string]any{ | ||
| "someOtherKey": "someValue", | ||
| }, | ||
| "global": map[string]any{ | ||
| "ingress": map[string]any{ | ||
| "configureCertmanager": true, | ||
| }, | ||
| }, | ||
| }) | ||
|
|
||
| _, err := common.Values(coalesced).PathValue("child.keyMapping.password") | ||
| is.ErrorAs(err, &common.ErrNoValue{}, "child.keyMapping.password should be absent") | ||
|
|
||
| _, err = common.Values(coalesced).PathValue("child.ingress.configureCertmanager") | ||
| is.ErrorAs(err, &common.ErrNoValue{}, "child.ingress.configureCertmanager should be absent so pluck falls through to global") | ||
| } |
There was a problem hiding this comment.
These new tests assert that subchart-default nil entries are removed even when a user supplies any value under the subchart key (the merge=true path). With the current coalescing logic (coalesceValues skips cleanNilValues when merging child chart tables), these tests will fail in CI until the functional fix is included. If this PR is meant to be mergeable independently, mark these cases as skipped or adjust expectations; otherwise, consider bundling the fix with the tests.
| injValues := map[string]any{ | ||
| "child": map[string]any{ | ||
| "someOtherKey": "someValue", | ||
| }, | ||
| } | ||
|
|
||
| if err := chartutil.ProcessDependencies(parent, injValues); err != nil { | ||
| t.Fatalf("Failed to process dependencies: %s", err) | ||
| } | ||
|
|
||
| tmp, err := util.CoalesceValues(parent, injValues) | ||
| if err != nil { |
There was a problem hiding this comment.
chartutil.ProcessDependencies takes common.Values, but injValues is declared as map[string]any, which won’t compile (distinct defined type). Consider declaring injValues as common.Values (or converting when calling ProcessDependencies) and pass injValues.AsMap() (or a map[string]any conversion) into util.CoalesceValues which expects map[string]any.
| is := assert.New(t) | ||
| coalesced := processAndCoalesce(t, newParentWithNilSubchart(), common.Values{ | ||
| "child": map[string]any{ | ||
| "someOtherKey": "someValue", |
There was a problem hiding this comment.
The really nefarious part of this bug / regression is, that helms behaviour changes when the end user configures a completely unrelated part of the sub-chart.
Failing tests pinning the gap left open after #31979: when the parent supplies any value under a subchart, coalescing routes through
merge=trueand bypassescleanNilValues, so subchart-default nils survive.Adds in
pkg/chart/v2/util/dependencies_test.go:…NoUserSubchartVals— baseline, passes.…WithUnrelatedSubchartVals— fails; unrelated sibling key triggers the leak.…WithPartialSameMapVals— fails; sibling nil in same map survives an override.Also tightens
TestRenderSubchartDefaultNilNoStringifyto callProcessDependencies, matching the real coalesce path. Tests-only; baseline for the follow-up fix.Special notes for your reviewer:
So far just adds test coverage for the remaining nil values merge regression.
I did not want to pollute the PR with an AI Slop "fix".
If applicable: