fix: sanitize defaultInherit values and dedupe applied templates

Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/85a8e815-3701-4b48-a28d-6bb2d50a3b40

Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-05-20 03:23:55 +00:00 committed by GitHub
parent 9d01a9341d
commit 05e5313ab8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 58 additions and 6 deletions

View File

@ -522,19 +522,41 @@ func (r *Inherits) UnmarshalYAML(unmarshal func(any) error) error {
type DefaultInherits []string
func (r *DefaultInherits) UnmarshalYAML(unmarshal func(any) error) error {
var single string
if err := unmarshal(&single); err == nil {
*r = []string{single}
var list []string
if err := unmarshal(&list); err == nil {
*r = normalizeDefaultInherits(list)
return nil
}
var list []string
if err := unmarshal(&list); err != nil {
var single string
if err := unmarshal(&single); err != nil {
return err
}
*r = list
*r = normalizeDefaultInherits([]string{single})
return nil
}
func normalizeDefaultInherits(in []string) []string {
if len(in) == 0 {
return nil
}
out := make([]string, 0, len(in))
for _, name := range in {
name = strings.TrimSpace(name)
if name == "" {
continue
}
out = append(out, name)
}
if len(out) == 0 {
return nil
}
return out
}
// ChartPathOrName returns ChartPath if it is non-empty, and returns Chart otherwise.
// This is useful to redirect helm commands like `helm template`, `helm dependency update`, `helm diff`, and `helm upgrade --install` to
// our modified version of the chart, in case the user configured Helmfile to do modify the chart before being passed to Helm.

View File

@ -237,13 +237,22 @@ func (st *HelmState) applyDefaultInherit(releaseInherit Inherits) Inherits {
existing := make(map[string]bool, len(releaseInherit))
for _, inh := range releaseInherit {
if inh.Template == "" {
continue
}
existing[inh.Template] = true
}
result := make(Inherits, 0, len(st.DefaultInherit)+len(releaseInherit))
for _, name := range st.DefaultInherit {
name = strings.TrimSpace(name)
if name == "" {
continue
}
if !existing[name] {
result = append(result, Inherit{Template: name})
existing[name] = true
}
}
result = append(result, releaseInherit...)

View File

@ -334,6 +334,12 @@ func TestApplyDefaultInherit(t *testing.T) {
releaseInherit: nil,
want: Inherits{{Template: "default"}},
},
{
name: "default inherit deduplicates and skips empty values",
defaultInherit: DefaultInherits{"default", " ", "default", "ops"},
releaseInherit: Inherits{{Template: "foo"}},
want: Inherits{{Template: "default"}, {Template: "ops"}, {Template: "foo"}},
},
}
for i := range tests {
@ -437,6 +443,21 @@ func TestDefaultInherits_UnmarshalYAML(t *testing.T) {
input: `["a", "b"]`,
want: DefaultInherits{"a", "b"},
},
{
name: "null value",
input: `null`,
want: nil,
},
{
name: "empty string value",
input: `""`,
want: nil,
},
{
name: "list trims and drops empty names",
input: `[" a ", "", " ", "b"]`,
want: DefaultInherits{"a", "b"},
},
}
for _, tt := range tests {