Hello community, here is the log from the commit of package helmfile for openSUSE:Factory checked in at 2020-09-01 20:08:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/helmfile (Old) and /work/SRC/openSUSE:Factory/.helmfile.new.3399 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "helmfile" Tue Sep 1 20:08:25 2020 rev:5 rq:830800 version:0.125.9 Changes: -------- --- /work/SRC/openSUSE:Factory/helmfile/helmfile.changes 2020-08-18 12:02:35.231419735 +0200 +++ /work/SRC/openSUSE:Factory/.helmfile.new.3399/helmfile.changes 2020-09-01 20:09:09.628642703 +0200 @@ -1,0 +2,17 @@ +Mon Aug 31 12:20:16 UTC 2020 - Manfred Hollstein <[email protected]> + +- v0.125.9: Merge pull request #1442 from roboll/fix-duplicate-with-kubectx-per-r… + * c575587 (HEAD, tag: v0.125.9, origin/master, origin/HEAD, master) + Merge pull request #1442 from roboll/fix-duplicate-with-kubectx-per-release + * f2dfa7c Fix kubeContext not taken into account for release uniqueness + * 41cd1fe Fix race while running helm dep build on local chart (#1439) + * 94e01b7 Bump chartify to 0.4.2 (#1437) + * 85e7798 Update to the latest version of helm-diff plugin (#1430) + * b42e847 Fix race while running helm dep build on local chart + +- v0.125.8: Fix regression in helmfile deps (#1431) + * 14e2b9e (HEAD, tag: v0.125.8, origin/master, origin/HEAD, master) + Fix regression in helmfile deps (#1431) + * 90a4122 fix: panic when using helm v3.3 (#1427) (#1428) + +------------------------------------------------------------------- Old: ---- helmfile-0.125.7.tar.gz New: ---- helmfile-0.125.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ helmfile.spec ++++++ --- /var/tmp/diff_new_pack.zOcA0z/_old 2020-09-01 20:09:11.752643697 +0200 +++ /var/tmp/diff_new_pack.zOcA0z/_new 2020-09-01 20:09:11.752643697 +0200 @@ -16,9 +16,9 @@ # Please submit bugfixes or comments via https://bugs.opensuse.org/ # -%define git_commit a9aa7af5725ddf95b73b783202ec953897d67240 +%define git_commit c575587e1ff2aa8dac8269e071c1c65fa5181865 Name: helmfile -Version: 0.125.7 +Version: 0.125.9 Release: 0 Summary: Deploy Kubernetes Helm Charts License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.zOcA0z/_old 2020-09-01 20:09:11.804643721 +0200 +++ /var/tmp/diff_new_pack.zOcA0z/_new 2020-09-01 20:09:11.804643721 +0200 @@ -5,7 +5,7 @@ <param name="exclude">.git</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> - <param name="revision">v0.125.7</param> + <param name="revision">v0.125.9</param> <param name="changesgenerate">enable</param> </service> <service name="recompress" mode="disabled"> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.zOcA0z/_old 2020-09-01 20:09:11.840643738 +0200 +++ /var/tmp/diff_new_pack.zOcA0z/_new 2020-09-01 20:09:11.844643740 +0200 @@ -1,4 +1,4 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/roboll/helmfile.git</param> - <param name="changesrevision">a9aa7af5725ddf95b73b783202ec953897d67240</param></service></servicedata> + <param name="changesrevision">f2dfa7ce642f36c70a0957a62c0c830d52bae537</param></service></servicedata> \ No newline at end of file ++++++ helmfile-0.125.7.tar.gz -> helmfile-0.125.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/Dockerfile.helm3 new/helmfile-0.125.9/Dockerfile.helm3 --- old/helmfile-0.125.7/Dockerfile.helm3 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/Dockerfile.helm3 2020-08-29 04:45:13.000000000 +0200 @@ -32,7 +32,7 @@ chmod +x kubectl && \ mv kubectl /usr/local/bin/kubectl -RUN helm plugin install https://github.com/databus23/helm-diff --version v3.0.0-rc.7 && \ +RUN helm plugin install https://github.com/databus23/helm-diff --version v3.1.3 && \ helm plugin install https://github.com/futuresimple/helm-secrets && \ helm plugin install https://github.com/hypnoglow/helm-s3.git && \ helm plugin install https://github.com/aslafy-z/helm-git.git diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/go.mod new/helmfile-0.125.9/go.mod --- old/helmfile-0.125.7/go.mod 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/go.mod 2020-08-29 04:45:13.000000000 +0200 @@ -24,7 +24,7 @@ github.com/spf13/cobra v0.0.3 github.com/tatsushid/go-prettytable v0.0.0-20141013043238-ed2d14c29939 github.com/urfave/cli v1.20.0 - github.com/variantdev/chartify v0.4.1 + github.com/variantdev/chartify v0.4.2 github.com/variantdev/dag v0.0.0-20191028002400-bb0b3c785363 github.com/variantdev/vals v0.10.0 go.uber.org/multierr v1.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/go.sum new/helmfile-0.125.9/go.sum --- old/helmfile-0.125.7/go.sum 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/go.sum 2020-08-29 04:45:13.000000000 +0200 @@ -833,6 +833,8 @@ github.com/variantdev/chartify v0.4.0/go.mod h1:Fr4oPNJ4b19knlovn0wBoU2+MZxQdBacmBs30wwgAFk= github.com/variantdev/chartify v0.4.1 h1:0a8Ipf7n65mbQaAAfI9JEbdDauMnwKs0Gdq/yu5jI7I= github.com/variantdev/chartify v0.4.1/go.mod h1:Fr4oPNJ4b19knlovn0wBoU2+MZxQdBacmBs30wwgAFk= +github.com/variantdev/chartify v0.4.2 h1:Vw647JysxJ4kz+6vOxOmrctRoTTf5qmpleB6hTQEjUk= +github.com/variantdev/chartify v0.4.2/go.mod h1:Fr4oPNJ4b19knlovn0wBoU2+MZxQdBacmBs30wwgAFk= github.com/variantdev/dag v0.0.0-20191028002400-bb0b3c785363 h1:KrfQBEUn+wEOQ/6UIfoqRDvn+Q/wZridQ7t0G1vQqKE= github.com/variantdev/dag v0.0.0-20191028002400-bb0b3c785363/go.mod h1:pH1TQsNSLj2uxMo9NNl9zdGy01Wtn+/2MT96BrKmVyE= github.com/variantdev/vals v0.4.0 h1:O1O7/sWhlvozcY2DjZBzlE1notxwVo6UBT1+w7HsO/k= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/pkg/app/app.go new/helmfile-0.125.9/pkg/app/app.go --- old/helmfile-0.125.7/pkg/app/app.go 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/pkg/app/app.go 2020-08-29 04:45:13.000000000 +0200 @@ -103,7 +103,10 @@ func (a *App) Deps(c DepsConfigProvider) error { return a.ForEachState(func(run *Run) (_ bool, errs []error) { - prepErr := run.withPreparedCharts(false, c.SkipRepos(), "deps", func() { + prepErr := run.withPreparedCharts("deps", state.ChartPrepareOptions{ + SkipRepos: c.SkipRepos(), + SkipResolve: true, + }, func() { errs = run.Deps(c) }) @@ -119,7 +122,7 @@ return a.ForEachState(func(run *Run) (_ bool, errs []error) { var reposErr error - err := run.withPreparedCharts(false, true, "repos", func() { + err := run.withPreparedCharts("repos", state.ChartPrepareOptions{SkipRepos: true}, func() { reposErr = run.Repos(c) }) @@ -137,7 +140,7 @@ func (a *App) DeprecatedSyncCharts(c DeprecatedChartsConfigProvider) error { return a.ForEachState(func(run *Run) (_ bool, errs []error) { - err := run.withPreparedCharts(false, true, "charts", func() { + err := run.withPreparedCharts("charts", state.ChartPrepareOptions{SkipRepos: true}, func() { errs = run.DeprecatedSyncCharts(c) }) @@ -163,7 +166,7 @@ var errs []error - prepErr := run.withPreparedCharts(false, c.SkipDeps(), "diff", func() { + prepErr := run.withPreparedCharts("diff", state.ChartPrepareOptions{SkipRepos: c.SkipDeps()}, func() { msg, matched, affected, errs = a.diff(run, c) }) @@ -218,7 +221,10 @@ return a.ForEachState(func(run *Run) (ok bool, errs []error) { // `helm template` in helm v2 does not support local chart. // So, we set forceDownload=true for helm v2 only - prepErr := run.withPreparedCharts(!run.helm.IsHelm3(), c.SkipDeps(), "template", func() { + prepErr := run.withPreparedCharts("template", state.ChartPrepareOptions{ + ForceDownload: !run.helm.IsHelm3(), + SkipRepos: c.SkipDeps(), + }, func() { ok, errs = a.template(run, c) }) @@ -233,7 +239,10 @@ func (a *App) Lint(c LintConfigProvider) error { return a.ForEachState(func(run *Run) (_ bool, errs []error) { // `helm lint` on helm v2 and v3 does not support remote charts, that we need to set `forceDownload=true` here - prepErr := run.withPreparedCharts(true, c.SkipDeps(), "lint", func() { + prepErr := run.withPreparedCharts("lint", state.ChartPrepareOptions{ + ForceDownload: true, + SkipRepos: c.SkipDeps(), + }, func() { errs = run.Lint(c) }) @@ -247,7 +256,9 @@ func (a *App) Sync(c SyncConfigProvider) error { return a.ForEachState(func(run *Run) (ok bool, errs []error) { - prepErr := run.withPreparedCharts(false, c.SkipDeps(), "sync", func() { + prepErr := run.withPreparedCharts("sync", state.ChartPrepareOptions{ + SkipRepos: c.SkipDeps(), + }, func() { ok, errs = a.sync(run, c) }) @@ -269,7 +280,9 @@ opts = append(opts, SetRetainValuesFiles(c.RetainValuesFiles())) err := a.ForEachState(func(run *Run) (ok bool, errs []error) { - prepErr := run.withPreparedCharts(false, c.SkipDeps(), "apply", func() { + prepErr := run.withPreparedCharts("apply", state.ChartPrepareOptions{ + SkipRepos: c.SkipDeps(), + }, func() { matched, updated, es := a.apply(run, c) mut.Lock() @@ -301,7 +314,9 @@ func (a *App) Status(c StatusesConfigProvider) error { return a.ForEachState(func(run *Run) (_ bool, errs []error) { - err := run.withPreparedCharts(false, true, "status", func() { + err := run.withPreparedCharts("status", state.ChartPrepareOptions{ + SkipRepos: true, + }, func() { errs = run.Status(c) }) @@ -315,7 +330,9 @@ func (a *App) Delete(c DeleteConfigProvider) error { return a.ForEachState(func(run *Run) (ok bool, errs []error) { - err := run.withPreparedCharts(false, true, "delete", func() { + err := run.withPreparedCharts("delete", state.ChartPrepareOptions{ + SkipRepos: true, + }, func() { ok, errs = a.delete(run, c.Purge(), c) }) @@ -329,7 +346,9 @@ func (a *App) Destroy(c DestroyConfigProvider) error { return a.ForEachState(func(run *Run) (ok bool, errs []error) { - err := run.withPreparedCharts(false, true, "destroy", func() { + err := run.withPreparedCharts("destroy", state.ChartPrepareOptions{ + SkipRepos: true, + }, func() { ok, errs = a.delete(run, true, c) }) @@ -349,7 +368,9 @@ "or set helm.sh/hook-delete-policy\n") } - err := run.withPreparedCharts(false, true, "test", func() { + err := run.withPreparedCharts("test", state.ChartPrepareOptions{ + SkipRepos: true, + }, func() { errs = run.Test(c) }) @@ -363,7 +384,9 @@ func (a *App) PrintState(c StateConfigProvider) error { return a.ForEachState(func(run *Run) (_ bool, errs []error) { - err := run.withPreparedCharts(false, true, "build", func() { + err := run.withPreparedCharts("build", state.ChartPrepareOptions{ + SkipRepos: true, + }, func() { state, err := run.state.ToYaml() if err != nil { errs = []error{err} @@ -386,7 +409,9 @@ var releases []*HelmRelease err := a.ForEachState(func(run *Run) (_ bool, errs []error) { - err := run.withPreparedCharts(false, true, "list", func() { + err := run.withPreparedCharts("list", state.ChartPrepareOptions{ + SkipRepos: true, + }, func() { //var releases m for _, r := range run.state.Releases { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/pkg/app/run.go new/helmfile-0.125.9/pkg/app/run.go --- old/helmfile-0.125.7/pkg/app/run.go 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/pkg/app/run.go 2020-08-29 04:45:13.000000000 +0200 @@ -36,12 +36,12 @@ return AskForConfirmation(msg) } -func (r *Run) withPreparedCharts(forceDownload, skipRepos bool, helmfileCommand string, f func()) error { +func (r *Run) withPreparedCharts(helmfileCommand string, opts state.ChartPrepareOptions, f func()) error { if r.ReleaseToChart != nil { panic("Run.PrepareCharts can be called only once") } - if !skipRepos { + if !opts.SkipRepos { ctx := r.ctx if err := ctx.SyncReposOnce(r.state, r.helm); err != nil { return err @@ -59,7 +59,7 @@ return err } - releaseToChart, errs := r.state.PrepareCharts(r.helm, dir, 2, helmfileCommand, forceDownload, skipRepos) + releaseToChart, errs := r.state.PrepareCharts(r.helm, dir, 2, helmfileCommand, opts) if len(errs) > 0 { return fmt.Errorf("%v", errs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/pkg/helmexec/exec.go new/helmfile-0.125.9/pkg/helmexec/exec.go --- old/helmfile-0.125.7/pkg/helmexec/exec.go 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/pkg/helmexec/exec.go 2020-08-29 04:45:13.000000000 +0200 @@ -48,40 +48,28 @@ return zap.New(core).Sugar() } -func getHelmVersion(helmBinary string, logger *zap.SugaredLogger, runner Runner) Version { +// versionRegex matches versions like v1.1.1 and v1.1 +var versionRegex = regexp.MustCompile("v(?P<major>\\d+)\\.(?P<minor>\\d+)(?:\\.(?P<patch>\\d+))?") - // Autodetect from `helm verison` - bytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil) - if err != nil { - panic(err) +func parseHelmVersion(versionStr string) (Version, error) { + if len(versionStr) == 0 { + return Version{}, nil } - if bytes == nil || len(bytes) == 0 { - return Version{} + matches := versionRegex.FindStringSubmatch(versionStr) + if len(matches) == 0 { + return Version{}, fmt.Errorf("error parsing helm verion '%s'", versionStr) } - - re := regexp.MustCompile("v(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)") - matches := re.FindStringSubmatch(string(bytes)) - result := make(map[string]string) - for i, name := range re.SubexpNames() { + for i, name := range versionRegex.SubexpNames() { result[name] = matches[i] } - major, err := strconv.Atoi(result["major"]) - if err != nil { - panic(err) - } - - minor, err := strconv.Atoi(result["minor"]) - if err != nil { - panic(err) - } - - patch, err := strconv.Atoi(result["patch"]) - if err != nil { - panic(err) - } + // We ignore errors because regex matches only integers + // If any of the parts does not exist - default "0" will be used + major, _ := strconv.Atoi(result["major"]) + minor, _ := strconv.Atoi(result["minor"]) + patch, _ := strconv.Atoi(result["patch"]) // Support explicit helm3 opt-in via environment variable if os.Getenv("HELMFILE_HELM3") != "" && major < 3 { @@ -89,21 +77,37 @@ Major: 3, Minor: 0, Patch: 0, - } + }, nil } return Version{ Major: major, Minor: minor, Patch: patch, + }, nil +} + +func getHelmVersion(helmBinary string, runner Runner) (Version, error) { + + // Autodetect from `helm verison` + bytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil) + if err != nil { + return Version{}, fmt.Errorf("error determining helm version: %w", err) } + + return parseHelmVersion(string(bytes)) } // New for running helm commands func New(helmBinary string, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer { + // TODO: proper error handling + version, err := getHelmVersion(helmBinary, runner) + if err != nil { + panic(err) + } return &execer{ helmBinary: helmBinary, - version: getHelmVersion(helmBinary, logger, runner), + version: version, logger: logger, kubeContext: kubeContext, runner: runner, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/pkg/helmexec/exec_test.go new/helmfile-0.125.9/pkg/helmexec/exec_test.go --- old/helmfile-0.125.7/pkg/helmexec/exec_test.go 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/pkg/helmexec/exec_test.go 2020-08-29 04:45:13.000000000 +0200 @@ -570,3 +570,50 @@ } } + +func Test_parseHelmVersion(t *testing.T) { + tests := []struct { + ver string + want Version + wantErr bool + }{ + { + ver: "v1.2.3", + want: Version{ + Major: 1, + Minor: 2, + Patch: 3, + }, + wantErr: false, + }, + { + ver: "v1.2", + want: Version{ + Major: 1, + Minor: 2, + Patch: 0, + }, + wantErr: false, + }, + { + ver: "v1", + wantErr: true, + }, + { + ver: "1.1.1", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.ver, func(t *testing.T) { + got, err := parseHelmVersion(tt.ver) + if (err != nil) != tt.wantErr { + t.Errorf("parseHelmVersion() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("parseHelmVersion() got = %v, want %v", got, tt.want) + } + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helmfile-0.125.7/pkg/state/state.go new/helmfile-0.125.9/pkg/state/state.go --- old/helmfile-0.125.7/pkg/state/state.go 2020-08-14 12:52:00.000000000 +0200 +++ new/helmfile-0.125.9/pkg/state/state.go 2020-08-29 04:45:13.000000000 +0200 @@ -6,6 +6,7 @@ "encoding/hex" "errors" "fmt" + "golang.org/x/sync/errgroup" "io" "io/ioutil" "os" @@ -519,6 +520,11 @@ func ReleaseToID(r *ReleaseSpec) string { var id string + kc := r.KubeContext + if kc != "" { + id += kc + "/" + } + tns := r.TillerNamespace if tns != "" { id += tns + "/" @@ -792,6 +798,21 @@ return result } +type ChartPrepareOptions struct { + ForceDownload bool + SkipRepos bool + SkipResolve bool +} + +type chartPrepareResult struct { + releaseName string + chartName string + chartPath string + err error + buildDeps bool + chartFetchedByGoGetter bool +} + // PrepareCharts creates temporary directories of charts. // // Each resulting "chart" can be one of the followings: @@ -806,21 +827,15 @@ // Otheriwse, if a chart is not a helm chart, it will call "chartify" to turn it into a chart. // // If exists, it will also patch resources by json patches, strategic-merge patches, and injectors. -func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurrency int, helmfileCommand string, forceDownload, skipDeps bool) (map[string]string, []error) { +func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurrency int, helmfileCommand string, opts ChartPrepareOptions) (map[string]string, []error) { releases := releasesNeedCharts(st.Releases) temp := make(map[string]string, len(releases)) - type downloadResults struct { - releaseName string - chartPath string - err error - diagnostic string - } errs := []error{} jobQueue := make(chan *ReleaseSpec, len(releases)) - results := make(chan *downloadResults, len(releases)) + results := make(chan *chartPrepareResult, len(releases)) var helm3 bool @@ -828,13 +843,15 @@ helm3 = helm.IsHelm3() } - updated, err := st.ResolveDeps() - if err != nil { - return nil, []error{err} + if !opts.SkipResolve { + updated, err := st.ResolveDeps() + if err != nil { + return nil, []error{err} + } + *st = *updated } - *st = *updated - var diagnostics []string + var builds []*chartPrepareResult st.scatterGather( concurrency, @@ -853,7 +870,7 @@ // If it wasn't called here, Helmfile can end up an issue like // https://github.com/roboll/helmfile/issues/1328 if _, err := st.triggerPrepareEvent(release, helmfileCommand); err != nil { - results <- &downloadResults{err: err} + results <- &chartPrepareResult{err: err} return } @@ -861,7 +878,7 @@ chartPath, err := st.goGetterChart(chartName, release.Directory, release.ForceGoGetter) if err != nil { - results <- &downloadResults{err: fmt.Errorf("release %q: %w", release.Name, err)} + results <- &chartPrepareResult{err: fmt.Errorf("release %q: %w", release.Name, err)} return } @@ -870,11 +887,11 @@ chartification, clean, err := st.PrepareChartify(helm, release, chartPath, workerIndex) defer clean() if err != nil { - results <- &downloadResults{err: err} + results <- &chartPrepareResult{err: err} return } - var diagnostic string + var buildDeps bool if chartification != nil { c := chartify.New( @@ -884,7 +901,7 @@ out, err := c.Chartify(release.Name, chartPath, chartify.WithChartifyOpts(chartification.Opts)) if err != nil { - results <- &downloadResults{err: err} + results <- &chartPrepareResult{err: err} return } else { // TODO Chartify @@ -916,25 +933,8 @@ // a broken remote chart won't completely block their job. chartPath = normalizeChart(st.basePath, chartPath) - if !skipDeps { - if err := helm.BuildDeps(release.Name, chartPath); err != nil { - if chartFetchedByGoGetter { - diagnostic = fmt.Sprintf( - "WARN: `helm dep build` failed. While processing release %q, Helmfile observed that remote chart %q fetched by go-getter is seemingly broken. "+ - "One of well-known causes of this is that the chart has outdated Chart.lock, which needs the chart maintainer needs to run `helm dep up`. "+ - "Helmfile is tolerating the error to avoid blocking you until the remote chart gets fixed. "+ - "But this may result in any failure later if the chart is broken badly. FYI, the tolerated error was: %v", - release.Name, - chartName, - err.Error(), - ) - } else { - results <- &downloadResults{err: err} - return - } - } - } - } else if !forceDownload { + buildDeps = !opts.SkipRepos + } else if !opts.ForceDownload { // At this point, we are sure that either: // 1. It is a local chart and we can use it in later process (helm upgrade/template/lint/etc) // without any modification, or @@ -973,7 +973,7 @@ fetchFlags := st.chartVersionFlags(release) fetchFlags = append(fetchFlags, "--untar", "--untardir", chartPath) if err := helm.Fetch(chartName, fetchFlags...); err != nil { - results <- &downloadResults{err: err} + results <- &chartPrepareResult{err: err} return } } @@ -985,38 +985,134 @@ } } - results <- &downloadResults{releaseName: release.Name, chartPath: chartPath, diagnostic: diagnostic} + results <- &chartPrepareResult{ + releaseName: release.Name, + chartName: chartName, + chartPath: chartPath, + buildDeps: buildDeps, + chartFetchedByGoGetter: chartFetchedByGoGetter, + } } }, func() { for i := 0; i < len(releases); i++ { downloadRes := <-results - if d := downloadRes.diagnostic; d != "" { - diagnostics = append(diagnostics, d) - } - if downloadRes.err != nil { errs = append(errs, downloadRes.err) return } temp[downloadRes.releaseName] = downloadRes.chartPath + + if downloadRes.buildDeps { + builds = append(builds, downloadRes) + } } }, ) - sort.Strings(diagnostics) - for _, d := range diagnostics { - st.logger.Warn(d) - } - if len(errs) > 0 { return nil, errs } + + if len(builds) > 0 { + if err := st.runHelmDepBuilds(helm, concurrency, builds); err != nil { + return nil, []error{err} + } + } + return temp, nil } +func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, builds []*chartPrepareResult) error { + type buildOutput struct { + diagnostic string + } + + buildQueue := make(chan *chartPrepareResult) + + buildOutputQueue := make(chan *buildOutput) + + buildWorkers := &errgroup.Group{} + for i := 0; i < concurrency; i++ { + buildWorkers.Go(func() error { + for r := range buildQueue { + out, err := func() (*buildOutput, error) { + if err := helm.BuildDeps(r.releaseName, r.chartPath); err != nil { + if r.chartFetchedByGoGetter { + return &buildOutput{ + diagnostic: fmt.Sprintf( + "WARN: `helm dep build` failed. While processing release %q, Helmfile observed that remote chart %q fetched by go-getter is seemingly broken. "+ + "One of well-known causes of this is that the chart has outdated Chart.lock, which needs the chart maintainer needs to run `helm dep up`. "+ + "Helmfile is tolerating the error to avoid blocking you until the remote chart gets fixed. "+ + "But this may result in any failure later if the chart is broken badly. FYI, the tolerated error was: %v", + r.releaseName, + r.chartName, + err.Error(), + ), + }, nil + } + return nil, err + } + return nil, nil + }() + + if err != nil { + return err + } + + if out != nil { + buildOutputQueue <- out + } + } + + return nil + }) + } + + diagnosticsAggregator := &sync.WaitGroup{} + diagnosticsAggregator.Add(1) + go func() { + var diagnostics []string + for r := range buildOutputQueue { + if d := r.diagnostic; d != "" { + diagnostics = append(diagnostics, d) + } + } + + sort.Strings(diagnostics) + for _, d := range diagnostics { + st.logger.Warn(d) + } + + diagnosticsAggregator.Done() + }() + + built := map[string]bool{} + + for _, b := range builds { + // `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. + // + // See https://github.com/roboll/helmfile/issues/1438 + if !built[b.chartPath] { + built[b.chartPath] = true + buildQueue <- b + } + } + close(buildQueue) + + if err := buildWorkers.Wait(); err != nil { + return err + } + close(buildOutputQueue) + + diagnosticsAggregator.Wait() + + return nil +} + type TemplateOpts struct { Set []string OutputDirTemplate string ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/variantdev/chartify/chartify.go new/vendor/github.com/variantdev/chartify/chartify.go --- old/vendor/github.com/variantdev/chartify/chartify.go 2020-08-17 17:43:10.000000000 +0200 +++ new/vendor/github.com/variantdev/chartify/chartify.go 2020-08-31 14:23:22.000000000 +0200 @@ -343,7 +343,7 @@ } } - if isChart && (len(u.JsonPatches) > 0 || len(u.StrategicMergePatches) > 0) { + if len(u.JsonPatches) > 0 || len(u.StrategicMergePatches) > 0 { patchOpts := &PatchOpts{ JsonPatches: u.JsonPatches, StrategicMergePatches: u.StrategicMergePatches, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2020-08-17 17:43:12.000000000 +0200 +++ new/vendor/modules.txt 2020-08-31 14:23:25.000000000 +0200 @@ -277,7 +277,7 @@ # github.com/urfave/cli v1.20.0 ## explicit github.com/urfave/cli -# github.com/variantdev/chartify v0.4.1 +# github.com/variantdev/chartify v0.4.2 ## explicit github.com/variantdev/chartify # github.com/variantdev/dag v0.0.0-20191028002400-bb0b3c785363
