diff --git a/pkg/helmexec/exec.go b/pkg/helmexec/exec.go index 34a6e5dc..08f1d5d3 100644 --- a/pkg/helmexec/exec.go +++ b/pkg/helmexec/exec.go @@ -204,6 +204,12 @@ func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, usernam return fmt.Errorf("empty field name") } + savedExtra := helm.extra + helm.extra = []string{} + defer func() { + helm.extra = savedExtra + }() + switch managed { case "acr": helm.logger.Infof("Adding repo %v (acr)", name) @@ -252,6 +258,11 @@ func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, usernam func (helm *execer) UpdateRepo() error { helm.logger.Info("Updating repo") + savedExtra := helm.extra + helm.extra = []string{} + defer func() { + helm.extra = savedExtra + }() out, err := helm.exec([]string{"repo", "update"}, map[string]string{}, nil) helm.info(out) return err diff --git a/pkg/state/state.go b/pkg/state/state.go index ae699477..53570cca 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1828,7 +1828,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre } if len(builds) > 0 { - if err := st.runHelmDepBuilds(helm, concurrency, builds); err != nil { + if err := st.runHelmDepBuilds(helm, concurrency, builds, opts); err != nil { return nil, []error{err} } } @@ -1837,7 +1837,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre } // nolint: unparam -func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, builds []*chartPrepareResult) error { +func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, builds []*chartPrepareResult, opts ChartPrepareOptions) error { // NOTES: // 1. `helm dep build` fails when it was run concurrency on the same chart. // To avoid that, we run `helm dep build` only once per each local chart. @@ -1848,7 +1848,21 @@ func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, // // See https://github.com/roboll/helmfile/issues/1521 + // Perform an update of repos once before running `helm dep build` so that we + // can safely pass --skip-refresh to the command to avoid doing a repo update + // for every iteration of the loop where charts have external dependencies. + // Only do this if there are repositories configured. + if len(builds) > 0 && !opts.SkipRefresh && len(st.Repositories) > 0 { + if err := helm.UpdateRepo(); err != nil { + return fmt.Errorf("updating repo: %w", err) + } + } + for _, r := range builds { + // Never update the local repository cache here, since we've already + // updated it before entering the loop + r.skipRefresh = true + buildDepsFlags := getBuildDepsFlags(r) if err := helm.BuildDeps(r.releaseName, r.chartPath, buildDepsFlags...); err != nil { if r.chartFetchedByGoGetter { diff --git a/test/e2e/template/helmfile/testdata/snapshot/chart_need/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/chart_need/output.yaml index 7954f3c1..46577aa7 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/chart_need/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/chart_need/output.yaml @@ -1,10 +1,12 @@ Adding repo myrepo http://localhost:18080/ "myrepo" has been added to your repositories -Building dependency release=foo, chart=$WD/temp1/foo +Updating repo Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "myrepo" chart repository Update Complete. ⎈Happy Helming!⎈ + +Building dependency release=foo, chart=$WD/temp1/foo Saving 1 charts Downloading raw from repo http://localhost:18080/ Deleting outdated charts diff --git a/test/e2e/template/helmfile/testdata/snapshot/chart_need_enable_live_output/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/chart_need_enable_live_output/output.yaml index 67616a32..61f4dd37 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/chart_need_enable_live_output/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/chart_need_enable_live_output/output.yaml @@ -2,10 +2,12 @@ Live output is enabled Adding repo myrepo http://localhost:18081/ "myrepo" has been added to your repositories -Building dependency release=foo, chart=$WD/temp1/foo +Updating repo Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "myrepo" chart repository Update Complete. ⎈Happy Helming!⎈ + +Building dependency release=foo, chart=$WD/temp1/foo Saving 1 charts Downloading raw from repo http://localhost:18081/ Deleting outdated charts diff --git a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml index 8f4523d9..3cf214c1 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml @@ -1,6 +1,11 @@ Adding repo myrepo http://localhost:18084/ "myrepo" has been added to your repositories +Updating repo +Hang tight while we grab the latest from your chart repositories... +...Successfully got an update from the "myrepo" chart repository +Update Complete. ⎈Happy Helming!⎈ + Building dependency release=foo1, chart=../../charts/raw-0.1.0 Building dependency release=foo2, chart=../../charts/raw-0.1.0 Templating release=foo1, chart=../../charts/raw-0.1.0 diff --git a/test/integration/test-cases/chart-needs.sh b/test/integration/test-cases/chart-needs.sh index bbf91605..a50ceab1 100644 --- a/test/integration/test-cases/chart-needs.sh +++ b/test/integration/test-cases/chart-needs.sh @@ -35,7 +35,7 @@ for i in $(seq 10); do info "Comparing lint/chart-needs #$i" # Remove azuredisk-csi-driver repo to ensure consistent output (repo addition message) ${helm} repo remove azuredisk-csi-driver &>/dev/null || true - ${helmfile} -f ${chart_need_case_input_dir}/${config_file} lint --include-needs | grep -v Linting | grep -v "has been removed" | grep -Ev "(Warning:.*is not a valid SemVerV2|\[WARNING\].*is not a valid SemVerV2|failed to load plugins)" > ${chart_needs_lint_reverse} || fail "\"helmfile lint\" shouldn't fail" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} lint --include-needs | grep -v Linting | grep -v "has been removed" | grep -Ev "(Updating repo|Hang tight while we grab|Update Complete|Successfully got an update from|Warning:.*is not a valid SemVerV2|\[WARNING\].*is not a valid SemVerV2|failed to load plugins)" > ${chart_needs_lint_reverse} || fail "\"helmfile lint\" shouldn't fail" diff -u ${lint_out_file} ${chart_needs_lint_reverse} || fail "\"helmfile lint\" should be consistent" done @@ -43,7 +43,7 @@ for i in $(seq 10); do info "Comparing diff/chart-needs #$i" # Remove azuredisk-csi-driver repo to ensure consistent output (repo addition message) ${helm} repo remove azuredisk-csi-driver &>/dev/null || true - ${helmfile} -f ${chart_need_case_input_dir}/${config_file} diff --include-needs | grep -Ev "Comparing release=azuredisk-csi-storageclass, chart=.*/chartify.*/azuredisk-csi-storageclass" > ${chart_needs_diff_reverse}.tmp || fail "\"helmfile diff\" shouldn't fail" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} diff --include-needs | grep -Ev "(Updating repo|Hang tight while we grab|Update Complete|Successfully got an update from|Comparing release=azuredisk-csi-storageclass, chart=.*/chartify.*/azuredisk-csi-storageclass)" > ${chart_needs_diff_reverse}.tmp || fail "\"helmfile diff\" shouldn't fail" cat ${chart_needs_diff_reverse}.tmp | sed -E '/\*{20}/,/\*{20}/d' > ${chart_needs_diff_reverse} # With --enable-live-output, there's a race condition that can cause non-deterministic ordering