diff --git a/pkg/state/chart_dependency.go b/pkg/state/chart_dependency.go index 60101c8a..7f88081c 100644 --- a/pkg/state/chart_dependency.go +++ b/pkg/state/chart_dependency.go @@ -129,6 +129,20 @@ func (d *ResolvedDependencies) Get(chart, versionConstraint string) (string, err return "", fmt.Errorf("no resolved dependency found for \"%s\", running \"helmfile deps\" may resolve the issue", chart) } +func dedupResolvedDependencies(deps []ResolvedChartDependency) []ResolvedChartDependency { + seen := map[string]bool{} + result := make([]ResolvedChartDependency, 0, len(deps)) + for _, dep := range deps { + key := dep.ChartName + "|" + dep.Repository + "|" + dep.Version + if seen[key] { + continue + } + seen[key] = true + result = append(result, dep) + } + return result +} + func (st *HelmState) mergeLockedDependencies() (*HelmState, error) { filename, unresolved := getUnresolvedDependenciess(st) @@ -369,6 +383,8 @@ func (m *chartDependencyManager) doUpdate(chartLockFile string, unresolved *Unre return lockedReqs.ResolvedDependencies[i].ChartName < lockedReqs.ResolvedDependencies[j].ChartName }) + lockedReqs.ResolvedDependencies = dedupResolvedDependencies(lockedReqs.ResolvedDependencies) + lockedReqs.Version = version.Version() updatedLockFileContent, err = yaml.Marshal(lockedReqs) diff --git a/pkg/state/chart_dependency_test.go b/pkg/state/chart_dependency_test.go index 23c97c5c..70585b1c 100644 --- a/pkg/state/chart_dependency_test.go +++ b/pkg/state/chart_dependency_test.go @@ -6,6 +6,69 @@ import ( "github.com/stretchr/testify/require" ) +func TestDedupResolvedDependencies(t *testing.T) { + tests := []struct { + name string + input []ResolvedChartDependency + expected []ResolvedChartDependency + }{ + { + name: "no duplicates", + input: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + {ChartName: "redis", Repository: "https://charts.bitnami.com/bitnami", Version: "17.0.7"}, + }, + expected: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + {ChartName: "redis", Repository: "https://charts.bitnami.com/bitnami", Version: "17.0.7"}, + }, + }, + { + name: "duplicates removed", + input: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + }, + expected: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + }, + }, + { + name: "same chart different versions kept", + input: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.1"}, + }, + expected: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.1"}, + }, + }, + { + name: "same chart different repos kept", + input: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + {ChartName: "app-template", Repository: "https://other.com", Version: "4.6.2"}, + }, + expected: []ResolvedChartDependency{ + {ChartName: "app-template", Repository: "https://example.com", Version: "4.6.2"}, + {ChartName: "app-template", Repository: "https://other.com", Version: "4.6.2"}, + }, + }, + { + name: "empty input", + input: []ResolvedChartDependency{}, + expected: []ResolvedChartDependency{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := dedupResolvedDependencies(tt.input) + require.Equal(t, tt.expected, result) + }) + } +} + func TestGetUnresolvedDependenciess(t *testing.T) { tests := []struct { name string