* feat: add `inherits:` for sub-helmfile config inheritance
Add an opt-in `inherits:` field to `helmfiles:` entries so a sub-helmfile
can inherit specific configuration categories from its parent:
helmfiles:
- path: myapp.yaml
inherits: [repositories, environments]
Allowed values: repositories, helmDefaults, commonLabels, apiVersions,
kubeVersion, templates, environments. Child values win; parent fills gaps
(consistent with `bases:`). This directly fixes#1495, where a repository
declared in the parent was unavailable to sub-helmfiles, producing a
confusing "repo not found" error.
Implementation notes:
- The 6 pure fields (repositories, helmDefaults, commonLabels, apiVersions,
kubeVersion, templates) are merged post-load via MergeInherited; verified
all are consumed post-load (ExecuteTemplates/converge), never at parse.
- environments is injected pre-load as ctxEnv, because RenderedValues is
baked at load time; the parent's resolved values become the base and the
child's own environments: block overrides per key.
- helmDefaults uses a *HelmSpec pointer (value type is non-comparable) with
a no-override mergo merge, so a child that omits helmDefaults inherits the
parent's fully.
- A footgun warning (WarnUninheritedRepos) suggests
`inherits: [repositories]` when a release references a repo the parent
declares but the child lacks.
- Unknown inherits keys are rejected at parse time with the allowed set.
Inheritance is opt-in and fully backward compatible: empty (the default)
preserves the historical independent-sub-helmfile behavior.
Fixes#1495
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address review — deep-copy inherited config and fix bases: doc link
- BuildInheritedConfig now deep-copies the pure fields via a YAML round-trip
(Env via environment.DeepCopy) so the returned config never aliases the
parent state's slices/maps, matching its doc comment. Now returns an error
to surface round-trip failures; the call site in processNestedHelmfiles is
updated. Added TestBuildInheritedConfig_PureFieldsAreDeepCopied to lock
in the no-aliasing guarantee.
- Fix the broken `bases:` anchor (#) in shared-configuration-across-teams.md
to point to writing-helmfile.md#layering-state-files.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address review — reject inherits without path and document helmDefaults caveat
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address review — make AllowedInherits immutable and clarify effective-repo wording
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
PR #2367 introduced CLIOverrides to give --state-values-set element-by-element
array merge semantics. However, nested helmfile values (helmfiles[].values:)
were also routed into CLIOverrides, causing their arrays to merge instead of
replace. This broke the pre-v1.3.0 behavior where passing an array via
helmfiles[].values: would fully replace the child's default array.
Add OverrideValuesAreCLI flag to SubhelmfileEnvironmentSpec so the loader can
distinguish CLI flags from nested helmfile values. CLI values continue using
CLIOverrides (element-by-element merge); nested helmfile values now use Values
(Sparse merge strategy → full array replacement).
Fixes#2451
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
This is a successor to #596. We need a smooth migration path from `gopkg.in/yaml.v2`, and this pull request moves it forward with `goccy/go-yaml` instead of `gopkg.in/yaml.v3`. Merging this unblocks users stuck in Helmfile v0.146.x or earlier due to #435, so that they can upgrade to 0.147.x or greater without updating their helmfile configs.
We previously tried to upgrade to `yaml.v3` (https://github.com/helmfile/helmfile/issues/394) in Helmfile v0.x, presuming it won't break anything. Apparently, it broke use-cases where you want to layer release's `values` field over three or more release templates and releases (#435).
We then tried to bring back `yaml.v2` for Helmfile v0.x and keep `yaml.v3` for the upcoming Helmfile v1. However, it failed due to incompatibility in the Unmarshaller interface between `yaml.v2` and `yaml.v3` (https://github.com/helmfile/helmfile/pull/596).
`goccy/go-yaml` is, from my observation, a well-maintained alternative to `yaml.v2`. One of its premises is that it enables us to swap the implementation from `gopkg.in/yaml.v2` to `goccy/go-yaml` just by replacing the import directive. It seems to use the same `Unmarshaller` interface as yaml.v2 too.
Once this PR gets merged, I'd like to follow-up with adding a new build-time variable and an envvar to set the proper default for the yaml parser Helmfile uses and the ability to switch the parser at runtime. All in all, the next Helmfile release, v0.150.0 will get reverted to use `gopkg.in/yaml.v2` by default which resolves#435.
New users who started using Helmfile since any of v0.148.0, v0.148.1, and v0.149.0 might be already relying on the new behavior, They might need to specify a new envvar to enable `goccy/go-yaml`.
Signed-off-by: yxxhero <aiopsclub@163.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: yxxhero <aiopsclub@163.com>
Changes:
- Prevent Helmfile from unnecessarily running `helm repo add` and `helm repo up` against repositories for unused repositories(repositories of releases filtered out by selector)
- Fixes#1330
`--retain-values-files` prevents temporary values files that were passed to Helm commands run by Helmfile for debugging purpose.
With that, you can manually rerun helm commands that were logged when `--log-level=debug` is enabled.
Resolves ##1117
The addition of `--set k1=v1,k2=v2` and `--values file1 --values file2` was originally planned in #361.
But it turned out we already had `--values` for existing helmfile commands like `sync`. Duplicated flags doesn't work, obviously.
So this actually add `--state-values-set k1=v1,k2=v2` and `--set-values-file file1 --set-values-file file2`.
They are called "state" values according to the discussion we had at #640Resolves#361