build: update Go to 1.27.1 and modernize the codebase (#2798)

Toolchain and CI:
- Bump go directive from 1.26.8 to 1.27.1 (go.mod)
- Use golang:1.27-alpine builder images in all Dockerfiles
- Bump golangci-lint to v2.13.2 (first release with go1.27 support)
- Add CI gate: `go fix -diff` fails when outdated Go patterns are
  detected (locally: `make check-modernize`)

Note: darwin binaries now require macOS 13 or later.

Lint fixes required by golangci-lint v2.13.2:
- goconst: ignore tests (all 436 findings were test-only; goconst
  got stricter since v2.12 and this option was added for it)
- openai.go: keep deprecated MaxTokens deliberately with a nolint
  rationale (max_tokens is the only form universally supported by
  OpenAI-compatible backends like One-API, LiteLLM, Ollama shim)
- state.go: drop always-nil flags param from appendChartVersionFlags
  (renamed to chartVersionFlags, unparam)

Modernization (go fix ./..., 62 files):
- interface{} -> any, maps.Copy, strings.SplitSeq, range-over-int,
  builtin min/max, slices.Contains/ContainsFunc/Sort, WaitGroup.Go,
  reflect.Type.Fields(), new(expr)
- exit_error.go: strings.Builder + fmt.Fprintf instead of string
  concatenation and WriteString(fmt.Sprintf(...)) (QF1012)
- chart_dependency.go: strings.CutLast for OCI dependency helpers

Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
yxxhero
2026-09-16 13:29:02 +08:00
committed by GitHub
co-authored by Claude
parent 88be4012b1
commit ad81e4231e
65 changed files with 710 additions and 941 deletions
+1 -1
View File
@@ -549,7 +549,7 @@ dependencies:
errCh := make(chan error, numGoroutines)
ready := make(chan struct{})
for i := 0; i < numGoroutines; i++ {
for range numGoroutines {
wg.Add(1)
readyWg.Add(1)
go func() {
+6 -5
View File
@@ -260,8 +260,8 @@ func chartDependenciesAlias(namespace, releaseName string) string {
// the chart path when helm processes OCI references during dependency update.
// See issue #954.
func ociDependencyChartName(chart string) string {
if idx := strings.LastIndex(chart, "/"); idx >= 0 {
return chart[idx+1:]
if _, name, found := strings.CutLast(chart, "/"); found {
return name
}
return chart
}
@@ -273,10 +273,11 @@ func ociDependencyChartName(chart string) string {
// chart="path_with_underscores/example", baseURL="oci://registry.example.com"
// → "oci://registry.example.com/path_with_underscores"
func ociDependencyRepoURL(chart, ociBaseURL string) string {
if idx := strings.LastIndex(chart, "/"); idx >= 0 {
return strings.TrimSuffix(ociBaseURL, "/") + "/" + chart[:idx]
pathPrefix, _, found := strings.CutLast(chart, "/")
if !found {
return ociBaseURL
}
return ociBaseURL
return strings.TrimSuffix(ociBaseURL, "/") + "/" + pathPrefix
}
func getUnresolvedDependenciess(st *HelmState) (string, *UnresolvedDependencies) {
+65 -71
View File
@@ -80,27 +80,25 @@ func TestGetUnresolvedDependenciess(t *testing.T) {
name: "oci chart with path prefix and underscores (issue #954)",
helmState: &HelmState{
FilePath: "helmfile.yaml",
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{
{
Name: "example",
Chart: "myrepo/path_with_underscores/example",
Version: "1.0.0",
Namespace: "myns",
},
{
Name: "another",
Chart: "myrepo/another_path/chart",
Version: "2.0.0",
Namespace: "myns",
},
Releases: []ReleaseSpec{
{
Name: "example",
Chart: "myrepo/path_with_underscores/example",
Version: "1.0.0",
Namespace: "myns",
},
Repositories: []RepositorySpec{
{
Name: "myrepo",
URL: "harbor.custom.com",
OCI: true,
},
{
Name: "another",
Chart: "myrepo/another_path/chart",
Version: "2.0.0",
Namespace: "myns",
},
},
Repositories: []RepositorySpec{
{
Name: "myrepo",
URL: "harbor.custom.com",
OCI: true,
},
},
},
@@ -130,34 +128,32 @@ func TestGetUnresolvedDependenciess(t *testing.T) {
name: "oci chart without path prefix (unchanged behavior)",
helmState: &HelmState{
FilePath: "helmfile.yaml",
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{
{
Name: "foo",
Chart: "chartsa/abc",
Version: "0.1.0",
Namespace: "ns1",
},
{
Name: "empty",
Chart: "chartsb/empty",
Namespace: "ns2",
},
{
Name: "empty",
Chart: "chartsb/empty",
},
Releases: []ReleaseSpec{
{
Name: "foo",
Chart: "chartsa/abc",
Version: "0.1.0",
Namespace: "ns1",
},
Repositories: []RepositorySpec{
{
Name: "chartsa",
URL: "localhost:5000/aaa",
OCI: true,
},
{
Name: "chartsb",
URL: "localhost:5000/bbb",
},
{
Name: "empty",
Chart: "chartsb/empty",
Namespace: "ns2",
},
{
Name: "empty",
Chart: "chartsb/empty",
},
},
Repositories: []RepositorySpec{
{
Name: "chartsa",
URL: "localhost:5000/aaa",
OCI: true,
},
{
Name: "chartsb",
URL: "localhost:5000/bbb",
},
},
},
@@ -191,31 +187,29 @@ func TestGetUnresolvedDependenciess(t *testing.T) {
name: "duplicate charts are differentiated by alias",
helmState: &HelmState{
FilePath: "helmfile.yaml",
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{
{
Name: "foo",
Chart: "myrepo/abc",
Version: "> 0.2.0",
Namespace: "ns1",
},
{
Name: "bar",
Chart: "myrepo/abc",
Version: "0.1.0",
Namespace: "ns2",
},
{
Name: "baz",
Chart: "myrepo/abc",
Version: "0.3.0",
},
Releases: []ReleaseSpec{
{
Name: "foo",
Chart: "myrepo/abc",
Version: "> 0.2.0",
Namespace: "ns1",
},
Repositories: []RepositorySpec{
{
Name: "myrepo",
URL: "localhost:5000/aaa",
},
{
Name: "bar",
Chart: "myrepo/abc",
Version: "0.1.0",
Namespace: "ns2",
},
{
Name: "baz",
Chart: "myrepo/abc",
Version: "0.3.0",
},
},
Repositories: []RepositorySpec{
{
Name: "myrepo",
URL: "localhost:5000/aaa",
},
},
},
+1 -1
View File
@@ -538,7 +538,7 @@ func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles
func() {
sortedSecrets := make([]secretResult, inputsSize)
for i := 0; i < inputsSize; i++ {
for range inputsSize {
result := <-results
sortedSecrets[result.id] = result
}
+7 -11
View File
@@ -648,10 +648,6 @@ func TestGetReleaseHardTimeout(t *testing.T) {
}
}
func strPtr(s string) *string {
return &s
}
func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
type args struct {
flags []string
@@ -691,7 +687,7 @@ func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
args: args{
flags: []string{},
helm: testutil.NewHelmExec(true),
release: &ReleaseSpec{ServerSide: strPtr("false")},
release: &ReleaseSpec{ServerSide: new("false")},
opt: &SyncOpts{},
expected: []string{"--server-side", "false"},
},
@@ -701,7 +697,7 @@ func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
args: args{
flags: []string{},
helm: testutil.NewHelmExec(true),
helmSpec: HelmSpec{ServerSide: strPtr("auto")},
helmSpec: HelmSpec{ServerSide: new("auto")},
release: &ReleaseSpec{},
opt: &SyncOpts{},
expected: []string{"--server-side", "auto"},
@@ -712,7 +708,7 @@ func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
args: args{
flags: []string{},
helm: testutil.NewHelmExec(true),
release: &ReleaseSpec{ServerSide: strPtr("true")},
release: &ReleaseSpec{ServerSide: new("true")},
opt: &SyncOpts{ServerSide: "false"},
expected: []string{"--server-side", "true"},
},
@@ -722,7 +718,7 @@ func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
args: args{
flags: []string{},
helm: testutil.NewHelmExec(true),
helmSpec: HelmSpec{ServerSide: strPtr("false")},
helmSpec: HelmSpec{ServerSide: new("false")},
release: &ReleaseSpec{},
opt: &SyncOpts{ServerSide: "true"},
expected: []string{"--server-side", "true"},
@@ -743,7 +739,7 @@ func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
args: args{
flags: []string{},
helm: testutil.NewVersionHelmExec("3.17.0"),
release: &ReleaseSpec{ServerSide: strPtr("true")},
release: &ReleaseSpec{ServerSide: new("true")},
opt: &SyncOpts{},
expected: []string{},
wantErr: true,
@@ -754,7 +750,7 @@ func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
args: args{
flags: []string{},
helm: testutil.NewVersionHelmExec("3.17.0"),
helmSpec: HelmSpec{ServerSide: strPtr("true")},
helmSpec: HelmSpec{ServerSide: new("true")},
release: &ReleaseSpec{},
opt: &SyncOpts{},
expected: []string{},
@@ -777,7 +773,7 @@ func TestAppendServerSideFlagsForUpgrade(t *testing.T) {
args: args{
flags: []string{},
helm: testutil.NewHelmExec(true),
release: &ReleaseSpec{ServerSide: strPtr("")},
release: &ReleaseSpec{ServerSide: new("")},
opt: &SyncOpts{ServerSide: "auto"},
expected: []string{"--server-side", "auto"},
},
+2 -6
View File
@@ -2,6 +2,7 @@ package state
import (
"fmt"
"slices"
"strings"
"dario.cat/mergo"
@@ -36,12 +37,7 @@ func AllowedInherits() []string {
// IsValidInherit reports whether key is an allowed inherits: entry.
func IsValidInherit(key string) bool {
for _, k := range allowedInherits {
if k == key {
return true
}
}
return false
return slices.Contains(allowedInherits, key)
}
// InheritedConfig carries parent-helmfile config to a sub-helmfile. Only the
+37 -52
View File
@@ -13,15 +13,14 @@ import (
)
func TestBuildInheritedConfig_OnlyRequestedFields(t *testing.T) {
st := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
st := &HelmState{
Repositories: []RepositorySpec{{Name: "a"}, {Name: "b"}},
HelmDefaults: HelmSpec{Timeout: 300, Atomic: true},
CommonLabels: map[string]string{"team": "platform"},
ApiVersions: []string{"v1"},
KubeVersion: "1.30.0",
Templates: map[string]TemplateSpec{"t": {}},
Env: environment.Environment{Name: "prod", Values: map[string]any{"k": "v"}},
}}
Env: environment.Environment{Name: "prod", Values: map[string]any{"k": "v"}}}
t.Run("repositories only", func(t *testing.T) {
in, err := st.BuildInheritedConfig([]string{"repositories"})
@@ -65,13 +64,12 @@ func TestBuildInheritedConfig_OnlyRequestedFields(t *testing.T) {
// does not alias the parent's slices/maps — mutating the copy must not affect
// the parent state. This guards against the cross-state coupling noted in review.
func TestBuildInheritedConfig_PureFieldsAreDeepCopied(t *testing.T) {
st := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
st := &HelmState{
Repositories: []RepositorySpec{{Name: "a"}, {Name: "b"}},
HelmDefaults: HelmSpec{Timeout: 300, Args: []string{"--parent-arg"}},
CommonLabels: map[string]string{"team": "platform"},
ApiVersions: []string{"v1"},
Templates: map[string]TemplateSpec{"base": {ReleaseSpec: ReleaseSpec{Namespace: "parent-ns"}}},
}}
Templates: map[string]TemplateSpec{"base": {ReleaseSpec: ReleaseSpec{Namespace: "parent-ns"}}}}
in, err := st.BuildInheritedConfig([]string{
"repositories", "helmDefaults", "commonLabels", "apiVersions", "templates",
})
@@ -96,21 +94,19 @@ func TestBuildInheritedConfig_PureFieldsAreDeepCopied(t *testing.T) {
}
func TestMergeInherited_NilIsNoop(t *testing.T) {
st := &HelmState{ReleaseSetSpec: ReleaseSetSpec{Repositories: []RepositorySpec{{Name: "a"}}}}
st := &HelmState{Repositories: []RepositorySpec{{Name: "a"}}}
require.NoError(t, st.MergeInherited(nil))
assert.Equal(t, []RepositorySpec{{Name: "a"}}, st.Repositories)
}
func TestMergeInherited_RepositoriesAppendsAndDedupsChildWins(t *testing.T) {
parent := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
Repositories: []RepositorySpec{{Name: "shared", URL: "parent-url"}, {Name: "only-parent"}},
}}
parent := &HelmState{
Repositories: []RepositorySpec{{Name: "shared", URL: "parent-url"}, {Name: "only-parent"}}}
in, err := parent.BuildInheritedConfig([]string{"repositories"})
require.NoError(t, err)
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
Repositories: []RepositorySpec{{Name: "shared", URL: "child-url"}, {Name: "only-child"}},
}}
child := &HelmState{
Repositories: []RepositorySpec{{Name: "shared", URL: "child-url"}, {Name: "only-child"}}}
require.NoError(t, child.MergeInherited(in))
names := repoNames(child.Repositories)
@@ -124,9 +120,8 @@ func TestMergeInherited_RepositoriesAppendsAndDedupsChildWins(t *testing.T) {
}
func TestMergeInherited_HelmDefaultsParentFillsChildGaps(t *testing.T) {
parent := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{Timeout: 300, Atomic: true},
}}
parent := &HelmState{
HelmDefaults: HelmSpec{Timeout: 300, Atomic: true}}
in, err := parent.BuildInheritedConfig([]string{"helmDefaults"})
require.NoError(t, err)
@@ -138,7 +133,7 @@ func TestMergeInherited_HelmDefaultsParentFillsChildGaps(t *testing.T) {
})
t.Run("child sets a non-zero field, parent fills the rest", func(t *testing.T) {
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{HelmDefaults: HelmSpec{Wait: true}}}
child := &HelmState{HelmDefaults: HelmSpec{Wait: true}}
require.NoError(t, child.MergeInherited(in))
assert.Equal(t, 300, child.HelmDefaults.Timeout, "parent fills child gap")
assert.True(t, child.HelmDefaults.Atomic, "parent fills child gap")
@@ -147,15 +142,13 @@ func TestMergeInherited_HelmDefaultsParentFillsChildGaps(t *testing.T) {
}
func TestMergeInherited_CommonLabelsUnionChildWins(t *testing.T) {
parent := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
CommonLabels: map[string]string{"team": "platform", "shared": "parent"},
}}
parent := &HelmState{
CommonLabels: map[string]string{"team": "platform", "shared": "parent"}}
in, err := parent.BuildInheritedConfig([]string{"commonLabels"})
require.NoError(t, err)
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
CommonLabels: map[string]string{"shared": "child", "local": "c"},
}}
child := &HelmState{
CommonLabels: map[string]string{"shared": "child", "local": "c"}}
require.NoError(t, child.MergeInherited(in))
assert.Equal(t, "platform", child.CommonLabels["team"], "parent-only key added")
@@ -164,15 +157,13 @@ func TestMergeInherited_CommonLabelsUnionChildWins(t *testing.T) {
}
func TestMergeInherited_TemplatesUnionChildWins(t *testing.T) {
parent := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
Templates: map[string]TemplateSpec{"base": {ReleaseSpec: ReleaseSpec{Namespace: "a"}}, "shared": {ReleaseSpec: ReleaseSpec{Namespace: "p"}}},
}}
parent := &HelmState{
Templates: map[string]TemplateSpec{"base": {ReleaseSpec: ReleaseSpec{Namespace: "a"}}, "shared": {ReleaseSpec: ReleaseSpec{Namespace: "p"}}}}
in, err := parent.BuildInheritedConfig([]string{"templates"})
require.NoError(t, err)
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
Templates: map[string]TemplateSpec{"shared": {ReleaseSpec: ReleaseSpec{Namespace: "c"}}, "local": {ReleaseSpec: ReleaseSpec{Namespace: "x"}}},
}}
child := &HelmState{
Templates: map[string]TemplateSpec{"shared": {ReleaseSpec: ReleaseSpec{Namespace: "c"}}, "local": {ReleaseSpec: ReleaseSpec{Namespace: "x"}}}}
require.NoError(t, child.MergeInherited(in))
assert.Contains(t, child.Templates, "base", "parent-only template added")
@@ -181,11 +172,11 @@ func TestMergeInherited_TemplatesUnionChildWins(t *testing.T) {
}
func TestMergeInherited_ApiVersionsAppendsAndDedups(t *testing.T) {
parent := &HelmState{ReleaseSetSpec: ReleaseSetSpec{ApiVersions: []string{"v1", "v2"}}}
parent := &HelmState{ApiVersions: []string{"v1", "v2"}}
in, err := parent.BuildInheritedConfig([]string{"apiVersions"})
require.NoError(t, err)
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{ApiVersions: []string{"v2", "v3"}}}
child := &HelmState{ApiVersions: []string{"v2", "v3"}}
require.NoError(t, child.MergeInherited(in))
assert.Equal(t, []string{"v1", "v2", "v3"}, child.ApiVersions)
@@ -193,7 +184,7 @@ func TestMergeInherited_ApiVersionsAppendsAndDedups(t *testing.T) {
func TestMergeInherited_KubeVersionChildWinsParentFillsGap(t *testing.T) {
t.Run("child empty inherits parent", func(t *testing.T) {
parent := &HelmState{ReleaseSetSpec: ReleaseSetSpec{KubeVersion: "1.30.0"}}
parent := &HelmState{KubeVersion: "1.30.0"}
in, err := parent.BuildInheritedConfig([]string{"kubeVersion"})
require.NoError(t, err)
child := &HelmState{}
@@ -201,10 +192,10 @@ func TestMergeInherited_KubeVersionChildWinsParentFillsGap(t *testing.T) {
assert.Equal(t, "1.30.0", child.KubeVersion)
})
t.Run("child set keeps its own", func(t *testing.T) {
parent := &HelmState{ReleaseSetSpec: ReleaseSetSpec{KubeVersion: "1.30.0"}}
parent := &HelmState{KubeVersion: "1.30.0"}
in, err := parent.BuildInheritedConfig([]string{"kubeVersion"})
require.NoError(t, err)
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{KubeVersion: "1.29.0"}}
child := &HelmState{KubeVersion: "1.29.0"}
require.NoError(t, child.MergeInherited(in))
assert.Equal(t, "1.29.0", child.KubeVersion)
})
@@ -216,9 +207,8 @@ func newObservedLogger() (*zap.SugaredLogger, *observer.ObservedLogs) {
}
func TestWarnUninheritedRepos_WarnsWhenParentHasRepoChildLacks(t *testing.T) {
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{{Name: "myapp", Chart: "release-charts/myapp"}},
}}
child := &HelmState{
Releases: []ReleaseSpec{{Name: "myapp", Chart: "release-charts/myapp"}}}
logger, recorded := newObservedLogger()
child.WarnUninheritedRepos([]string{"release-charts"}, logger)
@@ -230,10 +220,9 @@ func TestWarnUninheritedRepos_WarnsWhenParentHasRepoChildLacks(t *testing.T) {
func TestWarnUninheritedRepos_NoWarnWhenRepoInherited(t *testing.T) {
// child has the repo (e.g. because it was inherited and merged) -> no warn
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
child := &HelmState{
Repositories: []RepositorySpec{{Name: "release-charts"}},
Releases: []ReleaseSpec{{Name: "myapp", Chart: "release-charts/myapp"}},
}}
Releases: []ReleaseSpec{{Name: "myapp", Chart: "release-charts/myapp"}}}
logger, recorded := newObservedLogger()
child.WarnUninheritedRepos([]string{"release-charts"}, logger)
@@ -243,9 +232,8 @@ func TestWarnUninheritedRepos_NoWarnWhenRepoInherited(t *testing.T) {
func TestWarnUninheritedRepos_NoWarnForRepoNotInParent(t *testing.T) {
// repo absent from both -> helm will error separately, no inherit hint
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{{Name: "myapp", Chart: "other/myapp"}},
}}
child := &HelmState{
Releases: []ReleaseSpec{{Name: "myapp", Chart: "other/myapp"}}}
logger, recorded := newObservedLogger()
child.WarnUninheritedRepos([]string{"release-charts"}, logger)
@@ -254,15 +242,14 @@ func TestWarnUninheritedRepos_NoWarnForRepoNotInParent(t *testing.T) {
}
func TestWarnUninheritedRepos_IgnoresLocalAndBareCharts(t *testing.T) {
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
child := &HelmState{
Releases: []ReleaseSpec{
{Name: "a", Chart: "./local/chart"},
{Name: "b", Chart: "mychart"},
{Name: "c", Chart: "oci://registry/chart"},
{Name: "d", Chart: "https://host/charts/x"},
{Name: "e", Chart: "../sibling/y"},
},
}}
}}
logger, recorded := newObservedLogger()
child.WarnUninheritedRepos([]string{"release-charts"}, logger)
@@ -271,12 +258,11 @@ func TestWarnUninheritedRepos_IgnoresLocalAndBareCharts(t *testing.T) {
}
func TestWarnUninheritedRepos_WarnsOncePerRepo(t *testing.T) {
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
child := &HelmState{
Releases: []ReleaseSpec{
{Name: "a", Chart: "shared/x"},
{Name: "b", Chart: "shared/y"},
},
}}
}}
logger, recorded := newObservedLogger()
child.WarnUninheritedRepos([]string{"shared"}, logger)
@@ -285,9 +271,8 @@ func TestWarnUninheritedRepos_WarnsOncePerRepo(t *testing.T) {
}
func TestWarnUninheritedRepos_NilLoggerAndEmptyInputsAreSafe(t *testing.T) {
child := &HelmState{ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{{Name: "a", Chart: "x/y"}},
}}
child := &HelmState{
Releases: []ReleaseSpec{{Name: "a", Chart: "x/y"}}}
assert.NotPanics(t, func() { child.WarnUninheritedRepos(nil, nil) })
assert.NotPanics(t, func() { child.WarnUninheritedRepos(nil, zap.NewNop().Sugar()) })
assert.NotPanics(t, func() { child.WarnUninheritedRepos([]string{"x"}, zap.NewNop().Sugar()) })
+4 -6
View File
@@ -111,12 +111,10 @@ fieldSpecs:
`), 0644))
st := &HelmState{
logger: zap.NewNop().Sugar(),
fs: filesystem.DefaultFileSystem(),
ReleaseSetSpec: ReleaseSetSpec{
DefaultHelmBinary: helmBin,
DefaultKustomizeBinary: "kustomize",
},
logger: zap.NewNop().Sugar(),
fs: filesystem.DefaultFileSystem(),
DefaultHelmBinary: helmBin,
DefaultKustomizeBinary: "kustomize",
}
chartification := &Chartify{
+1 -1
View File
@@ -130,7 +130,7 @@ func TestChartifyTempDirConcurrentTracking(t *testing.T) {
}
var wg sync.WaitGroup
for i := 0; i < n; i++ {
for i := range n {
wg.Add(1)
go func(dir string) {
defer wg.Done()
+3 -7
View File
@@ -215,9 +215,7 @@ func TestEffectiveTemplateArgs(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{TemplateArgs: tt.helmDefaults},
},
HelmDefaults: HelmSpec{TemplateArgs: tt.helmDefaults},
}
assert.Equal(t, tt.want, st.effectiveTemplateArgs(tt.cliArgs))
})
@@ -231,10 +229,8 @@ func TestEffectiveTemplateArgs(t *testing.T) {
// command opt into server-side templating + kube-connection injection end-to-end.
func TestHelmDefaultsTemplateArgsReachesChartify(t *testing.T) {
st := &HelmState{
kubeconfig: "/path/to/kubeconfig",
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{TemplateArgs: []string{"--dry-run=server"}},
},
kubeconfig: "/path/to/kubeconfig",
HelmDefaults: HelmSpec{TemplateArgs: []string{"--dry-run=server"}},
}
// Mirror processChartification's exact call shape.
+1 -3
View File
@@ -74,9 +74,7 @@ func TestAppendSkipSchemaValidationFlagToChartifyTemplateArgs(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: tt.defaults,
},
HelmDefaults: tt.defaults,
}
got := st.appendSkipSchemaValidationFlagToChartifyTemplateArgs(tt.templateArgs, tt.release, tt.fromCLI)
+8 -16
View File
@@ -105,10 +105,8 @@ func TestGetOCIChart_ResolvesConstraintIntoCachePathAndPullFlag(t *testing.T) {
logger := zap.NewExample().Sugar()
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
logger: logger,
valsRuntime: valsRuntime,
@@ -190,10 +188,8 @@ func TestGetOCIChart_ResolvesToDifferentVersionsPicksSeparateCachePaths(t *testi
logger := zap.NewExample().Sugar()
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
logger: logger,
valsRuntime: valsRuntime,
@@ -250,10 +246,8 @@ func TestGetOCIChart_SkipRefreshSkipsConstraintResolution(t *testing.T) {
logger := zap.NewExample().Sugar()
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
logger: logger,
valsRuntime: valsRuntime,
@@ -312,10 +306,8 @@ func TestGetOCIChart_SharedConstraintResolvedOncePerProcess(t *testing.T) {
logger := zap.NewExample().Sugar()
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
Repositories: []RepositorySpec{
{Name: issue2766RepoName, URL: issue2766RepoURL, OCI: true},
},
logger: logger,
valsRuntime: valsRuntime,
+3 -3
View File
@@ -69,7 +69,7 @@ func TestForcedDownloadChartSerializesSameChart(t *testing.T) {
numReleases := 5
var wg sync.WaitGroup
for i := 0; i < numReleases; i++ {
for i := range numReleases {
wg.Add(1)
go func(idx int) {
defer wg.Done()
@@ -164,7 +164,7 @@ func TestWithChartOperationLockSerializesSameChart(t *testing.T) {
numReleases := 5
var wg sync.WaitGroup
for i := 0; i < numReleases; i++ {
for i := range numReleases {
wg.Add(1)
go func(idx int) {
defer wg.Done()
@@ -216,7 +216,7 @@ func TestWithChartOperationLockNoLockForLocalChart(t *testing.T) {
numReleases := 5
var wg sync.WaitGroup
for i := 0; i < numReleases; i++ {
for i := range numReleases {
wg.Add(1)
go func(idx int) {
defer wg.Done()
+10 -19
View File
@@ -37,7 +37,7 @@ func TestOCIChartFileLock(t *testing.T) {
// Number of concurrent goroutines trying to acquire the lock
numGoroutines := 5
for i := 0; i < numGoroutines; i++ {
for i := range numGoroutines {
wg.Add(1)
go func(id int) {
defer wg.Done()
@@ -78,11 +78,8 @@ func TestOCIChartFileLock(t *testing.T) {
// Multiple goroutines try to write to the same file
numGoroutines := 10
for i := 0; i < numGoroutines; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for range numGoroutines {
wg.Go(func() {
fileLock := flock.New(lockFilePath)
err := fileLock.Lock()
require.NoError(t, err)
@@ -95,7 +92,7 @@ func TestOCIChartFileLock(t *testing.T) {
require.NoError(t, err)
writeCount.Add(1)
}
}()
})
}
wg.Wait()
@@ -195,11 +192,8 @@ func TestOCIChartSharedExclusiveLocks(t *testing.T) {
var activeReaders atomic.Int32
var maxConcurrentReaders atomic.Int32
for i := 0; i < numReaders; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for range numReaders {
wg.Go(func() {
fileLock := flock.New(lockFilePath)
// Acquire shared (read) lock
err := fileLock.RLock()
@@ -225,7 +219,7 @@ func TestOCIChartSharedExclusiveLocks(t *testing.T) {
activeReaders.Add(-1)
err = fileLock.Unlock()
require.NoError(t, err)
}()
})
}
wg.Wait()
@@ -455,11 +449,8 @@ func TestOCIChartDoubleCheckLocking(t *testing.T) {
var wg sync.WaitGroup
// Simulate two processes trying to download the same chart
for i := 0; i < 2; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for range 2 {
wg.Go(func() {
fileLock := flock.New(lockFilePath)
err := fileLock.Lock()
require.NoError(t, err)
@@ -476,7 +467,7 @@ func TestOCIChartDoubleCheckLocking(t *testing.T) {
pullCount.Add(1)
}
// If directory exists, skip pull (use cached)
}()
})
}
wg.Wait()
+5 -6
View File
@@ -3,6 +3,7 @@ package state
import (
"fmt"
"regexp"
"slices"
"strings"
)
@@ -70,10 +71,8 @@ func SelectorsAreCompatible(selectorsA, selectorsB []string) (bool, error) {
}
for _, a := range filtersA {
for _, b := range filtersB {
if a.positiveLabelsCompatibleWith(b) {
return true, nil
}
if slices.ContainsFunc(filtersB, a.positiveLabelsCompatibleWith) {
return true, nil
}
}
@@ -116,8 +115,8 @@ func ParseLabels(l string) (LabelFilter, error) {
lf.positiveLabels = [][]string{}
lf.negativeLabels = [][]string{}
var err error
labels := strings.Split(l, ",")
for _, label := range labels {
labels := strings.SplitSeq(l, ",")
for label := range labels {
if match := reLabelMismatch.MatchString(label); match {
kv := strings.Split(label, "!=")
lf.negativeLabels = append(lf.negativeLabels, kv)
@@ -3,6 +3,7 @@ package state
import (
"os"
"path/filepath"
"slices"
"testing"
"github.com/stretchr/testify/assert"
@@ -82,7 +83,7 @@ version: 0.1.0
name: "release-level skipDeps overrides helmDefaults",
helmDefaultsSkipDeps: false,
helmDefaultsSkipRefresh: false,
releaseSkipDeps: boolPtr(true),
releaseSkipDeps: new(true),
chartPath: "./chart",
isLocal: true,
expectedBuildDeps: false, // release-level skipDeps=true
@@ -259,12 +260,10 @@ func TestRunHelmDepBuilds_SkipRefreshBehaviors(t *testing.T) {
st := &HelmState{
logger: logger,
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{
SkipRefresh: tt.helmDefaultsSkipRefresh,
},
Repositories: tt.repos,
HelmDefaults: HelmSpec{
SkipRefresh: tt.helmDefaultsSkipRefresh,
},
Repositories: tt.repos,
}
builds := []*chartPrepareResult{
@@ -283,13 +282,7 @@ func TestRunHelmDepBuilds_SkipRefreshBehaviors(t *testing.T) {
assert.Equal(t, tt.expectUpdateRepo, helm.updateRepoCalled,
"UpdateRepo called mismatch: expected %v, got %v", tt.expectUpdateRepo, helm.updateRepoCalled)
hasSkipRefreshFlag := false
for _, f := range helm.buildDepsFlags {
if f == "--skip-refresh" {
hasSkipRefreshFlag = true
break
}
}
hasSkipRefreshFlag := slices.Contains(helm.buildDepsFlags, "--skip-refresh")
assert.Equal(t, tt.expectSkipRefreshFlag, hasSkipRefreshFlag,
"--skip-refresh flag mismatch: expected %v, got %v (flags: %v)", tt.expectSkipRefreshFlag, hasSkipRefreshFlag, helm.buildDepsFlags)
})
@@ -322,11 +315,9 @@ func TestRunHelmDepBuilds_MultipleBuilds(t *testing.T) {
helm := &multiBuildTracker{}
st := &HelmState{
logger: logger,
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{SkipRefresh: false},
Repositories: []RepositorySpec{{Name: "stable", URL: "https://example.com"}},
},
logger: logger,
HelmDefaults: HelmSpec{SkipRefresh: false},
Repositories: []RepositorySpec{{Name: "stable", URL: "https://example.com"}},
}
builds := []*chartPrepareResult{
@@ -344,13 +335,7 @@ func TestRunHelmDepBuilds_MultipleBuilds(t *testing.T) {
expectedSkipRefresh := []bool{false, true}
for i, flags := range helm.buildDepsCalls {
hasSkipRefresh := false
for _, f := range flags {
if f == "--skip-refresh" {
hasSkipRefresh = true
break
}
}
hasSkipRefresh := slices.Contains(flags, "--skip-refresh")
assert.Equal(t, expectedSkipRefresh[i], hasSkipRefresh,
"build %d skip-refresh flag mismatch: expected %v, got %v (flags: %v)", i, expectedSkipRefresh[i], hasSkipRefresh, flags)
}
@@ -462,9 +447,7 @@ func TestNeedsRepoUpdate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
Repositories: tt.repos,
},
Repositories: tt.repos,
}
result := st.NeedsRepoUpdate()
assert.Equal(t, tt.expected, result,
+1 -5
View File
@@ -62,7 +62,7 @@ func TestSkipDepsAndSkipRefresh(t *testing.T) {
helmDefaultsSkipDeps: false,
helmDefaultsSkipRefresh: false,
releaseSkipDeps: nil,
releaseSkipRefresh: boolPtr(true),
releaseSkipRefresh: new(true),
optsSkipDeps: false,
optsSkipRefresh: false,
isLocal: true,
@@ -115,7 +115,3 @@ func TestSkipDepsAndSkipRefresh(t *testing.T) {
})
}
}
func boolPtr(b bool) *bool {
return &b
}
+2 -4
View File
@@ -77,10 +77,8 @@ func newShimState(t *testing.T) (*HelmState, helmexec.Interface) {
return &HelmState{
logger: zap.NewNop().Sugar(),
fs: filesystem.DefaultFileSystem(),
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{
{Name: "demo", Namespace: "apps", Chart: "./charts/demo"},
},
Releases: []ReleaseSpec{
{Name: "demo", Namespace: "apps", Chart: "./charts/demo"},
},
}, helm
}
+33 -39
View File
@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"net/url"
"os"
"path/filepath"
@@ -917,7 +918,7 @@ func (st *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValu
concurrency,
numReleases,
func() {
for i := 0; i < numReleases; i++ {
for i := range numReleases {
jobs <- releases[i]
}
close(jobs)
@@ -1158,7 +1159,7 @@ func (st *HelmState) DeleteReleasesForSync(affectedReleases *AffectedReleases, h
workerLimit,
len(releases),
func() {
for i := 0; i < len(releases); i++ {
for i := range releases {
jobQueue <- &releases[i]
}
close(jobQueue)
@@ -1269,7 +1270,7 @@ func (st *HelmState) SyncReleases(affectedReleases *AffectedReleases, helm helme
workerLimit,
len(preps),
func() {
for i := 0; i < len(preps); i++ {
for i := range preps {
jobQueue <- &preps[i]
}
close(jobQueue)
@@ -1711,13 +1712,13 @@ func (st *HelmState) rewriteChartDependencies(chartPath string) (string, func(),
}
type ChartDependency struct {
Name string `yaml:"name"`
Repository string `yaml:"repository"`
Data map[string]interface{} `yaml:",inline"`
Name string `yaml:"name"`
Repository string `yaml:"repository"`
Data map[string]any `yaml:",inline"`
}
type ChartMeta struct {
Dependencies []ChartDependency `yaml:"dependencies,omitempty"`
Data map[string]interface{} `yaml:",inline"`
Dependencies []ChartDependency `yaml:"dependencies,omitempty"`
Data map[string]any `yaml:",inline"`
}
var chartMeta ChartMeta
@@ -1728,8 +1729,8 @@ func (st *HelmState) rewriteChartDependencies(chartPath string) (string, func(),
modified := false
for i := range chartMeta.Dependencies {
dep := &chartMeta.Dependencies[i]
if strings.HasPrefix(dep.Repository, "file://") {
relPath := strings.TrimPrefix(dep.Repository, "file://")
if after, ok := strings.CutPrefix(dep.Repository, "file://"); ok {
relPath := after
if !filepath.IsAbs(relPath) {
absPath := filepath.Join(chartPath, relPath)
@@ -1820,7 +1821,7 @@ func (st *HelmState) rewriteChartDependencies(chartPath string) (string, func(),
if v, ok := d.Data["enabled"].(bool); ok {
dep.Enabled = v
}
if v, ok := d.Data["tags"].([]interface{}); ok {
if v, ok := d.Data["tags"].([]any); ok {
tags := make([]string, 0, len(v))
for _, t := range v {
if s, ok := t.(string); ok {
@@ -1829,12 +1830,12 @@ func (st *HelmState) rewriteChartDependencies(chartPath string) (string, func(),
}
dep.Tags = tags
}
if v, ok := d.Data["import-values"].([]interface{}); ok {
if v, ok := d.Data["import-values"].([]any); ok {
normalized, err := maputil.RecursivelyStringifyMapKey(v)
if err != nil {
st.logger.Warnf("Failed to normalize import-values for dependency %s: %v", d.Name, err)
} else {
dep.ImportValues = normalized.([]interface{})
dep.ImportValues = normalized.([]any)
}
}
req = append(req, dep)
@@ -1866,7 +1867,7 @@ func (st *HelmState) rewriteChartDependencies(chartPath string) (string, func(),
if err != nil {
st.logger.Warnf("Failed to normalize import-values in Chart.lock for dependency %s: %v", ld.Name, err)
} else {
ld.ImportValues = normalized.([]interface{})
ld.ImportValues = normalized.([]any)
}
}
}
@@ -2000,7 +2001,7 @@ func (st *HelmState) appendSkipSchemaValidationFlagToChartifyTemplateArgs(templa
}
func hasTemplateArg(templateArgs, arg string) bool {
for _, token := range strings.Fields(templateArgs) {
for token := range strings.FieldsSeq(templateArgs) {
if token == arg || strings.HasPrefix(token, arg+"=") {
return true
}
@@ -2037,8 +2038,7 @@ func (st *HelmState) processLocalChart(normalizedChart, dir string, release *Rel
// TLS/plain-http) so a prefetched chart behaves identically to one helm would have
// downloaded itself during `helm upgrade`. See issue #2741.
func (st *HelmState) chartFetchFlags(release *ReleaseSpec) []string {
var flags []string
flags = st.appendChartVersionFlags(flags, release)
flags := st.chartVersionFlags(release)
// non-OCI chart should be verified here, matching flagsForUpgrade.
if !st.IsOCIChart(release.Chart) {
@@ -3103,7 +3103,7 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
concurrency,
numReleases,
func() {
for i := 0; i < numReleases; i++ {
for i := range numReleases {
jobs <- releases[i]
}
close(jobs)
@@ -3177,7 +3177,7 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
}
},
func() {
for i := 0; i < numReleases; i++ {
for range numReleases {
res := <-results
if len(res.errors) > 0 {
for _, e := range res.errors {
@@ -3301,7 +3301,7 @@ func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []st
workerLimit,
len(preps),
func() {
for i := 0; i < len(preps); i++ {
for i := range preps {
jobQueue <- &preps[i]
}
close(jobQueue)
@@ -3364,7 +3364,7 @@ func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []st
}
},
func() {
for i := 0; i < len(preps); i++ {
for range preps {
res := <-results
if res.err != nil {
errs = append(errs, res.err)
@@ -3525,12 +3525,8 @@ func (st *HelmState) GetReleasesWithLabels() []ReleaseSpec {
spec := r
labels := map[string]string{}
// apply common labels
for k, v := range st.CommonLabels {
labels[k] = v
}
for k, v := range spec.Labels {
labels[k] = v
}
maps.Copy(labels, st.CommonLabels)
maps.Copy(labels, spec.Labels)
// Let the release name, namespace, and chart be used as a tag
labels["name"] = r.Name
labels["namespace"] = r.Namespace
@@ -3624,7 +3620,7 @@ func ConditionEnabled(r ReleaseSpec, values map[string]any) (bool, error) {
return false, fmt.Errorf("environment values field '%s' not found", currentKey)
}
iValues, ok = value.(map[string]interface{})
iValues, ok = value.(map[string]any)
if !ok {
return false, fmt.Errorf("environment values field '%s' is not a map", currentKey)
}
@@ -4177,8 +4173,7 @@ func (st *HelmState) timeoutFlags(release *ReleaseSpec, ops *SyncOpts) []string
}
func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSpec, workerIndex int, opt *SyncOpts) ([]string, []string, error) {
var flags []string
flags = st.appendChartVersionFlags(flags, release)
flags := st.chartVersionFlags(release)
flags = st.appendEnableDNSFlags(flags, release)
flags = st.appendWaitFlags(flags, helm, release, opt)
@@ -4324,8 +4319,7 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
}
func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseSpec, workerIndex int, opt *TemplateOpts) ([]string, []string, error) {
var flags []string
flags = st.appendChartVersionFlags(flags, release)
flags := st.chartVersionFlags(release)
flags = st.appendHelmXFlags(flags, release)
flags = st.appendEnableDNSFlags(flags, release)
@@ -4375,8 +4369,7 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec,
} else {
pluginsDir = cliv4.New().PluginsDirectory
}
var flags []string
flags = st.appendChartVersionFlags(flags, release)
flags := st.chartVersionFlags(release)
flags = st.appendEnableDNSFlags(flags, release)
disableOpenAPIValidation := false
@@ -4577,7 +4570,8 @@ func (st *HelmState) appendServerSideFlagsForDiff(flags []string, helm helmexec.
return st.appendServerSideFlagsForUpgrade(flags, helm, release, serverSide)
}
func (st *HelmState) appendChartVersionFlags(flags []string, release *ReleaseSpec) []string {
func (st *HelmState) chartVersionFlags(release *ReleaseSpec) []string {
var flags []string
version := release.Version
// Strip OCI digest from version (digest is handled in chart URL, not --version flag)
if idx := strings.Index(version, "@"); idx >= 0 {
@@ -5369,7 +5363,7 @@ func renderValsSecrets(e vals.Evaluator, input ...string) ([]string, error) {
return nil, fmt.Errorf("type %T isn't supported", mapRendered["values"])
}
for i := 0; i < len(rendered); i++ {
for i := range rendered {
output[i] = fmt.Sprintf("%v", rendered[i])
}
}
@@ -6238,7 +6232,7 @@ func (st *HelmState) getOCIChart(release *ReleaseSpec, tempDir string, helm helm
flags = st.appendKeyringFlags(flags, release)
flags = st.appendChartDownloadFlags(flags, release)
// Use the clean chartVersion (without digest) from getOCIQualifiedChartName
// rather than appendChartVersionFlags which uses release.Version verbatim.
// rather than chartVersionFlags which uses release.Version verbatim.
// The digest is already embedded in qualifiedChartName.
// When a digest is present, omit --version: the digest is the authoritative
// content identifier, and passing both causes errors in some Helm versions.
@@ -6351,8 +6345,8 @@ func parseOCIChartRef(chartURL string) (baseURL, version, digest string) {
// "@sha256:abc" → ("", "sha256:abc")
// "" → ("", "")
func parseVersionDigest(version string) (ver, digest string) {
if atIdx := strings.Index(version, "@"); atIdx >= 0 {
return version[:atIdx], version[atIdx+1:]
if before, after, ok := strings.Cut(version, "@"); ok {
return before, after
}
return version, ""
}
+6 -10
View File
@@ -3,7 +3,9 @@ package state
import (
"errors"
"fmt"
"maps"
"reflect"
"slices"
"strings"
"dario.cat/mergo"
@@ -99,8 +101,7 @@ func (st *HelmState) ExecuteTemplates() (*HelmState, error) {
release, err := st.releaseWithInheritedTemplate(&rtWithDefaults, nil)
if err != nil {
var cyclicInheritanceErr CyclicReleaseTemplateInheritanceError
if errors.As(err, &cyclicInheritanceErr) {
if cyclicInheritanceErr, ok := errors.AsType[CyclicReleaseTemplateInheritanceError](err); ok {
return nil, fmt.Errorf("unable to load release %q with template: %w", rt.Name, cyclicInheritanceErr)
}
return nil, err
@@ -112,9 +113,7 @@ func (st *HelmState) ExecuteTemplates() (*HelmState, error) {
if release.Labels == nil {
release.Labels = map[string]string{}
}
for k, v := range st.CommonLabels {
release.Labels[k] = v
}
maps.Copy(release.Labels, st.CommonLabels)
if len(release.ApiVersions) == 0 {
release.ApiVersions = st.ApiVersions
}
@@ -179,11 +178,8 @@ func (st *HelmState) releaseWithInheritedTemplate(r *ReleaseSpec, inheritancePat
path = append(path, templateName)
var cycleFound bool
for _, t := range inheritancePath {
if t == templateName {
cycleFound = true
break
}
if slices.Contains(inheritancePath, templateName) {
cycleFound = true
}
if cycleFound {
+38 -46
View File
@@ -208,16 +208,14 @@ func TestHelmState_executeTemplates(t *testing.T) {
fs: &filesystem.FileSystem{
Glob: func(s string) ([]string, error) { return nil, nil }},
basePath: ".",
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
},
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
},
RenderedValues: map[string]any{},
}
@@ -324,16 +322,14 @@ func TestHelmState_recursiveRefsTemplates(t *testing.T) {
fs: &filesystem.FileSystem{
Glob: func(s string) ([]string, error) { return nil, nil },
},
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
},
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
},
RenderedValues: map[string]any{},
}
@@ -411,9 +407,7 @@ func TestApplyDefaultInherit(t *testing.T) {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
st := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
DefaultInherit: tt.defaultInherit,
},
DefaultInherit: tt.defaultInherit,
}
got := st.applyDefaultInherit(tt.releaseInherit)
if len(got) != len(tt.want) {
@@ -439,31 +433,29 @@ func TestHelmState_executeTemplatesWithDefaultTemplates(t *testing.T) {
Glob: func(s string) ([]string, error) { return nil, nil },
},
basePath: ".",
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
Templates: map[string]TemplateSpec{
"default": {
ReleaseSpec: ReleaseSpec{
Namespace: "default-ns",
Labels: map[string]string{"managed": "true"},
},
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
Templates: map[string]TemplateSpec{
"default": {
ReleaseSpec: ReleaseSpec{
Namespace: "default-ns",
Labels: map[string]string{"managed": "true"},
},
},
DefaultInherit: DefaultInherits{"default"},
Releases: []ReleaseSpec{
{
Name: "app1",
Chart: "test-chart",
},
{
Name: "app2",
Chart: "test-chart-2",
Inherit: Inherits{
{Template: "default", Except: []string{"labels"}},
},
},
DefaultInherit: DefaultInherits{"default"},
Releases: []ReleaseSpec{
{
Name: "app1",
Chart: "test-chart",
},
{
Name: "app2",
Chart: "test-chart-2",
Inherit: Inherits{
{Template: "default", Except: []string{"labels"}},
},
},
},
+2 -4
View File
@@ -39,9 +39,7 @@ func TestAppendApiVersionsFlags_KubeVersion(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
ReleaseSetSpec: ReleaseSetSpec{
KubeVersion: tt.stateKubeVersion,
},
KubeVersion: tt.stateKubeVersion,
}
release := &ReleaseSpec{
@@ -65,7 +63,7 @@ func TestAppendApiVersionsFlags_KubeVersion(t *testing.T) {
require.True(t, foundKubeVersion, "Should have --kube-version flag in result")
} else {
// Should NOT have --kube-version flag
for i := 0; i < len(result); i++ {
for i := range result {
require.NotEqual(t, "--kube-version", result[i],
"Should not have --kube-version flag when nothing is set")
}
+1 -1
View File
@@ -229,7 +229,7 @@ func GroupReleasesByDependency(releases []Release, opts PlanOptions) ([][]Releas
var result [][]Release
for groupIndex := 0; groupIndex < len(plan); groupIndex++ {
for groupIndex := range plan {
dagNodesInGroup := plan[groupIndex]
var idsInGroup []string
+232 -329
View File
File diff suppressed because it is too large Load Diff