Compare commits

...

2 Commits

Author SHA1 Message Date
Shane Starcher 3145aca7c0
Merge ecf76e0268 into 8034acff6e 2025-10-25 08:47:45 +08:00
Shane Starcher ecf76e0268 feat: add --skip-charts flag to build command
Add a --skip-charts flag to the `helmfile build` command to allow users
to skip chart preparation, following the same pattern as the list and
destroy commands.

This addresses an issue where `helmfile build` would run `helm template`
on kustomize resources during chart preparation, even though build is
meant to be a read-only inspection command.

Changes:
- Add SkipCharts field to BuildOptions
- Add --skip-charts flag to build command CLI
- Update StateConfigProvider interface to include SkipCharts()
- Update PrintState() to conditionally skip withPreparedCharts when flag is set

By default, the flag is false (charts are prepared) to maintain backward
compatibility. Users can now run `helmfile build --skip-charts` to get
fast output without chart preparation.

Signed-off-by: Shane Starcher <shanestarcher@gmail.com>
2025-10-05 07:42:46 +08:00
4 changed files with 61 additions and 11 deletions

View File

@ -32,6 +32,7 @@ func NewBuildCmd(globalCfg *config.GlobalImpl) *cobra.Command {
f := cmd.Flags()
f.BoolVar(&buildOptions.EmbedValues, "embed-values", false, "Read all the values files for every release and embed into the output helmfile.yaml")
f.BoolVar(&buildOptions.SkipCharts, "skip-charts", false, "don't prepare charts when building releases")
return cmd
}

View File

@ -521,11 +521,52 @@ func (a *App) PrintDAGState(c DAGConfigProvider) error {
func (a *App) PrintState(c StateConfigProvider) error {
return a.ForEachState(func(run *Run) (_ bool, errs []error) {
err := run.withPreparedCharts("build", state.ChartPrepareOptions{
SkipRepos: true,
SkipDeps: true,
Concurrency: 2,
}, func() {
var err error
if !c.SkipCharts() {
err = run.withPreparedCharts("build", state.ChartPrepareOptions{
SkipRepos: true,
SkipDeps: true,
Concurrency: 2,
}, func() {
if c.EmbedValues() {
for i := range run.state.Releases {
r := run.state.Releases[i]
values, err := run.state.LoadYAMLForEmbedding(&r, r.Values, r.MissingFileHandler, r.ValuesPathPrefix)
if err != nil {
errs = []error{err}
return
}
run.state.Releases[i].Values = values
secrets, err := run.state.LoadYAMLForEmbedding(&r, r.Secrets, r.MissingFileHandler, r.ValuesPathPrefix)
if err != nil {
errs = []error{err}
return
}
run.state.Releases[i].Secrets = secrets
}
}
stateYaml, err := run.state.ToYaml()
if err != nil {
errs = []error{err}
return
}
sourceFile, err := run.state.FullFilePath()
if err != nil {
errs = []error{err}
return
}
fmt.Printf("---\n# Source: %s\n\n%+v", sourceFile, stateYaml)
errs = []error{}
})
} else {
if c.EmbedValues() {
for i := range run.state.Releases {
r := run.state.Releases[i]
@ -533,7 +574,7 @@ func (a *App) PrintState(c StateConfigProvider) error {
values, err := run.state.LoadYAMLForEmbedding(&r, r.Values, r.MissingFileHandler, r.ValuesPathPrefix)
if err != nil {
errs = []error{err}
return
return false, errs
}
run.state.Releases[i].Values = values
@ -541,7 +582,7 @@ func (a *App) PrintState(c StateConfigProvider) error {
secrets, err := run.state.LoadYAMLForEmbedding(&r, r.Secrets, r.MissingFileHandler, r.ValuesPathPrefix)
if err != nil {
errs = []error{err}
return
return false, errs
}
run.state.Releases[i].Secrets = secrets
@ -551,24 +592,24 @@ func (a *App) PrintState(c StateConfigProvider) error {
stateYaml, err := run.state.ToYaml()
if err != nil {
errs = []error{err}
return
return false, errs
}
sourceFile, err := run.state.FullFilePath()
if err != nil {
errs = []error{err}
return
return false, errs
}
fmt.Printf("---\n# Source: %s\n\n%+v", sourceFile, stateYaml)
errs = []error{}
})
}
if err != nil {
errs = append(errs, err)
}
return
return false, errs
}, false, SetFilter(true))
}

View File

@ -264,6 +264,7 @@ type StatusesConfigProvider interface {
type StateConfigProvider interface {
EmbedValues() bool
SkipCharts() bool
}
type DAGConfigProvider any

View File

@ -4,6 +4,8 @@ package config
type BuildOptions struct {
// EmbedValues is true if the values should be embedded
EmbedValues bool
// SkipCharts makes Build skip `withPreparedCharts`
SkipCharts bool
}
// NewBuildOptions creates a new Apply
@ -29,3 +31,8 @@ func NewBuildImpl(g *GlobalImpl, b *BuildOptions) *BuildImpl {
func (b *BuildImpl) EmbedValues() bool {
return b.BuildOptions.EmbedValues
}
// SkipCharts returns skipCharts flag
func (b *BuildImpl) SkipCharts() bool {
return b.BuildOptions.SkipCharts
}