Commit Graph
43 Commits
Author SHA1 Message Date
c36dbfd417 fix: resolve OCI version constraints before deriving the shared chart cache path (#2768)
* fix: resolve OCI version constraints before deriving the shared chart cache path

When an OCI release uses a semver constraint (e.g. `~1`, `^2.0.0`, `*`),
`getOCIChartPath` currently derives the on-disk cache directory from the
raw constraint string via `safeVersionPath`, which substitutes constraint
characters (`~`, `^`, `>`, `<`, `!`, `|`, `=`, ` `, `,`, `*`) with `_`.
So `version: ~1` becomes `.../mychart/_1/` on disk. `acquireChartLock`
then refuses to refresh anything under the shared cache dir to avoid
race conditions between concurrent processes, so once the constraint is
first resolved and written to `_1/`, every subsequent render on that
machine (or that container replica) returns the pinned tarball
regardless of newer matching tags being published.

In multi-pod deployments like ArgoCD's argocd-repo-server this shows up
as intermittent stale renders: different pods populate their caches at
different moments and serve different snapshots of the same `~1`
release forever.

Fix: for OCI releases whose `version` looks like a constraint, run
`helm show chart <ref> --version <constraint> [flags]` and use the
returned metadata.Version as the effective version for all downstream
cache-key and path derivation. Helm already resolves the constraint
against the registry and returns the concrete matching Chart.yaml.
Callers get a content-addressable cache path (`.../mychart/1.0.1/`)
that naturally invalidates when the constraint resolves to a new
version. Exact-version releases and non-OCI releases skip the extra
call.

Adds an opt-out `resolveOCIVersions` field on `helmDefaults` and
`ReleaseSpec` (both default true). If the resolution call fails
transiently, the resolver logs a warning and falls back to the
pre-fix behavior so a network hiccup doesn't break rendering.

Adds `ShowChartWithFlags` to helmexec.Interface so the existing
`ShowChart` API stays backwards compatible.

Resolves #2766

Signed-off-by: Samuel Archambault <samuel.archambault@getmaintainx.com>

* refactor: move ShowChartWithFlags to a ChartInspector capability interface

Address Copilot review feedback on PR #2768: adding a method to the
exported helmexec.Interface is a source-breaking change for every
third-party implementation and mock of that interface, even though
ShowChart itself stayed backward-compatible.

Move ShowChartWithFlags off Interface and onto a new capability
interface, helmexec.ChartInspector, following the same pattern used
by the existing DependencyUpdater capability interface. The concrete
execer and the exectest.Helm test stub still satisfy it (they
already have the method); the OCI resolver in state.HelmState now
type-asserts and falls back to the pre-fix caching behavior when the
capability is absent, so downstream callers with their own
helmexec.Interface implementations keep compiling untouched.

Adds TestResolveOCIConstraintVersion_ChartInspectorFallback that
exercises the type-assertion path with a helm value that satisfies
Interface but deliberately does not satisfy ChartInspector.

Reverts ShowChartWithFlags additions from testutil.noCallHelmExec
and app_test.mockHelmExec since Interface no longer requires them.

Signed-off-by: Samuel Archambault <samuel.archambault@getmaintainx.com>

* fix: detect wildcard-segment semver constraints (1.x, 1.X) as constraints

Address Copilot review feedback on PR #2768: the previous
isVersionConstraint implementation scanned the input for operator
characters (~, ^, >, <, !, |, =, space, comma, *). Masterminds/semver
also accepts wildcard-segment constraints like "1.x", "1.X", "1.x.x",
and "1.2.X" that contain no operator characters. Those would slip past
the classifier, bypass OCI constraint resolution, and remain cached
forever under the raw ".../mychart/1.x/" path — the same stale-cache
bug the PR is meant to fix.

Replace the character scan with a semver-parser-based check: a value
is a constraint iff Masterminds/semver rejects it as a NewVersion but
accepts it as a NewConstraint. This correctly:

  - Recognizes wildcard forms (1.x, 1.X, 1.x.x, 1.2.x, v1.x).
  - Preserves exact versions where "x" appears in prerelease metadata
    ("1.0.0-alpha.x") or build metadata ("1.0.0+x", "1.0.0+build.x.1")
    without misclassifying them, which a naive "add x to the scanned
    charset" fix would have gotten wrong.
  - Continues to classify values that are neither a version nor a
    constraint (empty string, "latest", junk) as non-constraints; helm
    handles those elsewhere.

Removes the now-unused versionConstraintChars string constant.

Expands TestIsVersionConstraint with 8 wildcard cases and 3 prerelease
/build metadata cases containing "x", plus 2 non-parseable inputs.
Adds a "wildcard segment constraint resolves to concrete version"
subtest to TestResolveOCIConstraintVersion so the end-to-end pipeline
is exercised for a version string that has no operator characters.

Signed-off-by: Samuel Archambault <samuel.archambault@getmaintainx.com>

* test: add getOCIChart integration test proving cache-path/pull-flag wiring

Address Copilot review feedback on PR #2768. The existing unit test
exercised resolveOCIConstraintVersion in isolation but did not prove
that its output was propagated into the downstream cache key, cache
path, and `helm chart pull --version` flag. Add a targeted
integration test that:

  1. Calls getOCIChart with a constraint release (`~1`) and a helm
     mock whose ShowChartWithFlags returns Chart.yaml version 1.0.1.
  2. Asserts helm chart pull receives `--version 1.0.1`, not `~1`.
  3. Asserts the destination path passed to helm chart pull contains
     the resolved-version segment (`/1.0.1/`) and does NOT contain
     the raw-constraint segment (`/_1/`).
  4. Reads back the on-disk Chart.yaml under the cache path to
     confirm resolved version, path, and flag agree end to end.

Add a second test that runs the same release twice with different
resolver outputs (1.0.1, then 1.0.2 — simulating a newly published
matching tag) and asserts the two resolutions land in distinct cache
directories. This is the promise of the fix: once the raw constraint
is out of the path, a new matching tag stops silently reusing the
previously-resolved cache entry.

The integration test flushed out a real correctness gap in the
initial fix: getOCIChart resolved release.Version and chartVersion
but did NOT recompute the qualified OCI ref that
getOCIQualifiedChartName built pre-resolution. Helm was therefore
receiving `oci://<repo>/<chart>:<constraint>` alongside a
`--version <resolved>` flag — at best redundant, at worst rejected
by future Helm versions. Fixed by re-invoking
getOCIQualifiedChartName on the mutated release copy so the
embedded tag also carries the resolved value.

Isolates the shared helmfile cache via `t.Setenv(HELMFILE_CACHE_HOME,
t.TempDir())` so the OutputDirTemplate == "" code path (which writes
into remote.CacheDir) does not touch the user's real
`~/.cache/helmfile` during test runs.

Signed-off-by: Samuel Archambault <samuel.archambault@getmaintainx.com>

* refactor: flatten OCI constraint-resolution wiring in getOCIChart

Address review feedback on PR #2768:

- Extract the inline resolve/requalify block from getOCIChart into
  applyOCIConstraintResolution, keeping getOCIChart flat (guard-clause
  style) and making the resolution wiring independently testable. The
  helper returns the (possibly updated) release, qualified chart name,
  and chart version; every failure mode returns its inputs unchanged.

- On a re-qualify failure after a successful resolution, fall back to
  the pre-fix behavior entirely (raw constraint in cache key, ref, AND
  --version flag) instead of the previous half-resolved mix (resolved
  version in the cache key, raw constraint in the path and flag), which
  could desynchronize the in-process cache key from the on-disk path.

- Build the 'helm show chart' ref by reusing parseOCIChartRef instead of
  re-implementing its last-slash/last-colon tag-splitting inline. Same
  behavior for all realistic refs (registry ports preserved), and it
  also handles the digest suffix should one ever reach this point.

- Drop --devel from the resolver flags: helm documents --devel as
  ignored whenever --version is set, and --version is always passed on
  this path.

No behavior change intended beyond the requalify-failure fallback
(which cannot realistically trigger) and the removal of the inert
--devel flag.

Signed-off-by: yxxhero <aiopsclub@163.com>

* fix: classify partial semver versions (1, 1.2) as OCI constraints

Address review feedback on PR #2768: Masterminds' lenient parser accepts
partial versions like "1" or "1.2" as versions, so the previous
classifier (NewVersion fails && NewConstraint succeeds) treated them as
exact pins. But helm's OCI resolution — registry.GetTagMatchingVersionOrConstraint
— honors a version string as an exact pin ONLY when a registry tag
literally equals it; otherwise it parses the string as a constraint, and
"1"/"1.2" float across 1.x.y/1.2.y tags. Caching those under their raw
spelling reproduces the stale-cache bug of issue #2766, just with a
narrower trigger.

Replace the NewVersion probe with isFullSemver, which additionally
requires the whole major.minor.patch triple to be spelled out
(optional v prefix, prerelease, and build metadata all still count as
exact when the core is fully qualified). When a registry does carry a
literal tag equal to the version string, the resolver's
metadata.Version == chartVersion path reports no change, so literal-tag
pins keep today's behavior.

TestIsVersionConstraint: "1"/"1.0" flip to constraints, joined by new
v1.2/0/v1 cases and a 1.2.3 exact case. TestResolveOCIConstraintVersion
gains a "partial version resolves" subtest.

Docs updated to describe the parser-based classification instead of
"constraint characters".

Signed-off-by: yxxhero <aiopsclub@163.com>

* fix: skip OCI constraint resolution under skipRefresh

Address review feedback on PR #2768: the resolver ran even under
--skip-refresh, so offline and cache-only workflows gained a
'helm show chart' registry attempt per constraint-versioned OCI release.
It degraded gracefully (warn + fallback), but added registry-timeout
latency and warning noise per release.

skipOCIConstraintResolution now suppresses resolution when any of the
skipRefresh levels is set — CLI --skip-refresh (forced), per-release
skipRefresh, or helmDefaults.skipRefresh — with the same precedence the
other skipRefresh consumers in prepareChartForRelease use. Skipped runs
fall back to the constraint-keyed cache path, i.e. they reuse whatever a
previous non-skipped run resolved, which is what 'skip checking for
updates to cached charts' means for constraint versions.

The existing issue #2766 integration tests flip their opts to
SkipRefresh: false since they assert resolution happens. New coverage:
TestSkipOCIConstraintResolution (tri-state precedence table) and
TestGetOCIChart_SkipRefreshSkipsConstraintResolution (no inspector call,
raw constraint in --version and cache path).

Signed-off-by: yxxhero <aiopsclub@163.com>

* perf: memoize OCI constraint resolution per chart+constraint

Address review feedback on PR #2768: resolution ran before the
in-process chart-cache fast path and was not memoized, so every
constraint-versioned OCI release paid its own 'helm show chart' registry
round-trip on every render — including N releases sharing the same
chart+constraint, whose parallel workers could even resolve to different
versions if the registry changed between their lookups.

Memoize successful resolutions in resolvedOCIConstraints keyed by
(chart ref, constraint), mirroring the downloadedCharts pattern:

- Releases sharing a chart+constraint cost one round-trip per process
  and consistently use one resolved version per run.
- Only successful resolutions are memoized; failures may be transient.
- Flags are not part of the key: they govern TLS/verification/registry
  credentials, not which tag a constraint matches (--devel is already
  omitted as it is ignored whenever --version is set).
- Concurrent misses may both hit the registry; last write wins,
  harmlessly.

resetResolvedOCIConstraintsForTest is added alongside the existing
resetChartCacheForTest and wired into the issue #2766 tests — notably
ResolvesToDifferentVersionsPicksSeparateCachePaths, which reuses the
same chart+constraint across its two runs and would otherwise be served
the first resolution from the memo (which is exactly the intended
per-process semantics).

New coverage: TestResolveOCIConstraintVersion_Memoized (memo hit skips
the registry, different constraint is a different key) and
TestGetOCIChart_SharedConstraintResolvedOncePerProcess (two releases,
one inspector call, one pull, same path).

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: cover URL-embedded OCI constraint resolution

Address review feedback on PR #2768: the existing integration tests only
exercised the repo-aliased spelling (chart: myrepo/mychart, version:
'~1') and the version-field spelling. The chart-URL spelling
(chart: oci://<registry>/<chart>:~1) takes a different branch in
getOCIQualifiedChartName — the URL version is deliberately NOT embedded
into the qualified ref and flows through --version only — so its
re-qualification after constraint resolution (release.Version mutated to
the resolved value, versionInURL still the constraint) was untested.

TestGetOCIChart_URLEmbeddedConstraintResolves asserts the resolver
receives the URL-embedded constraint, helm chart pull receives the
resolved version via --version with a tag-less ref, and the cache path
carries the resolved version segment instead of the raw constraint.

Also gofmt-aligns the test tables added in earlier commits and drops a
redundant 1.2.3 test case that tripped goconst.

Signed-off-by: yxxhero <aiopsclub@163.com>

* docs: note empty-version OCI releases are unaffected by resolveOCIVersions

Releases with no version: at all keep their pre-existing semantics: helm
picks the latest tag at pull time and helmfile caches it under a
version-less shared-cache path. Document the limitation alongside the
other resolveOCIVersions scope notes.

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: Samuel Archambault <samuel.archambault@getmaintainx.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: Samuel Archambault <samuel.archambault@getmaintainx.com>
Co-authored-by: yxxhero <aiopsclub@163.com>
2026-09-07 16:50:25 +08:00
yxxhero 7f748fec1b feat: support Helm 4 --rollback-on-failure alongside deprecated --atomic (#2722)
* feat: support Helm 4 --rollback-on-failure alongside deprecated --atomic (#2712)

Helm 4 renamed the `--atomic` flag to `--rollback-on-failure`
(helm/helm#13629). The old flag still works under Helm 4 but is
deprecated (prints a warning) and slated for removal in Helm 5.

Add a `rollbackOnFailure` key to both `helmDefaults` (HelmSpec) and
`releases[]` (ReleaseSpec) that emits `--rollback-on-failure`. It
requires Helm 4+ (errors otherwise) and is mutually exclusive with
`atomic`.

Additionally, when the resolved Helm binary is v4+, an existing
`atomic: true` now emits `--rollback-on-failure` instead of `--atomic`,
so users are migrated off the deprecated flag automatically without any
config change. On older Helm, `atomic: true` continues to emit
`--atomic`.

Updated the spew-based values-ID hashes in temp_test.go that change
whenever ReleaseSpec gains a field (same approach as the --force-conflicts
change in #2480).

Closes #2712.

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: add integration test for rollback-on-failure / atomic migration (#2712)

Covers the end-to-end plumbing that unit tests cannot (real helm version
detection + cluster deploy) via test/integration/run.sh:

  1. atomic: true parses, deploys a ConfigMap, and emits the version-correct
     flag: --rollback-on-failure on Helm 4 (auto-migration of the deprecated
     --atomic) and --atomic on Helm 3.
  2. rollbackOnFailure: true emits --rollback-on-failure on Helm 4 and is
     rejected with a clear Helm-4-required error on Helm 3.

Flag assertions grep the `exec: helm upgrade --install` lines logged under
--debug, matching flags as standalone tokens so the release name
"issue-2712-atomic" cannot be confused with the "--atomic" flag.

Verified locally against Helm 4.2.3: both atomic:true and
rollbackOnFailure:true emit --rollback-on-failure with no --atomic.

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <aiopsclub@163.com>
2026-07-31 22:22:31 +08:00
Arthur Garreauandyxxhero cc85562625 feat: Add ConditionTemplate support in releaseSpec (#2669)
* feat: Add ConditionTemplate support in releaseSpec

Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>

* feat: improve testing, clarify doc

Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>

* feat: update CHANGELOG for ConditionTemplate support and fix test cases for ID generation

Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>

* Update pkg/state/state_exec_tmpl.go

Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>

* Update pkg/state/state_exec_tmpl.go

Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>

* Update docs/configuration.md

Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>

* refactor: improve comments for condition checks and clean up whitespace

Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>

---------

Signed-off-by: Arthur Garreau <arthur.garreau98@gmail.com>
Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
2026-07-01 18:44:43 +08:00
yxxheroandRoman Mykhailiuk 9d3a9ad6c7 feat: parallel kubedog tracking with progress printer and safety valves (#2654)
* feat: parallel kubedog tracking with progress printer and safety valves

Rework kubedog integration so resource tracking runs in parallel with
helm upgrade/install, giving live progress output and recovering from
known helm/kubedog wedge conditions.

Core:
- kubedogTrackingHandle runs tracking in a background goroutine alongside
  the helm subprocess (startBackgroundKubedogTracking); helm output is
  buffered and replayed as a single block so it no longer interleaves
  with progress ticks.
- Capture UID+generation baselines before handing off to helm so each
  tracker waits until the resource actually changes (freshness gate).

Progress printer (pkg/kubedog/printer.go):
- Styled, auto-sized progress table with a heartbeat flusher, child (pod)
  status roll-up, pre-ready pod-phase handling, multi-namespace support,
  and optional color. PreviewBreakdown summarizes kept/filtered resources.

Safety valves (verify cluster state via the live API):
- Tracker-race valve (always on): when helm succeeds but a dyntracker
  goroutine is wedged, poll the API and cancel the tracker so wait()
  returns success instead of blocking until --track-timeout.
- Helm-stuck killer (opt-in via helmStuckGrace): if the cluster stays
  converged while helm v4's hook waiter is wedged, SIGINT the helm
  subprocess to recover.
- Failure watchdog (pkg/kubedog/watchdog.go): surface failing pods that
  never made it into dyntracker's resource graph.

Options: trackFailedLogs, helmStuckGrace, trackTimeout, color
(Color/NoColor), and resource filtering (trackKinds/skipKinds/
trackResources). PersistentVolumeClaim support in resource classification.

Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com>

* test: add unit tests for kubedog tracking

Cover the progress printer, resource classification, the failure
watchdog, helm-output trimming/dedup, the release hard-timeout helper,
and the color/track option plumbing.

Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com>

* test: update golden logs, e2e snapshots, and values-id fixtures

Refresh pkg/app testapply/testdestroy golden logs, e2e template
snapshots, and the TestGenerateID values-id golden hashes for the new
kubedog progress output and the merged release struct layout.

Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com>

* refactor: remove dead kubedog display code and dedupe tracker setup

Deep-review pass on the parallel kubedog tracking changes:

- Remove pkg/kubedog/display.go (308 lines) and display_test.go (453 lines).
  These rendered progress for the legacy per-kind trackers that this PR
  replaces; in the merged tree every function is unreferenced outside its
  own tests. The new progressPrinter (printer.go) supersedes them.
  TestMain (color.ForceColor for deterministic ANSI in tests) is preserved
  in a new main_test.go.
- Dedupe trackWithKubedog: the post-helm fallback rebuilt the exact same
  tracker options as buildReleaseTracker. Reuse buildReleaseTracker instead,
  dropping ~40 lines of duplicated timeout/log/filter/tracker construction.

No behavior change; build, go vet, golangci-lint, and the kubedog/state
unit tests all pass.

Signed-off-by: yxxhero <aiopsclub@163.com>

* fix: stop waitForFreshness busy-looping the API after helm finishes

Once upstreamDoneCh closes it is always ready, so the select in
waitForFreshness stopped blocking on the ticker and re-ran probe() (a
live GET) as fast as the round-trip allowed for the whole 3s grace
window — hammering the API server once per tracked resource.

Track a local view of the channel and nil it out on first delivery so
the first hit records the timestamp (one fast retry, as intended) and
all subsequent polls are ticker-throttled. Functional behavior is
unchanged: return nil when fresh, errUpstreamDoneNoChange after grace.

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: drop trailing blank line from helm4 OCI pull snapshots

The trailing-newline trim in helmexec.info() removes the blank line helm
prints after the OCI chart "Digest:" line. The helm3 (output.yaml)
snapshots never captured that line, but the helm4 (output-helm4.yaml)
snapshots for oci_chart_pull{,_direct,_once,_once2} and
issue_473_oci_chart_url_fetch still expected it, so they failed under
helm 4. Remove the blank line so the snapshots match the trimmed output.

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: refresh diff-args integration goldens for styled release headers

DisplayAffectedReleases now emits a styled "========== Updated Releases
==========" header (matching the app/e2e goldens already updated by this
PR) and helmexec.info() trims the trailing blank after helm's install
status. Update the diff-args apply-stderr{,-helm4} and apply-live-
stderr{,-helm4} goldens accordingly so they match the actual stderr.

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: drop trimmed blank line from v1-subhelmfile template golden

The trailing-newline trim in helmexec.info() removes the blank line helm
prints after '"incubator" has been added to your repositories'. Update
the v1-subhelmfile-multi-bases-with-array-values result and result-live
goldens so the template stdout comparison matches.

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: Roman Mykhailiuk <romanm@cybellum.com>
2026-06-21 13:43:17 +08:00
yxxhero a94fdf4194 feat: add support for helm 4 --server-side upgrade flag (#2641)
* feat: add support for helm 4 --server-side upgrade flag

Add support for the helm 4 upgrade flag --server-side which accepts
"true", "false", or "auto" (default "auto"). This allows users to
explicitly control server-side apply behavior, which is needed for
releases originally installed with Helm 3 and being managed with Helm 4.

The flag can be configured via:
- CLI: --server-side flag on sync, apply, and diff commands
- helmDefaults.serverSide in helmfile.yaml
- releases[].serverSide per-release override

Precedence: release-level > CLI flag > helmDefaults.
Errors are returned when serverSide is set but running Helm 3, or when
an invalid value is provided.

Closes #2640

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: update TestGenerateID expected hashes for new ServerSide field

Adding ServerSide *string to ReleaseSpec changes spew's %#v output and
shifts the FNV hash used by generateValuesID. Update the hard-coded want
values to the new deterministic hashes.

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <aiopsclub@163.com>
2026-06-16 08:24:47 +08:00
yxxheroandcopilot-swe-agent[bot] 420cc3ba9c fix: add trackFailOnError option to control kubedog exit code (#2576)
* 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>
2026-05-04 14:20:03 +08:00
Jinyu c70b20ad7a feat: add an arg that passing description to helm upgrade command (#2497)
* feat: add an arg that passing description to `helm upgrade` command

fix: github actions

Signed-off-by: swimablefish <swimablefish@gmail.com>

* fix: lint and test failed

Signed-off-by: swimablefish <swimablefish@gmail.com>

* feat: encapsulation

Signed-off-by: swimablefish <swimablefish@gmail.com>

* feat: add version gate

Signed-off-by: swimablefish <swimablefish@gmail.com>

* feat: rephrase

Signed-off-by: swimablefish <swimablefish@gmail.com>

---------

Signed-off-by: swimablefish <swimablefish@gmail.com>
2026-03-24 21:01:44 +08:00
yxxhero d613c5484c feat: add --force-conflicts flag support for Helm 4 (#2480)
* 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>
2026-03-14 08:44:44 +08:00
yxxhero ce09f560d9 fix: configure kubedog rate limiter to prevent context cancellation (#2446) 2026-03-03 19:24:28 +08:00
yxxhero 6e21671228 feat: kubedog integration with unified resource handling (#2383)
* feat: add kubedog-based resource tracking integration

Add kubedog tracking as an alternative to Helm's --wait flag with:
- Real-time deployment progress tracking
- Container log streaming
- Fine-grained resource filtering (trackKinds/skipKinds/trackResources)

Features:
- New pkg/resource package for unified manifest parsing and filtering
- New pkg/kubedog package wrapping kubedog library
- CLI flags: --track-mode, --track-timeout, --track-logs
- Helmfile YAML support for trackMode, trackTimeout, trackLogs, trackKinds, skipKinds, trackResources
- Case-insensitive kind matching for filtering
- Multi-context support with proper kubeconfig/kubeContext handling

Tracking supports: Deployment, StatefulSet, DaemonSet, Job

Resource filtering priority (highest to lowest):
1. trackResources - explicit resource whitelist
2. skipKinds - blacklist specific kinds
3. trackKinds - whitelist specific kinds

Integration:
- Disable Helm --wait when using kubedog tracking
- Track after successful Helm sync/apply
- Respect release.Namespace as fallback for resources without namespace
- Use getKubeContext() for correct cluster targeting

Tests:
- Unit tests for resource filtering and kubedog options
- Integration test with httpbin chart
- E2E snapshot tests for YAML serialization
- Documentation in docs/advanced-features.md

Signed-off-by: yxxhero <aiopsclub@163.com>

* fix: address PR #2383 review comments (round 4)

1. resource/filter.go: Skip empty whitelist entries in matchWhitelist
   - At least one field (kind/name/namespace) must be specified
   - Prevents matching all resources with empty TrackResources entries

2. config/apply.go: Add ValidateConfig for track-mode validation
   - Validate --track-mode must be 'helm' or 'kubedog'
   - Reject invalid values like --track-mode foo

3. config/sync.go: Add ValidateConfig for track-mode validation
   - Same validation as apply command
   - Ensures consistent behavior across commands

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <aiopsclub@163.com>
2026-03-02 17:15:12 +08:00
Aditya Menon 0129681222 feat: add helmfile unittest command for helm-unittest integration (#2400)
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>
2026-02-16 09:45:10 +08:00
Aditya Menon c8bcbcd629 🐛 Fix four critical issues: environment merging, kubeVersion detection, lookup() with kustomize, and Helm 4 color flags (#2276)
* fix: deep merge environments from multiple bases (#2273)

Problem:
When using multiple base helmfiles, environment values were being
completely replaced instead of deep-merged due to mergo.WithOverride
introduced in PR #2228.

Solution:
- Created mergeEnvironments() function for proper deep merging
- Manually merge environment Values and Secrets slices before struct merge
- Preserves all environment values from both base and current helmfile

Testing:
- Added TestEnvironmentMergingWithBases with two scenarios:
  1. Multiple bases with overlapping environment values
  2. Environment values with array merging

Fixes #2273

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: auto-detect Kubernetes version for helm-diff (#2275)

Problem:
When helmfile runs helm-diff without specifying kubeVersion, helm-diff
falls back to v1.20.0. This causes chart compatibility checks to fail
for charts requiring newer Kubernetes versions (e.g., kubeVersion: ">=1.25.0").

Root Cause:
- flagsForDiff() was not passing kubeVersion to helm-diff plugin
- Without --kube-version flag, helm-diff uses default v1.20.0

Solution:
- Created pkg/cluster package with DetectServerVersion() function
- Auto-detect cluster version using k8s.io/client-go discovery API
- Pass detected version to helm-diff via --kube-version flag
- Priority: helmfile.yaml kubeVersion > auto-detected version
- Works with both Helm 3 and Helm 4

Implementation:
- pkg/cluster/version.go: Cluster version detection
- pkg/app/app.go: detectKubeVersion() helper used in diff() and apply()
- pkg/state/state.go: Added DetectedKubeVersion field to DiffOpts
- Integrated into flagsForDiff() with proper precedence

Testing:
- Unit tests for cluster version detection
- Unit tests for kubeVersion precedence logic
- Integration test with chart requiring Kubernetes >=1.25.0
- Tests verify upgrade scenario (critical failure case from issue)
- Validated with both Helm 3 and Helm 4

Fixes #2275

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: enable lookup() function with strategicMergePatches (#2271)

Problem:
When using strategicMergePatches (kustomize), Helm's lookup() function
stops working. Charts like Grafana use lookup() to preserve existing
resource values (e.g., PVC volumeName), which get lost when using patches.

Root Cause:
- Chartify runs "helm template" to render charts before applying patches
- By default, "helm template" runs client-side without cluster access
- The lookup() function requires cluster connectivity to query resources
- Without cluster access, lookup() returns empty values

Solution:
- Pass --dry-run=server to helm template when using kustomize patches
- This enables cluster connectivity for lookup() while keeping client-side rendering
- Only applied to commands requiring cluster access (diff, apply, sync, etc.)
- Offline commands (template, lint, build) remain cluster-independent

Implementation:
- Modified processChartification() to accept helmfileCommand parameter
- Added switch-based logic to determine cluster requirement per command
- Conditionally set chartifyOpts.TemplateArgs = "--dry-run=server"
- Safe default: unknown commands assume cluster access

Command Behavior:
- helmfile diff/apply/sync: Uses --dry-run=server, lookup() works
- helmfile template/lint/build: No cluster requirement, works offline
- Charts without lookup(): Unaffected
- Charts with lookup() + cluster: Lookup values preserved correctly

Testing:
- Integration test with ConfigMap using lookup() to preserve values
- Verifies lookup works with strategicMergePatches
- Tests both with and without cluster access
- Validates offline template command still works

Fixes #2271

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: remove unnecessary error return from mergeEnvironments

The mergeEnvironments function always returns nil, making the error
return value unnecessary. This fixes the unparam linter warning.

- Changed function signature to not return error
- Updated call site to not handle error
- All tests still pass

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: handle nil Environments map in mergeEnvironments

Fixes panic when base helmfile has nil Environments map.
Initialize the destination map if nil before merging to prevent
"assignment to entry in nil map" panic.

- Added nil check in mergeEnvironments to return early
- Initialize layers[0].Environments before merge if nil
- Fixes TestVisitDesiredStatesWithReleasesFiltered_Issue1008_MissingNonDefaultEnvInBase

The panic occurred when a base helmfile didn't define any environments
but a subsequent layer did. Now we properly initialize an empty map
to merge into.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* test: disable kubeVersion auto-detection in unit tests

Add DisableKubeVersionAutoDetection field to App struct to prevent
unit tests from connecting to real Kubernetes clusters during testing.

The kubeVersion auto-detection feature (issue #2275) was causing
unit tests to fail because:
1. Tests use mock helm implementations without real cluster access
2. Auto-detection was connecting to local minikube cluster (v1.34.0)
3. Test expectations didn't include --kube-version flag in diff keys

Solution:
- Add DisableKubeVersionAutoDetection bool field to App struct
- Check this flag in detectKubeVersion() before attempting detection
- Set flag to true in all pkg/app/*_test.go files

This ensures unit tests remain isolated and don't depend on
external cluster state while preserving auto-detection for
production use.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* chore: upgrade helm-diff plugin to v3.14.1

Update helm-diff plugin from v3.14.0 to v3.14.1 across all environments:
- Dockerfiles (main, debian-stable-slim, ubuntu)
- CI workflow matrix configurations
- Integration test default version

This ensures consistency across development, testing, and production
environments.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* test: fix table formatting and improve E2E test infrastructure

This commit addresses multiple test failures and improves the testing
infrastructure for better reliability and maintainability.

Table Formatting Fixes:
- Added trimTrailingWhitespace() helper function to remove trailing
  whitespace from table output in both FormatAsTable() and printDAG()
- Fixes TestList and TestDAG failures caused by tabwriter padding
  empty columns with trailing spaces
- Updated golden file for table output test to match new behavior

E2E Test Infrastructure Improvements:
- Implemented dynamic port allocation for Docker registry tests to
  prevent port conflicts (replaced hardcoded port 5000/5001)
- Added getFreePort() function using kernel-allocated unused ports
- Added waitForRegistry() function with proper health check polling
  of Docker Registry /v2/ endpoint (replaces sleep hack)
- Added prepareInputFile() function to handle port substitution and
  path resolution when copying helmfile configs to temp directories
- Extracted setupLocalDockerRegistry() helper to reduce cognitive
  complexity from 111 to ≤110 (gocognit threshold)
- Added port normalization in test output to replace dynamic ports
  with $REGISTRY_PORT placeholder for deterministic comparisons

Test Configuration Updates:
- Updated OCI chart tests to use dynamic port allocation via
  $REGISTRY_PORT placeholder in helmfile configs
- Converted relative chart paths to absolute paths when input files
  are copied to temp directories (fixes path resolution issues)
- Left postrenderer paths as relative since they're resolved from
  working directory (works for both Helm 3 and Helm 4)

Golden File Updates:
- Updated all OCI-related test expected outputs to use $REGISTRY_PORT
  placeholder instead of hardcoded ports
- Removed trailing whitespace from issue_493 test expected output
- Updated postrenderer test outputs to reflect chart path normalization

Test Cleanup:
- Removed unused fakeInit struct and CheckHelmPlugins() call from
  snapshot tests (not needed for template/fetch/list commands)
- Removed unused imports (app, helmexec packages)

Technical Details:
- Port allocation uses net.Listen with port 0 for kernel assignment
- Registry health check polls with 500ms intervals and 30s timeout
- Chart paths: ../../charts/* → absolute paths (input file moves to temp)
- Postrenderer paths: remain relative (resolved from working directory)
- OCI cache paths normalized: oci__localhost_PORT → oci__localhost_$REGISTRY_PORT

All originally failing tests now pass:
- TestList ✓
- TestDAG ✓
- TestHelmfileTemplateWithBuildCommand (all OCI tests) ✓
- TestFormatAsTable ✓

Fixes three test failures reported in issue.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix(test): convert postrenderer paths to absolute for Helm 3

Helm 3 resolves postrenderer script paths relative to the helmfile
location. When the input file is copied to a temp directory for
port substitution, relative postrenderer paths break.

Solution:
- Added postrenderersDir parameter to prepareInputFile()
- Convert ../../postrenderers/* to absolute paths for Helm 3 only
- Use existing isHelm4() function to detect Helm version
- Helm 4 extracts plugin names from paths, so works with relative

This fixes the postrenderer test failure in CI where Helm 3 could
not find the postrenderer script at the relative path.

Fixes: Error: unable to find binary at ../../postrenderers/add-cm2.bash
Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix(test): remove remaining hardcoded port 5001 in OCI tests

Updated 4 remaining OCI chart tests that still had hardcoded port 5001:
- oci_chart_pull
- oci_chart_pull_once
- oci_chart_pull_once2
- oci_chart_pull_direct

Changes:
- config.yaml: Removed hardcoded port, use dynamic allocation
- input.yaml.gotmpl: Replaced localhost:5001 with localhost:$REGISTRY_PORT

This ensures all OCI chart tests use dynamic port allocation to
prevent port conflicts during parallel test execution.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: prevent helm-diff from normalizing server-side defaults

Problem:
The suppress-output-line-regex integration test was failing because
helm-diff was reporting "has changed, but diff is empty after suppression"
for Service resources when it should have shown ipFamilyPolicy and ipFamilies
fields being removed.

Root Cause:
When auto-detected kubeVersion (e.g., 1.34.0) is passed to helm-diff via
--kube-version flag, helm-diff normalizes server-side defaults. This makes
fields like ipFamilyPolicy and ipFamilies appear unchanged, even though they
don't exist in the chart template and will be removed by the upgrade.

After applying suppressOutputLineRegex patterns, only label changes remained
(helm.sh/chart and app.kubernetes.io/version). These were correctly suppressed,
leaving an empty diff - hence the "diff is empty after suppression" message.

Solution:
Added a new configuration option 'disableAutoDetectedKubeVersionForDiff' to allow
disabling auto-detected kubeVersion being passed to helm-diff. This prevents
helm-diff from normalizing server-side defaults when needed.

Default behavior: Pass auto-detected kubeVersion (fixes issue #2275, existing behavior)
Opt-out behavior: Set flag to true to only use explicit kubeVersion from helmfile.yaml

helmDefaults:
  disableAutoDetectedKubeVersionForDiff: true  # false by default

releases:
- name: myrelease
  disableAutoDetectedKubeVersionForDiff: true  # override per-release

Implementation:
- Added DisableAutoDetectedKubeVersionForDiff field to HelmSpec and ReleaseSpec
- Updated flagsForDiff() to check this flag before passing kubeVersion
- Default (false): pass auto-detected kubeVersion (fixes issue #2275)
- Opt-out (true): only pass explicit kubeVersion from helmfile.yaml
- Updated suppress-output-line-regex test to disable auto-detected kubeVersion

This approach:
- Maintains backward compatibility (default passes auto-detected kubeVersion)
- Fixes issue #2275 for charts requiring newer Kubernetes versions
- Allows users to opt-out when server-side normalization causes issues
- Fixes suppress-output-line-regex test regression

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* test: update hash values in TestGenerateID after adding DisableAutoDetectedKubeVersionForDiff field

The hash values in TestGenerateID needed to be updated because adding the
DisableAutoDetectedKubeVersionForDiff field to ReleaseSpec changed the structure's
hash representation. This is expected behavior as generateValuesID() hashes the
entire ReleaseSpec structure.

Updated all expected hash values to match the new values:
- baseline: foo-values-66f7fd6f7b
- different bytes content: foo-values-6664979cd7
- different map content: foo-values-78897dfd49
- different chart: foo-values-64b7846cb7
- different name: bar-values-576cb7ddc7
- specific ns: myns-foo-values-6c567f54c

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: address PR review comments and resolve issue #2280

This commit addresses all review comments from GitHub Copilot and
resolves issue #2280 regarding --color flag conflict with Helm 4.

Changes:
1. Fixed documentation in pkg/cluster/version.go
   - Updated function comment to reflect error return behavior
   - Corrected version format example and comment

2. Added complete command categorization in pkg/state/state.go
   - Added all helmfile commands to cluster access switch statement
   - Properly categorized 15+ commands based on cluster requirements
   - Added clarifying comments for command groups

3. Resolved issue #2280: --color flag conflict with Helm 4
   - In Helm 4, --color expects a value (never/auto/always)
   - Converts --color to --color=always for Helm 4
   - Converts --no-color to --color=never for Helm 4
   - Prevents Helm from consuming next argument as color value
   - Added comprehensive unit tests
   - Added integration test (Helm 4 only)

Issue #2280 Details:
When running helmfile diff with --color and --context flags on Helm 4,
the --color flag would consume --context as its value, resulting in:
"invalid color mode '--context': must be one of: never, auto, always"

The fix detects Helm 4 and converts boolean color flags to the format
Helm 4 expects, preventing the argument consumption issue.

Fixes #2280

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: correct kubeVersion precedence comment in test

The comment incorrectly stated that state.KubeVersion takes precedence
over paramKubeVersion, but the actual implementation (getKubeVersion in
state.go:3354-3364) shows the correct order is:

1. paramKubeVersion (auto-detected from cluster)
2. release.KubeVersion (per-release override)
3. state.KubeVersion (helmfile.yaml global setting)

Updated the comment to match the implementation and the test cases.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* fix: resolve Helm 4 --color flag conflict (issue #2280)

This commit resolves issue #2280 where the --color flag causes Helm 4
to consume the next argument, resulting in errors like:
"invalid color mode '--context': must be one of: never, auto, always"

Root Cause:
In Helm 4, the --color flag is parsed by the Helm binary before being
passed to plugins like helm-diff. This causes Helm to interpret the
next argument (e.g., --context) as the value for --color.

Solution:
Remove --color and --no-color flags from helm-diff commands when using
Helm 4, and instead use the HELM_DIFF_COLOR environment variable.
The helm-diff plugin supports HELM_DIFF_COLOR=[true|false] as an
alternative to the --color/--no-color flags.

Changes:
1. Added filterColorFlagsForHelm4() function in pkg/helmexec/exec.go
   - Removes --color and --no-color flags from flags slice
   - Sets HELM_DIFF_COLOR=true for --color
   - Sets HELM_DIFF_COLOR=false for --no-color

2. Modified DiffRelease() to call filterColorFlagsForHelm4() on Helm 4

3. Added comprehensive unit tests in pkg/helmexec/exec_test.go
   - Test_DiffRelease_ColorFlagHelm4: Verifies flags are filtered
   - Test_FilterColorFlagsForHelm4: Tests all flag combinations

4. Added integration test in test/integration/test-cases/issue-2280.sh
   - Tests the exact scenario from issue #2280
   - Verifies --color and --context flags work together
   - Helm 4 only test (skipped on Helm 3)

Fixes #2280

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* refactor: apply Copilot code review nitpicks

This commit addresses minor code quality improvements suggested by
GitHub Copilot's automated review.

Changes:
1. pkg/app/formatters.go - Optimize trimTrailingWhitespace()
   - Only modify lines that actually have trailing whitespace
   - Avoids unnecessary string allocations for clean lines
   - Performance optimization for table formatting

2. test/e2e/template/helmfile/snapshot_test.go
   - Use 0600 permissions for temporary input files (was 0644)
   - Improves security by making temp files owner-only read/write
   - Prevents potential exposure of sensitive test data

   - Improve error messages in getFreePort()
   - Wrap errors with context using fmt.Errorf("%w")
   - Better error debugging when port allocation fails

   - Add retry logic to setupLocalDockerRegistry()
   - Handles race condition where port gets taken between allocation and use
   - Retries up to 3 times with new ports on "address already in use" errors
   - Fails fast on other Docker errors for better test diagnostics

All tests passing. These are non-functional improvements that enhance
code quality, performance, security, and test reliability.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* docs: improve code comments based on Copilot feedback

This commit addresses documentation nitpicks from GitHub Copilot's
automated review to improve code clarity and maintainability.

Changes:
1. pkg/app/app.go - Clarify detectKubeVersion() return conditions
   - Updated comment to explicitly list all three cases when empty
     string is returned: kubeVersion already set, auto-detection
     disabled, or detection fails
   - Improves function documentation clarity

2. test/e2e/template/helmfile/snapshot_test.go
   - Added reference to retry logic in getFreePort() comment
   - Points callers to setupLocalDockerRegistry() for proper race
     condition handling example
   - Better guidance for future code maintainers

3. pkg/state/state.go - Explain patches check rationale
   - Added comment explaining why --dry-run=server is only enabled
     when patches are used
   - Clarifies that this is a conservative approach to minimize
     unnecessary cluster connections
   - Documents primary use case (Grafana chart with PVC preservation)

All changes are documentation-only with no functional impact.
All tests passing.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

* refactor: enable lookup() for all cluster commands and add defensive check

This commit addresses two Copilot review suggestions to improve code
robustness and functionality.

Changes:
1. pkg/state/state.go - Remove patches requirement for lookup()
   - Previously only enabled --dry-run=server when patches were present
   - Now enables it for ALL cluster-requiring commands
   - Rationale: lookup() function can be used without patches
   - Improves compatibility with charts using lookup() standalone
   - Trade-off: Slightly more cluster connections vs broader support

2. pkg/helmexec/exec.go - Add defensive check for HELM_DIFF_COLOR
   - Only set environment variable if not already present
   - Makes code more defensive for future implementation changes
   - Note: Changes behavior from "last wins" to "first wins"
   - In practice, env map is freshly created so check is precautionary

3. pkg/helmexec/exec_test.go - Update test expectations
   - Changed test case to reflect "first wins" behavior
   - Updated test name and comment for clarity

Breaking behavior change:
- When both --color and --no-color are present, the FIRST flag now
  wins instead of the LAST flag
- This deviates from standard CLI conventions where later flags
  override earlier ones
- However, this is unlikely to affect real usage as users rarely
  specify conflicting flags

All tests passing.

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>

---------

Signed-off-by: Aditya Menon <amenon@canarytechnologies.com>
2025-11-21 08:32:54 +08:00
Simon Bouchard a6fab4dc75 feat: update strategy for reinstall (#2019)
* feat: Add updateStrategy option in the state file with 'reinstall'/'reinstallIfForbidden' choices to uninstall and apply the specific release(s) (if forbidden to update)

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Fix unit tests related to the new updateStrategy feature

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Fix unit tests related to the new updateStrategy feature

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Resolve linter issue due to cognitive complexity

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Updated index.md to describe the possible values of updateStrategy

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Add validation of updateStrategy parameter and unit test

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Updated unit test

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Removed 'reinstall' update strategy option to only have reinstallIfForbidden, cleanup of pre-sync changes, adapted unit tests

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Display affected releases that were reinstalled

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Make sure to add --wait when deleting a release to be reinstalled due to reinstallIfForbidden

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

* Apply suggestions from Copilot code review

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>

---------

Signed-off-by: Simon Bouchard <sbouchard@rbbn.com>
2025-10-29 08:47:46 +08:00
yxxhero b0911ab1a2 feat(state): add missingFileHandlerConfig and related logic (#2105)
* feat(state): add missingFileHandlerConfig and related logic

Signed-off-by: yxxhero <aiopsclub@163.com>

* feat(state): add missingFileHandlerConfig and related logic

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <aiopsclub@163.com>
2025-07-21 19:15:51 -04:00
yxxhero c3864a45d3 feat: add --take-ownership flag to helm diff and related config (#1992)
* feat: add --take-ownership flag to helm diff and related config

Signed-off-by: yxxhero <aiopsclub@163.com>

* fix: nil issue

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 more issue

Signed-off-by: yxxhero <aiopsclub@163.com>

* fix more issues

Signed-off-by: yxxhero <aiopsclub@163.com>

* fix tests

Signed-off-by: yxxhero <aiopsclub@163.com>

* add more tests

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <aiopsclub@163.com>
2025-04-27 12:57:41 -04:00
Adam Blasko 9bf51cb011 Feat: setting reuseValues flag in release (#2004)
* Feat: reuseValues in release

Adding properties to set reuseValues flag on release-level.

Signed-off-by: Adam Blasko <adam.blasko1@gmail.com>

* feat: fixing tests

Most of the tests had issues with flag order, which changed due to moving the value control flags out of the "common flags" for diff

Signed-off-by: Adam Blasko <adam.blasko1@gmail.com>

* fix: fixing lint issue

Signed-off-by: Adam Blasko <adam.blasko1@gmail.com>

---------

Signed-off-by: Adam Blasko <adam.blasko1@gmail.com>
2025-04-23 07:53:29 +08:00
yxxhero e4273d050e feat: add labels for helm release (#1046)
feat: add labels for k8s resources

Signed-off-by: yxxhero <aiopsclub@163.com>
2025-03-30 19:24:41 -04:00
Connor Hindley 2c38611acd feat: Add support for --wait-retries flag. (#1922)
* feat: Add support for --wait-retries flag.

This change wires up waitRetries option to set the helm --wait-retries flag.

--wait-retries was added in helm 3.15.0 and makes waiting more robust to registry errors.
https://github.com/helm/helm/commit/fc74964
https://github.com/helm/helm/releases/tag/v3.15.0

Resolves #1522

Signed-off-by: Connor Hindley <connor.hindley@tanium.com>
2025-02-12 07:28:37 +08:00
yxxhero bd12fa1cc3 feat(state): add support for setString in ReleaseSpec and HelmState (#1821)
* feat(state): add support for setString in ReleaseSpec and HelmState

Signed-off-by: yxxhero <aiopsclub@163.com>

* docs: add setString section to index.md for helm configuration

Signed-off-by: yxxhero <aiopsclub@163.com>

* tests: fix more tests

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <aiopsclub@163.com>
2024-12-09 10:37:56 -05:00
Zubair Haque d1416ec7b4 feat: add skip json schema validation during the install /upgrade of a Chart (#1737)
* open PR for --skip-schema-validation flag

Signed-off-by: zhaque44 <haque.zubair@gmail.com>
2024-10-24 20:53:18 +08:00
Shane Starcher b6ab825d3c [feature] add --skip-refresh to globals (#1736) 2024-10-12 19:56:55 +08:00
2cc995e508 feat: adding ability for for charts to be pulled with plain HTTP (#1672)
* eat: adding ability for for charts to be pulled without HTTPS

accomplished by:

- Adding PlainHttp attribute to RepositorySpec., HelmDefault, ReleaseSpec
- Adding UnitTests for getOCIChart Flags.
- Adding funciton and unitTests for getChartDownload
- Changing and refactoring how Flags are added to getOCIChart.

Resolves #1224

Signed-off-by: Peter Halliday <peter.halliday@servicenow.com>

* Pass PlainHttp to OCI repo options, fix unit test

Signed-off-by: Pascal Rivard <privard@rbbn.com>

* Fix doc

Signed-off-by: Pascal Rivard <privard@rbbn.com>

* Use repository fields in non-OCI chart download options

Signed-off-by: Pascal Rivard <privard@rbbn.com>

* Update hashes in TestGenerateID

Signed-off-by: Pascal Rivard <privard@rbbn.com>

* Make sure repo exists when using its options

Signed-off-by: Pascal Rivard <privard@rbbn.com>

* Do not add TLS options if PlainHttp is set, adapt unit tests

Signed-off-by: Pascal Rivard <privard@rbbn.com>

* Fix doc

Signed-off-by: Pascal Rivard <privard@rbbn.com>

* Remove 'else if' from appendChartDownloadFlags

Signed-off-by: Pascal Rivard <privard@rbbn.com>

---------

Signed-off-by: Peter Halliday <peter.halliday@servicenow.com>
Signed-off-by: Pascal Rivard <privard@rbbn.com>
Co-authored-by: Peter Halliday <peter.halliday@servicenow.com>
Co-authored-by: Pascal Rivard <privard@rbbn.com>
2024-08-27 08:00:20 +08:00
yxxhero 9203641f03 feat: add suppress output line regex support (#1329)
* feat: add suppress output line regex support

Signed-off-by: yxxhero <aiopsclub@163.com>
2024-02-18 12:10:14 +08:00
b10692dc9b Create DeleteWait and DeleteTimeout parameters for Destroy (#1177)
* Create DeleteWait and DeleteTimeout parameters

Signed-off-by: Virginia Tavares <briosovirginia@gmail.com>

* Create tests for deleteWait and deleteTimeout

Signed-off-by: Virginia Tavares <briosovirginia@gmail.com>

* build(deps): bump github.com/aws/aws-sdk-go from 1.48.6 to 1.48.7 (#1176)

Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.48.6 to 1.48.7.
- [Release notes](https://github.com/aws/aws-sdk-go/releases)
- [Commits](https://github.com/aws/aws-sdk-go/compare/v1.48.6...v1.48.7)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update temp_test.go with DeleteWait and DeleteTimeout

Signed-off-by: Virginia Tavares <briosovirginia@gmail.com>

* Create deleteWait function in state.go

Signed-off-by: Virginia Tavares <briosovirginia@gmail.com>

* Fix comments from review

Signed-off-by: Virginia Tavares <briosovirginia@gmail.com>

---------

Signed-off-by: Virginia Tavares <briosovirginia@gmail.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Virginia Tavares <virginia.tavares@ericsson.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 08:38:37 +08:00
Maarten Boekhold d0b8d7ee5e Add "PostRendererArgs" option to be passed to helm (#1133)
* Add "PostRendererArgs" option to be passed to helm

This allows using PowerShell scripts on Windows as Post Renderer.

Signed-off-by: Maarten Boekhold <maarten.boekhold@finastra.com>
2023-11-21 21:32:14 +08:00
yxxhero 803ff8d0ab feat keyring supportting (#984)
* feat keyring supportting

Signed-off-by: yxxhero <aiopsclub@163.com>
2023-08-22 21:00:45 -05:00
Jan-Otto Kröpke d1c260af5f feat: Allow to skip diff output on release base (#906)
* feat: Allow to skip diff output on release base

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>

* fix tests

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* feat: Allow to skip diff output on release base

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>

* fix tests

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* s/skipDiffOutput/suppressDiff

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* s/skipDiffOutput/suppressDiff

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix tests

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>

---------

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
2023-07-02 07:50:59 +08:00
yxxhero c55fa0f765 Replace interface{} by any (#901)
Signed-off-by: yxxhero <aiopsclub@163.com>
2023-06-16 10:49:05 +09:00
yxxhero 1843cc447e Add insecure skip tls verify support (#882)
* feat: add insecure-skip-tls-verify support

Signed-off-by: yxxhero <aiopsclub@163.com>
2023-06-04 16:34:24 +08:00
yxxhero ae77967bf2 cleanup: remove tls configures about helm v2 (#880) 2023-06-03 22:02:46 +08:00
yxxhero 00dace9b63 Feat add cascade support (#860)
* feat: add cascade support for helm v3.12.0

Signed-off-by: yxxhero <aiopsclub@163.com>
2023-05-15 13:49:33 +08:00
Vincent Stchu 3d0f0afe3a Feat: support helm flag --enable-dns (#830)
* Support helm flag --enable-dns

Signed-off-by: vincent_stchu <24803055+vincentstchu@users.noreply.github.com>
2023-04-27 16:27:09 +08:00
AlexAxenti 0012e7e5a1 feat: add duration to affected releases on sync (#773)
* feat: add duration to affected releases on sync

Signed-off-by: Alexandru Axenti <alex.axenti@gmail.com>
2023-04-15 08:09:47 +08:00
Yusuke Kuoka fc027d1538 breaking: Fix the inherit feature to support multi-inheritance (#674)
* breaking: Fix the inherit feature introduced in Helmfile v0.150.0 for multi-inheritance

Follow-up for #435
Addresses https://github.com/helmfile/helmfile/discussions/656#discussioncomment-4877360 towards Helmfile v1

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

* Print a deprecation warning on releases[].inherit of map

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

---------

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
2023-02-07 08:18:19 +08:00
xiaomudk c4eb62388b Drop Helm v2 support (#613)
Resolves #589

Signed-off-by: xiaomudk <xiaomudk@gmail.com>
2023-01-17 09:24:47 +09:00
Yusuke Kuoka 490bb5d147 feat: inherit field for release template inheritance (#606)
* feat: `inherit` field for release template inheritance

Ref https://github.com/helmfile/helmfile/issues/435#issuecomment-1364749414

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

* Fix wording

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

* Comment on releaseWithInheritedTemplate

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

* Update Release Template doc with the new `inherit` feature

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

* Fix a typo in code comment

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
2022-12-28 10:01:04 +09:00
Yusuke Kuoka d0915641ca Fix TestGenerateID
Signed-off-by: yxxhero <aiopsclub@163.com>
2022-12-13 13:12:07 +08:00
yxxhero ac23def893 add Go lint
Signed-off-by: yxxhero <aiopsclub@163.com>
2022-07-16 20:21:11 +08:00
Yusuke Kuoka 8e50dbc46d Fix helmfile deps not to remove entries for charts that are being chartified
When chartify is involved due to the use of `forceNamespace`, `strategicMergePatches`, `jsonPatches`, and so on, We had been internally mutating the Release.Chart with the path to the local temporary directory that contains the modified version of the chart.

This resulted in us unintentionally making `helmfile deps` to remove entries for the chart being modified out of helmfile.lock file, which resulted in issues like #2110.

To be clear, although the original issue is reported to occur for `strategicMergePatches`, I believe that it occurered also for any remote charts using `jsonPatches` and `forceNamespace` too.

I also believe this has been the issue since our introduction of chartify (maybe a year or so ago??), and I guess why it took so much time to be found and reported is that not so many people with chartify in combination with `helmfile deps` 🤔

Lastly, this changes chart names surfaced in the various log output from Helmfile, from temporary chart paths to the chart name/path declared in the helmfile.yaml. I think this is generally a good change, no fear of being a breaking change. But if anyone has any concern about that, please feel free to comment/report/etc.

Ref https://github.com/roboll/helmfile/issues/2110

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
2022-04-06 02:12:08 +00:00
Yusuke Kuoka be5af8e3b7 Enhance support for kube-version and api-versions (#2121)
This adds support for `kube-version` and `api-versions` to be available to `chartify` so that it works even if your release requires `chartify` due to that you use features like `forceNamespace`, `jsonPatches`, `strategicMergePatches`, and so on.

This also enhances `ReleaseSpec` which corresponds to each item of `releases[]` in your `helmfile.yaml` to also accept `kubeVersion` and `apiVersions`, in addition to the top-level `kubeVersion` and `apiVersions` we have today.

The top-level ones works as the default values for release-specific ones. If you have been using the top-level ones, keep using it. It is backward-compatible. If you want to specify it per release, because, for example, your releases are deployed across clusters(in case you differentiate `kubeContext` fields), try the new fields added to the release spec.

Resolves #1864
2022-03-31 11:02:36 +09:00
Quan TRAN 53c6d2f988 Add helmfile-fetch command to downloading and generating charts (#1734) 2021-03-30 16:26:31 +09:00
Jason Witkowski 2618cfb38b Enable --wait-for-jobs flag introduced in helm 3.5 (#1715)
Fixes #1650
Fixes #785

This change introduces:

- `--wait-for-jobs` CLI override option to helmfile binary
- `waitForJobs` helmDefaults parameter (default `false`)
- `waitForJobs` release parameter (default `false`)

Note that `--wait-for-jobs` was introduced in Helm 3.5 (https://github.com/helm/helm/pull/8363)
2021-03-23 16:53:57 +09:00
Yusuke Kuoka 9b64d65d94 feat: Stabilize helmfile-diff output (#1622)
This finishes the work started at #1619 by introducing the following changes:

- You can now set `HELMFILE_TEMPDIR` and `CHARTIFY_TEMPDIR` as the directory to persist temporary values files rendered by helmfile and temporary charts generated by chartify. Note that chartify is used internally when you use kustomize integration or raw K8s manifests as a chart.
- Helmfile uses the hash sum of the release config and the values file content in the file name of the temporary values file.

  In combination with `HELMFILE_TEMPDIR` and `CHARTIFY_TEMPDIR`, this enables helmfile to use the stable file names for temporary values files, which contribute to stabilize log messages like `Comparing release=appset, chart=PATH/TO/TEMPORARY/CHART`, where the `PATH/TO/TEMPORARY/CHART` had been randomized due to formerly random helmfile tempdir and temporary values file names, and random chartify tempdir.

You can try this feature with a script like:

```
tempdir=$(mktemp -d -t helmfile)

HELMFILE_TEMPDIR=${tempdir} CHARTIFY_TEMPDIR=${tempdir} helmfile diff

rm -rf ${tempdir}
```
2020-12-15 10:24:27 +09:00