Fix intermittent failures while building deps on local chart (#1532)
Fixes #1521
This commit is contained in:
parent
3018e82902
commit
d9286ed8f6
|
|
@ -19,8 +19,6 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
|
|
||||||
"github.com/variantdev/chartify"
|
"github.com/variantdev/chartify"
|
||||||
|
|
||||||
"github.com/roboll/helmfile/pkg/environment"
|
"github.com/roboll/helmfile/pkg/environment"
|
||||||
|
|
@ -1044,89 +1042,36 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, builds []*chartPrepareResult) error {
|
func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, builds []*chartPrepareResult) error {
|
||||||
type buildOutput struct {
|
// NOTES:
|
||||||
diagnostic string
|
// 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.
|
||||||
|
//
|
||||||
|
// See https://github.com/roboll/helmfile/issues/1438
|
||||||
|
// 2. Even if it isn't on the same local chart, `helm dep build` intermittently fails when run concurrentl
|
||||||
|
// So we shouldn't use goroutines like we do for other helm operations here.
|
||||||
|
//
|
||||||
|
// See https://github.com/roboll/helmfile/issues/1521
|
||||||
|
for _, r := range builds {
|
||||||
|
if err := helm.BuildDeps(r.releaseName, r.chartPath); err != nil {
|
||||||
|
if r.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",
|
||||||
|
r.releaseName,
|
||||||
|
r.chartName,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
|
||||||
buildQueue := make(chan *chartPrepareResult)
|
st.logger.Warn(diagnostic)
|
||||||
|
|
||||||
buildOutputQueue := make(chan *buildOutput)
|
continue
|
||||||
|
|
||||||
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
|
return fmt.Errorf("building dependencies of local chart: %w", err)
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue