Before this fix, .Values in patch template files only contained environment
values, not the release's own values. This meant references like
{{ .Values.ingress.enabled }} would fail when ingress.enabled was set in
the release's values: file rather than environment values.
Now patch gotmpl files see .Values as merged(environment values, release values),
matching user expectations that values defined in the release should be
accessible in conditional patches.
Fixes#1904
Signed-off-by: yxxhero <aiopsclub@163.com>
Changed SetValue.Values type from []string to []any to allow passing
maps (not just strings) in the values field of set/setTemplate.
Previously, YAML like:
setTemplate:
- name: source.helm.parameters
values:
- name: demo
- version: v2
would fail with 'cannot unmarshal !!map into string'. Map values are
now serialized to JSON when generating --set flags.
Fixes#1021
Signed-off-by: yxxhero <aiopsclub@163.com>
When helmfile.d contains multiple release files and one release has a
local chart dependency (e.g. chart: ../chart), the dependency path was
passed to DirectoryExistsAt without normalizing against basePath. This
caused the path to be resolved against CWD instead of the helmfile
directory, so the local chart was not detected and helmfile tried to
resolve it as a remote repo, failing with:
'failed reading adhoc dependencies: no helm list entry found for repository'
Fixes#2596
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: refresh Chart.lock after rewriting file:// dependencies
`rewriteChartDependencies` rewrites relative `file://` repository URLs in
Chart.yaml to absolute paths so chartify can resolve them from a temp
directory. That mutates the Chart.yaml dependencies block, which
invalidates the Chart.lock digest (helm computes it as
`sha256(json.Marshal([2][]Dependency{req, lock}))` over the dependencies).
Once the lock is out of sync, downstream `helm dependency build` errors
with "the lock file (Chart.lock) is out of sync with the dependencies
file (Chart.yaml)" and chartify falls back to `helm dependency update`.
`dep update` then re-resolves Chart.yaml's version constraints against
the chart repo, so any constraint that admits newer versions
(e.g. `version: "*"`, `~1.0`) silently picks up a newer dependency on
every render — even though Chart.lock pins a specific version.
Repro:
- Chart.yaml has `version: "*"` for some-dep, Chart.lock pins 4.1.0,
upstream now publishes 4.2.0.
- `helm template .` honors the cached `charts/some-dep-4.1.0.tgz`.
- `helmfile template` produces 4.2.0, because it triggered chartify
(via jsonPatches/strategic-merge/kustomize/etc), which copied the
chart, ran `dep build` against an out-of-sync lock, fell back to
`dep up`, and re-resolved the wildcard.
This commit refreshes Chart.lock alongside Chart.yaml in the temp copy:
- Mirror the rewritten file:// repository URLs onto matching entries in
Chart.lock's dependencies. Without this, `helm dep build` would resolve
the lock's relative `file://` paths against the temp chart directory
and fail with "directory ... not found".
- Recompute the digest using helm's resolver.HashReq algorithm
(`sha256(json.Marshal([2][]chart.Dependency{req, lock}))`). The
algorithm is small and stable; resolver.HashReq itself lives in an
internal package, so it's inlined here.
- Locked versions are preserved verbatim — only the repository URL is
updated and the digest recomputed. Chart.lock remains the source of
truth for which versions get installed.
- The original Chart.lock on disk is never modified; only the temp copy
is rewritten.
Adds TestRewriteChartDependencies_RefreshesChartLock covering digest
recomputation, file:// URL mirroring, version preservation, untouched
non-file:// deps, and original-on-disk integrity.
Signed-off-by: Shane Starcher <shane.starcher@gmail.com>
* fix: address Copilot review issues for Chart.lock refresh
- Map all helm Dependency fields (alias, condition, tags, import-values,
enabled) when building the request slice for digest computation, not
just name/version/repository. This ensures the recomputed digest
matches Helm's resolver.HashReq for all dependency shapes.
- Match lock entries by Name + Alias (not Name alone) to correctly
handle charts with duplicate dependency names distinguished by alias.
- Log a warning when reading Chart.lock fails with a non-NotExist error,
while still treating a missing Chart.lock as expected.
- Add test case exercising dependencies with alias, condition, tags, and
import-values fields, including same-name deps disambiguated by alias.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Shane Starcher <shane.starcher@gmail.com>
* build(deps): bump github.com/helmfile/chartify to v0.26.4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Shane Starcher <shane.starcher@gmail.com>
* fix: normalize import-values for JSON marshaling and improve test coverage
- Normalize import-values using maputil.RecursivelyStringifyMapKey before
assigning to helmchart.Dependency.ImportValues. When go-yaml v2 decodes
nested maps (e.g. import-values entries with child/parent keys), they
become map[interface{}]interface{} which json.Marshal cannot encode.
This would silently prevent Chart.lock rewriting. The normalization
converts all map keys to strings, making the value JSON-safe.
- Improve TestRewriteChartDependencies_RefreshesChartLockWithExtraFields
to prove that extra fields (condition, tags, import-values) actually
affect the computed digest by comparing digests with and without those
fields and asserting they differ.
Signed-off-by: Shane Starcher <shane.starcher@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: normalize lock ImportValues and fix digest test isolation
- Normalize lock.Dependencies ImportValues via RecursivelyStringifyMapKey
before json.Marshal, preventing failures when go-yaml v2 decodes nested
maps as map[interface{}]interface{}.
- Fix TestRewriteChartDependencies_RefreshesChartLockWithExtraFields to use
a shared root directory so both chart variants resolve file:// paths to
the same absolute location, isolating digest differences to field content.
- Add TestRewriteChartDependencies_GoYamlV2ImportValues exercising the
HELMFILE_GO_YAML_V3=false path with import-values containing nested maps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Shane Starcher <shane.starcher@gmail.com>
* fix: add exact digest verification test against Helm's HashReq
Add TestRewriteChartDependencies_DigestMatchesHelmHashReq which computes
the expected digest independently using the same algorithm as Helm's
resolver.HashReq and asserts the rewritten Chart.lock matches exactly.
This guards against producing a digest that is "different" yet still
rejected by `helm dependency build`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Shane Starcher <shane.starcher@gmail.com>
---------
Signed-off-by: Shane Starcher <shane.starcher@gmail.com>
Co-authored-by: Shane Starcher <shane.starcher@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
PR #1839 introduced template rendering for postRendererArgs, but PR #2510
reverted it while fixing a separate regression. This left helmDefaults-level
postRendererArgs containing template expressions (e.g. {{ .Release.Name }})
passed to helm as literal strings instead of being resolved per-release.
Add renderPostRendererArgs() that templates helmDefaults.postRendererArgs
at flag-generation time using the release's template data, reusing the
existing createReleaseTemplateData() helper. Release-level args are already
templated by ExecuteTemplateExpressions and CLI args are static, so only
the helmDefaults path needs rendering.
Fixes#2580
Signed-off-by: opencode <opencode@users.noreply.github.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
* feat(state): add mergeStrategy field to EnvironmentSpec
Introduces a per-environment mergeStrategy with valid values "override"
(default, current behavior) and "fallback". This commit only adds the
field, the constants, and a parse-time validator; the loader still
ignores the value, so behavior is unchanged.
Subsequent commits thread the value through the values loader and
implement the fallback semantics.
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
* refactor(state): thread mergeStrategy through values loader
Adds a mergeStrategy string parameter to LoadEnvironmentValues,
loadValuesEntries, and mapMerge so the value can flow from
EnvironmentSpec down to the merge call site. Behavior is unchanged in
this commit; mapMerge ignores the strategy and the next commit
implements the fallback semantics.
Top-level state.DefaultValues and the --state-values-file/-set loaders
are passed an empty strategy ("") since they have no per-environment
spec to consult and stay on the default override behavior.
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
* feat(state): implement fallback merge strategy
Adds a hand-rolled fallbackDeepMerge that, unlike mergo, preserves
keys present in the destination even when their value is the zero
value (false, 0, "", nil, empty list/map). mapMerge dispatches to it
when mergeStrategy == "fallback"; "override" and the empty default
keep using mergo with WithOverride so existing behaviour is unchanged.
Validation lives at the entry of LoadEnvironmentValues so a single
chokepoint guards the field. Invalid values produce an error naming
both the offending value and the valid options.
Tests cover: first-file-wins precedence, gap filling, deep nested
merge, three-file chains, explicit zero-value preservation (the case
naïve mergo gets wrong), explicit nil preservation, inline map
entries, override regression, default-equals-override equivalence,
and invalid-strategy errors.
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
* feat(state): expose prior-file values in fallback template context
Under mergeStrategy: fallback, .gotmpl values files can now reference
values from earlier files in the same `values:` list via .Values
(e.g. `service.domain: "service.{{ .Values.cluster.domain }}"`).
The accumulated result is layered under env.GetMergedValues so env
defaults, env values, and CLI overrides still win on overlap. Override
mode keeps the historical template context — unchanged — so this is
strictly opt-in via the mergeStrategy field.
Together with the precedence flip from the previous commit, this lets
users replace the brittle two-stage `merged-values.yaml.gotmpl`
workaround with native helmfile syntax.
Tests cover the headline cross-file template reference case and pin
the override-mode contract that prior-file values stay invisible.
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
* docs: document mergeStrategy and fallback semantics
Adds a new section to values-and-merging.md describing the override vs
fallback strategies, the explicit-zero-value preservation guarantee,
and the cross-file template reference behavior. Adds a brief pointer
to environments.md so users land on the new field from the
environment values discussion.
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
* refactor(state): reuse maputil.MergeMaps for fallback merge
Replaces the hand-rolled fallbackDeepMerge with a single call to
maputil.MergeMaps, swapping its arguments so the accumulated dest wins
over the new src file. Same first-file-wins semantic, fewer lines, and
the fallback path now inherits the same slice merge strategies the
rest of helmfile already uses.
The one observable behavior shift is for explicit nil values: under
fallback, nil in an earlier file no longer 'wins' over a non-nil value
in a later file — instead it falls through (matching MergeMaps' rule
that nil from the override side only fills missing keys). This is
internally consistent: nil-overwrites is an mergo.WithOverride quirk
that lives only in the override path. The renamed test
NilFallsThroughToFallback pins the new behavior with a comment
referencing the contrast with override mode (Issue1154).
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
---------
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
When a release `dependencies[].chart` is given as `<repoName>/<chart>`
and the matching `repositories:` entry has `oci: true`, helmfile now
rewrites it to `oci://<repoURL>/<chart>` before passing it to chartify.
Without this, chartify's lookup falls into its `helm repo list` branch,
which never finds OCI repos because helm 3+ does not register OCI
registries as named repos (they live in the `helm registry login`
state instead). The user-visible failure was:
failed reading adhoc dependencies: no helm list entry found for
repository "<name>". please `helm repo add` it!
Explicit `oci://` URLs already worked through chartify's OCI branch;
this change makes the `<repoName>/<chart>` form behave the same way.
Non-OCI repo prefixes, unknown prefixes, single-segment names, and
explicit `oci://` URLs all pass through unchanged. A debug log records
each rewrite at the call site for easier troubleshooting.
Fixes#1756.
Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
* fix: add trackFailOnError option to control kubedog exit code behavior
When kubedog release tracking fails (e.g. pod ImagePullBackOff), helmfile
exits with code 0 instead of a non-zero exit code. Add a trackFailOnError
configuration option (default: false) that when set to true, propagates
kubedog tracking failures to the exit code.
The option is available as:
- Per-release YAML: trackFailOnError: true
- CLI flag: --track-fail-on-error (sync and apply commands)
Extract trackReleaseIfEnabled helper to consolidate kubedog tracking logic
from two duplicated call sites into a single maintainable method.
Fixes#2507
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: add //go:build ignore to server.go to fix go test CI failure
The test/integration/test-cases/issue-2103/input/server.go is a
package main helper binary used by the issue-2103 integration test.
When go test -coverprofile runs on this package, it fails with
"go: no such tool covdata" in the CI environment.
Adding //go:build ignore excludes the file from go list ./... (and
therefore from PKGS in the Makefile), while still allowing the
integration test to build it explicitly via file path:
go build -o server ./path/to/server.go
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/8a7000af-72b7-48f8-8a82-24813b5df341
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
* fix: update TestGenerateID expected hashes after adding TrackFailOnError field
Adding TrackFailOnError *bool to ReleaseSpec changed the spew
serialization of the struct, which changed the FNV-32a hash values
produced by generateValuesID. Update temp_test.go with the new
expected hash strings.
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/caa86cd9-73d1-4894-b745-fd70c0811fd6
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* fix: use --post-renderer-args=VALUE format to prevent Helm flag parsing failure
When postRendererArgs contains values like short flags (e.g. -v), passing
--post-renderer-args and the value as separate arguments causes Helm to
interpret the value as its own flag. Using the --post-renderer-args=VALUE
format unambiguously binds the value to the flag.
Fixes#2563
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: update hasFlagWithValue doc/errors and add -v short-flag test cases
- Update hasFlagWithValue doc comment to describe both '--flag value' and
'--flag=value' forms
- Update t.Errorf messages in app_test.go to reflect both accepted formats
- Add 'post-renderer-args-short-flag-value' test case (-v) to both
TestHelmState_flagsForUpgrade and TestHelmState_flagsForTemplate to
verify --post-renderer-args=-v emission (core regression from #2563)
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/dd95f046-358b-4867-9069-9432c1b5318e
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
When multiple releases reference the same chart with the same name,
repository, and version, helmfile deps would write duplicate entries
to helmfile.lock. This adds deduplication of resolved dependencies
after sorting and before writing the lock file.
Fixes#2562
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: skip subhelmfiles when selectors conflict with CLI selectors (#2544)
When CLI selectors are provided (e.g. -l name=b), subhelmfiles whose
explicit selectors are provably incompatible are now skipped entirely,
avoiding unnecessary YAML loading and template rendering.
Two selector sets are incompatible when every pair has a positive label
conflict: same key with different values (e.g. name=b vs name=a).
Negative labels are not compared.
Fixes#2544
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address PR review comments - use CLI selectors, fix doc comment, add malformed selector test
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/1f1c33ce-e50d-4781-85b8-d606b5d4ca54
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
* fix: add debug logging, unit tests, docs, and fix integration test for subhelmfile selector skip
- Add debug log when skipping subhelmfile due to selector conflict
- Add TestSubhelmfileSelectorsConflict with 11 cases for direct unit coverage
- Document the selector-based subhelmfile skip optimization in docs/index.md
- Fix integration test: use 'app' label key instead of reserved 'name' key
(GetReleasesWithLabels overwrites labels["name"] with the release name)
Signed-off-by: yxxhero <aiopsclub@163.com>
* refactor: avoid map allocation in positiveLabelsCompatibleWith
Compare positive label slices directly instead of allocating a map per
comparison, as label counts are typically small (1-3 entries).
Addresses Copilot review comment on PR #2545.
Signed-off-by: yxxhero <aiopsclub@163.com>
* docs: clarify subhelmfile selector docs per Copilot review feedback
Reword the first two bullets to avoid the contradiction between
'CLI selectors are ignored' and the new skip optimization.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address Copilot review comments round 3
- Log parse errors from SelectorsAreCompatible at debug level instead of
silently discarding them
- Hoist regex compilation to package-level vars in ParseLabels to avoid
repeated compilation per selector
- Replace EXIT traps with explicit cleanup calls in integration test to
avoid interfering with the parent runner's trap
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* fix: eliminate race condition in rewriteChartDependencies by copying chart before modifying
Instead of modifying the original Chart.yaml in-place (which causes race
conditions when multiple releases reference the same local chart), copy the
chart to a temporary directory and rewrite the copy's dependencies. This
eliminates the need for per-chart mutex locks and prevents file corruption
when concurrent goroutines process releases sharing the same local chart.
Fixes#2502
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address PR review comments for rewriteChartDependencies
- Handle non-NotExist errors from st.fs.Stat to surface permission/IO failures
- Reword function doc to clarify temp copy is conditional on rewrite being needed
- Assert rewrittenPath vs tempDir based on expectModified in test table
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add integration test for issue #2502 race condition with shared local chart
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: separate environments and releases with --- in helmfile.yaml
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: correct file:// path and remove --skip-deps for dependency build
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: correct file:// dependency path (5 levels up to test/integration/)
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: remove output validation from race condition test
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: assert WriteFile/MkdirTemp/RemoveAll/CopyDir in DefaultFileSystem test
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: add strategicMergePatches to trigger chartify in race condition test
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: scope test values under raw subchart and align ConfigMap name with strategic merge patches
The race condition test values.yaml had templates at the top level instead
of scoped under the raw subchart key, causing helm template to produce no
output and chartify's ReplaceWithRendered to fail with an empty
helmx.1.rendered directory. Also align the ConfigMap name to match the
strategicMergePatches target.
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
* enabledns flags available on template command
Enable dns flag was not available in helmfile template command
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: helmDefaults.postRendererArgs not passed to helm commands (#2508)
The commit b5eb8793 (#1839) added template support for postRendererArgs
by copying HelmDefaults.PostRendererArgs to each release and then
niling out HelmDefaults.PostRendererArgs. However, the nil-out
prevented the fallback in appendPostRenderArgsFlags from ever being
reached, causing helmDefaults.postRendererArgs to be silently ignored
when no release-level postRendererArgs was set.
Remove the nil-out line so that HelmDefaults.PostRendererArgs remains
available as a fallback while still supporting template expressions
via the copy-to-release mechanism.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: use helm4-compatible postRenderer value in app tests
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/17a1a3c2-e104-49c5-a607-1e81a7b9de06
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
* fix: remove postRendererArgs copy loop so CLI flags can override helmDefaults
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/c85f0436-2346-402e-8ad6-e08a4fff7413
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
* test: add missing CLI>helmDefault and release>CLI postRendererArgs priority tests
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/37cf3613-a4e1-4eac-b6bc-002761256d31
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
* fix: clarify comment wording in app_test.go
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/37cf3613-a4e1-4eac-b6bc-002761256d31
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
* refactor: extract newPostRendererTestApp and hasFlagWithValue helpers in app_test.go
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/faf50bca-33b2-4eb4-8ef1-49f470dfa5b7
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* fix: environment values pollution causing boolean false overrides to be dropped (#2527)
PR #2367 introduced envCopy.Values = values in NewEnvironmentTemplateData,
where values = GetMergedValues() = Defaults + Values + CLIOverrides. This
caused .Environment.Values to include Defaults, so when multi-part helmfiles
re-assigned environment values via {{ toYaml .Environment.Values }}, Defaults
values (e.g. helmDefaults.atomic: true) were written into the environment
Values field. Later, GetMergedValues() applied Values over Defaults, causing
the stale atomic: true to win over the correct atomic: false override.
Fix: set .Environment.Values to Values + CLIOverrides only (excluding Defaults),
so re-assignment patterns don't pollute the Values layer with Defaults.
Signed-off-by: yxx <yxx@users.noreply.github.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: rename test to correctly reflect Values override Defaults precedence
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/1b251877-7050-404b-8cc7-abd6aa3ec36b
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
* test: flip regression test fixture to exercise false override (issue #2527)
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/c428fd46-b698-4e88-bff2-4c9ac72d2deb
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
---------
Signed-off-by: yxx <yxx@users.noreply.github.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* feat: Refactor TestRewriteChartDependencies
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
* fix: keep all chart dependencies key / values
In rewriteChartDependencies we were only parsing name / repository / version,
thus dropping keys like condition / import-values.
This at least fixes the use of condition.
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
---------
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
* fix: helmfile fetch fails for kustomization directories
Fixes#2503
When running `helmfile fetch` on a release that points to a local
kustomization directory (without Chart.yaml), the command failed with
"Chart.yaml is missing".
The issue was that the condition `helmfileCommand != "pull"` in
prepareChartForRelease skipped chartification for ALL cases during
fetch, including local kustomization directories that NEED chartify
to convert them to Helm charts.
Solution:
- Added `NeedsChartifyForLocalDir` field to the Chartify struct to
track when chartification is needed because the local directory
is not a Helm chart (no Chart.yaml)
- Modified the condition to skip chartification for "pull" ONLY when
it's not a local directory without Chart.yaml
This preserves the original fix (commit 1f134d93) for remote charts
with transformers while fixing local kustomization directories.
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add integration test for helmfile fetch with kustomization
Add test case for issue #2503 to verify helmfile fetch works correctly
with local kustomization directories (without Chart.yaml).
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: helmfile list now reflects version from helmfile.lock
The list command now resolves locked dependencies before returning
release information, ensuring the version field reflects the pinned
version from helmfile.lock when present.
Fixes#1953
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address PR review comments
- Remove redundant maps.Copy in list() - labels already merged by GetReleasesWithLabels()
- Fix default lockfile path to use basePath for multi-file mode
- Update test to expect basePath-joined lockfile path
- Add multi-file test for lockfile resolution in helmfile.d directory
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix more test
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix tests
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: propagate errors instead of panic in list()
When skipCharts=false, errors from list() now properly propagate instead
of causing a crash. Uses a closure variable to capture the error and
propagates it after withPreparedCharts completes.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix tests
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix tests
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix tests
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
* feat: add --force-conflicts flag support for Helm 4
Add support for Helm 4's --force-conflicts flag which forces server-side
apply changes against conflicts. This flag is mutually exclusive with
--force/--force-replace and only available in Helm 4.
Fixes#2429
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address review comments on force-conflicts feature
- Fix comment grammar: 'forces' instead of 'force'
- Improve error messages to indicate both sources (releases[] and helmDefaults)
- Add test case for helmDefaults.forceConflicts with Helm 3 (should error)
- Update TestGenerateID expected hashes after adding ForceConflicts field to structs
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: use --force-replace flag for Helm 4 instead of deprecated --force
Helm 4 deprecated the --force flag in favor of --force-replace.
This fix detects the Helm version and uses the appropriate flag:
- Helm 4: --force-replace
- Helm 3: --force
Also fixed a nil pointer panic in appendHideNotesFlags when called
with nil SyncOpts.
Fixes#2476
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix(ci): pin semver to v2.12.0 for Go 1.25 compatibility
semver@latest requires Go 1.26.1 but the project uses Go 1.25.4.
Pinning to v2.12.0 which is compatible with Go 1.25.
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add test cases for force flag from defaults with nil release
Add test cases to cover the scenario where release.Force is nil and
HelmDefaults.Force enables force for both Helm 3 and Helm 4.
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add nil ops test and rename misleading test names
- Add test case for appendHideNotesFlags with ops=nil to prevent
regression
- Rename force-from-default-nil-release-* to
force-from-default-nil-force-* for clarity (release.Force is nil,
not the release itself)
Signed-off-by: yxxhero <aiopsclub@163.com>
* refactor: add explicit parentheses for force condition
Add explicit parentheses around the two disjuncts in the force
condition to make the intended grouping unambiguous and easier
to read.
Signed-off-by: yxxhero <aiopsclub@163.com>
* refactor: check ops nil before Helm version in appendHideNotesFlags
- Swap the order to check ops == nil first to avoid unnecessary
IsVersionAtLeast call
- Restore the "see Helm release" comment for consistency with other
flag helpers
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>
Add support for trackMode: helm-legacy to use Helm v4's --wait=legacy flag,
which maintains compatibility with Helm v3's wait behavior during migration.
Helm v4 changed the default --wait behavior from polling to a watcher-based
approach. This can cause issues with charts that have broken livenessProbe
configurations without startupProbe. The --wait=legacy flag preserves the
Helm v3 polling behavior for smoother migration.
Changes:
- Add TrackModeHelmLegacy constant in pkg/kubedog/options.go
- Use kubedog.TrackMode constants instead of raw strings in helmx.go
- Enhance appendWaitFlags to use --wait=legacy for Helm v4 when trackMode
is helm-legacy
- Add nil check for logger before logging warning
- Add version check with warning when helm-legacy is used with Helm v3
- Update validation in pkg/config to accept helm-legacy track mode
- Update command-line flags in cmd/apply.go and cmd/sync.go
- Add comprehensive documentation in docs/advanced-features.md
- Add thorough test coverage including warning message verification
Behavior:
- Helm v4 + helm-legacy: Uses --wait=legacy
- Helm v3 + helm-legacy: Falls back to --wait with warning
- Helm v4 + helm: Uses --wait (watcher mode)
- Any + kubedog: Skips --wait flag
Fixes#2464
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: Copilot <copilot@github.com>
When using jsonPatches or kustomize patches with helmfile, chartify runs
"helm template" internally to render the chart before applying patches.
The lookup() helm function requires cluster access (--dry-run=server).
Previously, --kubeconfig was passed to helm diff and helm upgrade commands,
but not to chartify's internal helm template call. This caused failures
when users specified --kubeconfig flag with a non-default kubeconfig location.
This fix ensures --kubeconfig is passed to chartify's TemplateArgs for
cluster-requiring commands (sync, apply, diff, etc.), alongside the existing
--kube-context and --dry-run=server flags.
Fixes#2444
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: local chart with external dependencies error when repos configured
When helm repo update was run, the code unconditionally set skipRefresh=true
for all builds, causing helm dep build --skip-refresh to fail for local charts
with external dependencies not listed in helmfile.yaml.
Now only non-local charts (precomputed skipRefresh=true) get --skip-refresh,
while local charts preserve their skipRefresh=false to allow refreshing repos
for external dependencies.
Fixes#2431
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: update snapshot tests for local chart refresh behavior
Local charts now run helm repo update during helm dep build to support
external dependencies not listed in helmfile.yaml (fixes#2431).
Signed-off-by: yxxhero <aiopsclub@163.com>
* refactor: remove redundant skipRefresh assignment
The condition 'if didUpdateRepo && r.skipRefresh { r.skipRefresh = true }'
was a no-op since setting true to true has no effect. The precomputed
skipRefresh value from prepareChartForRelease is already correct, so we
simply preserve it without modification.
Signed-off-by: yxxhero <aiopsclub@163.com>
* refactor: only call UpdateRepo when at least one build uses --skip-refresh
Avoid redundant helm repo update when all builds have skipRefresh=false,
as each helm dep build will refresh repos itself in that case.
Co-authored-by: Copilot <copilot@github.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: update release_template_inheritance snapshot for skipRefresh optimization
UpdateRepo is now only called when at least one build uses --skip-refresh,
so local charts without skipRefresh no longer trigger the global repo update.
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add regression test for issue #2431
Add TestIssue2431_LocalChartWithExternalDependency to verify that local
charts with external dependencies on repos NOT in helmfile.yaml work
correctly. The test ensures:
- UpdateRepo is NOT called when all builds have skipRefresh=false
- helm dep build does NOT receive --skip-refresh flag
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add integration test for issue #2431
Add test case to verify that local charts with repos configured in
helmfile.yaml work correctly. The test ensures that helmfile template
does not fail with 'no cached repository' or 'no repository definition'
errors when:
- helmfile.yaml has non-OCI repos configured
- Local chart is used (which may have external dependencies not in helmfile.yaml)
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: update issue #2431 integration test to match issue scenario
Add external dependency (karma chart from wiremind repo) to local chart's
Chart.yaml, matching the exact scenario described in issue #2431 where:
- helmfile.yaml has repos configured (vector)
- Local chart depends on a repo NOT in helmfile.yaml (wiremind)
Signed-off-by: yxxhero <aiopsclub@163.com>
* revert: remove unit tests and restore e2e snapshot outputs
Remove pkg/state/run_helm_dep_builds_skip_refresh_test.go and restore
chart_need snapshot outputs to original state. The fix is verified by
the integration test for issue #2431.
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: remove snapshot outputs to regenerate them
Remove chart_need snapshot outputs so they can be regenerated by tests.
Signed-off-by: yxxhero <aiopsclub@163.com>
* revert: restore release_template_inheritance snapshot output
Signed-off-by: yxxhero <aiopsclub@163.com>
* restore: add back unit tests for skipRefresh behavior
Signed-off-by: yxxhero <aiopsclub@163.com>
* restore: add back chart_need snapshot outputs
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: update snapshot outputs for skipRefresh optimization
- Remove TestIssue2431_LocalChartWithExternalDependency unit test
- Update chart_need outputs: local chart runs helm dep build with repo refresh
- Update release_template_inheritance: no deps so no repo refresh output
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: update test comments and names per review feedback
- Update TestRunHelmDepBuilds_MultipleBuilds comment to remove reference
to removed didUpdateRepo variable
- Rename test case to accurately describe condition being tested
(build with skipRefresh=true instead of misleading 'non-local chart')
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: Copilot <copilot@github.com>
When no repositories are defined in helmfile.yaml, local charts with
external dependencies need to refresh the repo cache. Previously, we
always passed --skip-refresh to helm dep build, which broke this case.
Now --skip-refresh is only passed when we actually ran helm repo update,
meaning repos are configured AND no skip refresh flags are set. This
preserves the precomputed skipRefresh value from prepareChartForRelease
which accounts for CLI flags, helmDefaults.skipRefresh, and release.skipRefresh.
Fixes#2417
Signed-off-by: yxxhero <aiopsclub@163.com>
When using only OCI repositories, helmfile would attempt to run
'helm repo update' which fails with 'no repositories found' error.
OCI repositories don't need 'helm repo update' as they use
'helm registry login' instead.
This fix adds a HasNonOCIRepositories() helper function and uses it
to determine whether to run 'helm repo update'.
Fixes#2418
Signed-off-by: yxxhero <aiopsclub@163.com>
fix: helmDefaults.skipRefresh ignored in runHelmDepBuilds (#2269)
`runHelmDepBuilds()` only checked the CLI flag (`opts.SkipRefresh`) when
deciding whether to run `helm repo update` before building dependencies.
This meant that setting `helmDefaults.skipRefresh: true` in helmfile.yaml
had no effect on the repo update call inside dep builds.
Add `!st.HelmDefaults.SkipRefresh` to the guard condition so that
`helmDefaults.skipRefresh: true` is respected alongside the CLI flag.
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* fix: eliminate os.Chdir in sequential helmfiles to fix relative path resolution
The sequential code path used within() → os.Chdir() to change the
process-wide working directory when processing helmfile.d files.
This broke relative environment variable paths (e.g. KUBECONFIG=kubeconfig.yaml)
because they resolved from the wrong directory after chdir.
Replace the chdir-based approach with the same baseDir parameter pattern
used by the parallel code path, passing explicit directory context through
loadDesiredStateFromYamlWithBaseDir() instead of mutating global process state.
Closes#2409
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* fix: restore within() for single-file sequential to preserve chart path format
The previous approach used baseDir for all sequential processing, which
changed chart path format in output (e.g. from "../../../../charts/raw"
to "test/integration/charts/raw"). This broke integration tests that
compare chart paths in expected output.
Now the sequential branch uses two strategies:
- Single file: use os.Chdir via within() to preserve backward-compatible
relative chart paths in output
- Multiple files with --sequential-helmfiles: use baseDir parameter to
avoid os.Chdir, fixing relative env var paths like KUBECONFIG (#2409)
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* fix: revert e2e snapshot outputs to match within() behavior
The previous commit restored within() for single-file sequential
processing, which produces relative chart paths (e.g. ../../charts/raw)
and filename-only FilePath. Revert the e2e snapshot expected outputs
to match main branch since single-file behavior is now identical.
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* fix: restructure integration test for multi-file sequential processing
- Point -f at helmfile.d/ directly (not parent dir) so findDesiredStateFiles
discovers the yaml files
- Add second helmfile to trigger baseDir path (len > 1)
- Inline environment config to avoid base file relative path issues
- Verify both releases appear in output instead of comparing with parallel
(which may differ in ordering)
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* fix: reduce cognitive complexity and improve accuracy of sequential helmfiles
Replace inline visitSubHelmfiles closure with calls to the existing
processNestedHelmfiles() method, matching the parallel path. This
eliminates duplicated nested logic and reduces gocognit complexity
below the CI threshold of 110. Also fixes help text and docs to
accurately describe that single-file processing still uses within(),
and adds kubeContext verification to the integration test.
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* test: validate kubeContext resolution in sequential helmfiles integration test
Restructure the integration test to replicate the exact user scenario
from issue #2409:
- Multiple files in helmfile.d/ using bases: with relative paths
(../bases/) for environments and defaults
- Environment values set kubeContext via .Environment.Values
- helmDefaults.kubeContext rendered from gotmpl
- Local chart references (../../../../charts/raw) from helmfile.d/
- Run diff against the minikube cluster to exercise kubeContext
resolution, which would fail with "context does not exist" if
os.Chdir() broke relative path resolution
- Also verify template output for both releases and relative values
file (values/common.yaml) resolution
Fix normalizeChart() in util.go to be idempotent — skip re-prefixing
when the chart path already starts with basePath. This prevents
double-prefixing of local chart paths (e.g. helmfile.d/test/.../raw)
when normalizeChart is called multiple times (once during chart
preparation and again during diff/sync).
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
---------
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* fix: helmBinary setting ignored in multi-document YAML files
The helmBinary setting in helmfile.yaml was being ignored when using
multi-document YAML files (files with --- separators).
Root Cause:
When processing multi-document YAML files, the load() function splits
the file into parts and processes each part separately. Each part was
calling applyDefaultsAndOverrides() which would set an empty helmBinary
to the default 'helm'. When merging parts, the default value from a
later part would override the correct value from an earlier part.
Fix:
- Added a new applyDefaults parameter to ParseAndLoad() to control when
defaults are applied
- Modified rawLoad() to pass applyDefaults=false when processing
individual parts
- Added a call to ApplyDefaultsAndOverrides() after all parts are merged
to apply defaults once on the final merged state
- Exported ApplyDefaultsAndOverrides() method for use by the app package
Fixes: #2319
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: update comment per PR review
Change 're-apply' to 'apply' since defaults are never applied during
part processing (applyDefaults=false is passed), so this is the first
and only time defaults are applied to the merged state.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: clarify applyDefaults logic in test LoadFile callbacks
Add explicit applyDefaults variable with comment explaining why it
equals evaluateBases: base files shouldn't apply defaults, only the
main file should after all parts/bases are merged.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address PR review comments
- Remove applyDefaults parameter from rawLoad() since it's always false
- Add regression test for multi-document YAML with helmBinary (issue #2319)
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add integration test for helmBinary in multi-document YAML
Add TestHelmBinaryPreservedInMultiDocumentYAML that exercises the full
loadDesiredStateFromYaml path to ensure helmBinary from the first
document is preserved when merging multi-document YAML files.
This is a regression test at the load() orchestration level for issue #2319.
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
Adds a new `helmfile unittest` command that integrates the helm-unittest
plugin, allowing users to define unit test paths per release and run them
via helmfile.
Closes#2376
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* feat: support .Environment.* in --output-dir-template
This commit adds support for accessing environment values in the --output-dir-template flag.
Previously, users could only access .OutputDir, .State.*, and .Release.* in the template.
Now .Environment.* is also available, allowing users to use environment values in the
output directory path.
Example usage:
helmfile template -e test-1 --output-dir-template='{{ .OutputDir }}/{{ .Environment.cluster.name }}/{{ .Environment.Name }}/{{ .Release.Name }}'
This produces output like: ./gitops/my-test-cluster/test-1/release-name/
Changes:
- Add Environment field to GenerateOutputDir template data
- Add Environment field to generateChartPath template data (now a method on HelmState)
- Update help text for --output-dir-template flag in template and fetch commands
- Add test cases for Environment in template
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address PR review comments for --output-dir-template
- Clarify .Environment.Name, .Environment.KubeContext, .Environment.Values.* in help text
- Update generateChartPath comment to reflect broader usage (fetch, pull, OCI)
- Add tests for GenerateOutputDir with Environment fields
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address additional PR review comments
- Move HelmState setup outside test loop to reduce duplication
- Document Environment field (.Name, .KubeContext, .Values) in template data structs
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: skip cache refresh for shared cache paths to prevent race conditions
When multiple helmfile processes run in parallel (e.g., as ArgoCD plugin),
they share the same OCI chart cache in ~/.cache/helmfile. One process could
delete and re-download (refresh) a cached chart while another process was
still using it, causing "path not found" errors.
This fix:
- Adds isSharedCachePath() helper to detect shared cache paths
- Skips chart deletion/refresh for paths in the shared cache directory
- Users can force refresh by running `helmfile cache cleanup` first
Fixes#2387
Signed-off-by: yxxhero <aiopsclub@163.com>
* docs: document OCI chart caching behavior and multi-process safety
Add documentation for:
- OCI chart cache location and behavior
- How to force cache refresh with `helmfile cache cleanup`
- Multi-process safety when using shared cache
- Cache management commands (info, cleanup)
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address review comments for shared cache handling
- Return error instead of chartActionDownload for corrupted shared cache
- Change refresh skip log from Debugf to Infof for user visibility
- Add t.Helper() to createTestLogger test helper
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: handle symlinks and add debug logging in isSharedCachePath
- Use filepath.EvalSymlinks to resolve symlinks before path comparison
- Add debug logging when filepath.Abs fails
- Add test case for symlink to shared cache directory
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: address copilot review comments
- Include underlying error in corrupted cache error message
- Add cleanup for test directories created in shared cache
- Clarify --skip-refresh flag documentation
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: handle edge case when chartPath equals sharedCacheDir
- isSharedCachePath now returns true for exact match with cache dir
- Add test case for exact match with shared cache directory
Signed-off-by: yxxhero <aiopsclub@163.com>
* test: add integration test for acquireChartLock shared cache behavior
Add TestAcquireChartLockSharedCacheSkipRefresh to verify that
acquireChartLock returns chartActionUseCached instead of
chartActionRefresh when the chart exists in the shared cache,
even when refresh is requested. This tests the core fix for
the race condition issue #2387.
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
fix: support OCI chart digest syntax in chart URLs and version fields
Helm supports pinning OCI chart images by digest (@sha256:...), version
tag (:version), or both (:version@sha256:digest) since helm/helm#12690.
Helmfile failed to parse these formats, incorrectly constructing helm
commands and losing version/digest information embedded in chart URLs.
Root causes:
- resolveOciChart() used last ":" to find version tag, but sha256:abc
contains ":", so digest URLs were split incorrectly
- getOCIQualifiedChartName() included :version and @digest in chartName
with no parsing of either source
- appendChartVersionFlags() passed release.Version verbatim to --version
flag, including any digest suffix
- ChartPull() discarded the tag from resolveOciChart but did not
preserve digest in the URL
This commit adds parseOCIChartRef() and parseVersionDigest() utilities,
then updates the OCI chart handling pipeline so that:
- Digests are preserved in the chart URL passed to helm pull
- Version tags are extracted cleanly for the --version flag
- Both chart URL and version field are parsed for version/digest info
Fixes#2097
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
* feat: Ensure repo update is only run once
Perform a single Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "glm-bitnami" chart repository
...Unable to get an update from the "fluent" chart repository (https://fluent.github.io/helm-charts):
Get "https://fluent.github.io/helm-charts/index.yaml": read tcp 192.168.0.104:51893->185.199.108.153:443: read: connection reset by peer
...Unable to get an update from the "grafana" chart repository (https://grafana.github.io/helm-charts):
Get "https://grafana.github.io/helm-charts/index.yaml": read tcp 192.168.0.104:51897->185.199.109.153:443: read: connection reset by peer
...Unable to get an update from the "ingress-nginx" chart repository (https://kubernetes.github.io/ingress-nginx):
Get "https://kubernetes.github.io/ingress-nginx/index.yaml": read tcp 192.168.0.104:51894->185.199.110.153:443: read: connection reset by peer
...Unable to get an update from the "chartmuseum" chart repository (https://chartmuseum.github.io/charts):
Get "https://chartmuseum.github.io/charts/index.yaml": read tcp 192.168.0.104:51896->185.199.110.153:443: read: connection reset by peer
...Successfully got an update from the "glm-chartmuseum" chart repository
...Successfully got an update from the "apollo" chart repository
...Successfully got an update from the "kyverno" chart repository
...Unable to get an update from the "mysql-operator" chart repository (https://mysql.github.io/mysql-operator/):
Get "https://mysql.github.io/mysql-operator/index.yaml": read tcp 192.168.0.104:51903->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "metallb" chart repository (https://metallb.github.io/metallb):
Get "https://metallb.github.io/metallb/index.yaml": read tcp 192.168.0.104:51904->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "dragonfly" chart repository (https://dragonflyoss.github.io/helm-charts/):
Get "https://dragonflyoss.github.io/helm-charts/index.yaml": read tcp 192.168.0.104:51905->185.199.108.153:443: read: connection reset by peer
...Unable to get an update from the "openfga" chart repository (https://openfga.github.io/helm-charts):
Get "https://openfga.github.io/helm-charts/index.yaml": read tcp 192.168.0.104:51907->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "cnpg" chart repository (https://cloudnative-pg.github.io/charts):
Get "https://cloudnative-pg.github.io/charts/index.yaml": read tcp 192.168.0.104:51910->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "metrics-server" chart repository (https://kubernetes-sigs.github.io/metrics-server/):
Get "https://kubernetes-sigs.github.io/metrics-server/index.yaml": read tcp 192.168.0.104:51913->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "ot-helm" chart repository (https://ot-container-kit.github.io/helm-charts/):
Get "https://ot-container-kit.github.io/helm-charts/index.yaml": read tcp 192.168.0.104:51914->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "coredns" chart repository (https://coredns.github.io/helm):
Get "https://coredns.github.io/helm/index.yaml": read tcp 192.168.0.104:51917->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "redis-operator" chart repository (https://ot-container-kit.github.io/helm-charts/):
Get "https://ot-container-kit.github.io/helm-charts/index.yaml": read tcp 192.168.0.104:51912->185.199.111.153:443: read: connection reset by peer
...Unable to get an update from the "andrcuns" chart repository (https://andrcuns.github.io/charts):
Get "https://andrcuns.github.io/charts/index.yaml": read tcp 192.168.0.104:51915->185.199.111.153:443: read: connection reset by peer
...Successfully got an update from the "gitlab-jh" chart repository
...Successfully got an update from the "hashicorp" chart repository
...Successfully got an update from the "incubator" chart repository
...Successfully got an update from the "jenkins" chart repository
...Successfully got an update from the "nvidia" chart repository
...Successfully got an update from the "elastic" chart repository
...Successfully got an update from the "projectcalico" chart repository
...Unable to get an update from the "juicefs" chart repository (https://juicedata.github.io/charts/):
Get "https://juicedata.github.io/charts/index.yaml": read tcp 192.168.0.104:51919->185.199.111.153:443: read: connection reset by peer
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈ before running any
commands, allowing us to safely pass --skip-refresh to avoid redundant
repo updates for each chart with external dependencies.
This reduces the number of repository refresh operations from O(n) to O(1)
where n is the number of charts with remote dependencies.
Co-authored-by: Javex <github@javex.eu>
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: ensure repo update only runs when repositories are configured
This fixes CI issues where tests fail with 'no repositories found' error.
The PR #2378 adds a single helm.UpdateRepo() call before running helm dep
build commands. However, when no repositories are configured, this call
fails. The fix adds a check for len(st.Repositories) > 0 before calling
UpdateRepo().
Additionally, updated snapshot files to reflect the new output ordering
where repo update happens before building dependencies.
Signed-off-by: yxxhero <aiopsclub@163.com>
* feat: Update test snapshots for single repo update
The code changes in PR #2378 ensure that helm repo update is only run once
before building dependencies. This requires updating test snapshots to include
the 'Updating repo' output that now appears before 'Building dependency' messages.
Updated snapshots:
- chart_need/output.yaml
- chart_need_enable_live_output/output.yaml
- release_template_inheritance/output.yaml
- environments_releases_without_same_yaml_part/output.yaml
- environment_missing_in_subhelmfile/output.yaml
- pr_560/output.yaml
- environments_values_gotmpl_with_environment_name/output.yaml
- postrenderer/output.yaml (fixed YAML structure)
- oci_need/output.yaml
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: Correctly update test snapshots based on repository configuration
Only update snapshots for tests that have repositories defined:
- chart_need/output.yaml (has repositories - shows 'Updating repo')
- chart_need_enable_live_output/output.yaml (has repositories - shows 'Updating repo')
- release_template_inheritance/output.yaml (has repositories - shows 'Updating repo')
Tests without repositories should NOT show 'Updating repo':
- environments_releases_without_same_yaml_part/output.yaml
- environments_values_gotmpl_with_environment_name/output.yaml
- pr_560/output.yaml
- environment_missing_in_subhelmfile/output.yaml
- postrenderer/output.yaml (uses OCI dependencies)
- oci_need/output.yaml (uses OCI dependencies)
This matches the conditional logic in the code that only runs
helm.UpdateRepo() when len(st.Repositories) > 0.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: correct snapshot test expectations for repo update optimization
- Re-add trailing newlines to environment_missing_in_subhelmfile output
- Restore correct chart paths (/... instead of ../../...)
- Restore postrenderer output with cm2 ConfigMap and correct field order
- Fixes CI test failures introduced by incorrect snapshot updates
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: update integration test expected lint output for repo update
Include 'Updating repo' messages in expected lint output files
to match the new behavior where helm repo update is run once
before building dependencies.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: remove extra blank line from lint output files
Integration test output files had an extra blank line that was
not present in the expected output, causing test failures.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: update lint output for single repo update
With the repo update optimization, lint runs only once
with 'Updating repo' messages instead of running twice.
Update expected output to match new single-run behavior.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: filter out repo update messages in lint test
Update test runner to filter out repo update messages that are
now generated by the single helm.UpdateRepo() call, keeping
the expected lint output consistent with the original behavior.
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: filter repo update messages from diff test
Filter out repo update messages in diff test output to
match new behavior where helm.UpdateRepo() is called once.
Signed-off-by: yxxhero <aiopsclub@163.com>
* Fix missing closing parenthesis in grep command
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix: prevent --args flags from being passed to helm repo commands
When helmfile template --args is used, the extra flags were being
passed to helm repo update and helm repo add commands, which don't
support all flags that helm template/install support. This caused
failures when flags like --dry-run were passed via --args.
The fix saves the extra flags before executing helm repo commands,
clears them, and restores them afterwards to ensure repo commands
run without unsupported flags.
Fixes CI issue in PR #2378 where test issue-1749 fails
with "Error: unknown flag: --dry-run" during helm repo update.
Signed-off-by: yxxhero <aiopsclub@163.com>
---------
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: Javex <github@javex.eu>