v2 → v3 Migration Guide¶
Status: Preview. v3.0.0 is content-frozen on
mainahead of the August 2026 launch window. This page is the consumer-facing migration playbook; pin the existing:2floating tag until the launch announcement.
TL;DR
The runtime image bumps Helm 3.x → 4.2.2 and Cosign 2.x → 3.1.1. The pipe's env-var schema, exit-code map, and chart-source semantics are unchanged. The only consumer-visible behavioural change is in SAFE_UPGRADE=true deploys — Helm v4 uses the kstatus-based watcher wait strategy instead of the helm-3 resource-poll wait. For most pipelines, the migration is a one-line image-tag change: :2 → :3.
v3.0.0 is a SemVer-major release driven by the bundled-binary majors rather than by any change in the pipe's own contract. The pipe's public surface (env vars, exit codes, structured-log shape, chart-source URI schemes, action verbs) is fully forward-compatible from v2.0. The bump exists so consumers can opt-in to the helm-v4 + cosign-v3 runtime deliberately — see ADR-0010 for the rationale.
Breaking changes at a glance¶
| Change | v2.x (helm 3.18.6 / cosign 2.6.3) | v3.0.0 (helm 4.2.2 / cosign 3.1.1) | Reference |
|---|---|---|---|
| Bundled Helm | 3.18.6 |
4.2.2 |
ADR-0010 |
| Bundled Cosign | 2.6.3 |
3.1.1 |
PR #71 |
| Bundled helm-diff plugin | 3.10.0 |
3.15.10 |
PR #71 |
SAFE_UPGRADE=true wait strategy |
helm-3 resource-poll wait | helm-4 kstatus-based watcher wait |
helm v4.2.2 pkg/cmd/flags.go::AddWaitFlag |
| Internal upgrade argv tail (advisory) | --wait --atomic --description "pipe:safe-upgrade" |
--wait --rollback-on-failure --description "pipe:safe-upgrade" |
helm v4.2.2 pkg/cmd/upgrade.go::MarkDeprecated("atomic", …) |
| Image-tag floating policy | :2 rolling within v2.x |
:3 rolling within v3.x; :2 frozen at last helm-3 build through 2026-11-11 |
This guide §"Tag policy" |
trivy-image CI gate |
advisory until v3.0.0 prep work | hard gate in the v3 release | PR #71 |
The pipe's public API (env vars, exit codes, structured-log keys, action verbs, chart-source URI schemes) is fully unchanged from v2.0. If your pipeline does not pin to :2 exclusively and you do not parse Helm CLI stderr from the pipe's logs, the migration is a one-line image: swap.
Helm v3 → v4 — the headline runtime change¶
Breaking change
The bundled Helm binary jumps from major v3 to major v4. The pipe's helm upgrade --install surface is preserved (chart source, release name, namespace, set-string injection, --history-max, --timeout), but Helm v4 changes the wait strategy for SAFE_UPGRADE=true deploys and renames the --atomic flag to --rollback-on-failure (the pipe migrates to the canonical v4 name internally).
Why now¶
Helm v3 enters end-of-life on 2026-11-11 (Helm Version Support Policy). After that date, no further security backports land on the v3 branch. v3.0.0 of this pipe is published five months ahead of the EOL so consumers have a controlled migration window instead of a rushed EOL-day bump.
What changed under the hood¶
Helm v4 introduces a typed WaitStrategy enum for the --wait flag (watcher / hookOnly / legacy). Bare --wait still works (resolved to watcher via NoOptDefVal) — so the pipe's argv stays compatible — but the default semantics of the watcher are kstatus-based (kstatus library) rather than helm-3's resource-poll loop. In practice:
- Custom-resource readiness: kstatus watches CR status fields the helm-3 poller did not understand. If your charts include custom resources with
status.conditions, the watcher correctly waits forReady=Trueinstead of declaring success on initial CR creation. - Stderr output during wait: the lines emitted by
helm upgrade --waitare different in v4. Pipelines that grep for specific helm-3 wait messages (e.g."beginning wait for"or specific resource-name patterns) may need to update. - Timing characteristics: kstatus polling cadence is event-driven rather than fixed-interval. For most charts the wall-clock difference is small, but pipelines with very tight
--timeoutwindows may want to widen them by 10-20 % during the v3 ramp.
What changed at the argv layer¶
When you set SAFE_UPGRADE=true, the pipe internally appends a fixed argv tail to helm upgrade --install:
| argv tail | |
|---|---|
| v2.x (helm 3) | --wait --atomic --description "pipe:safe-upgrade" |
| v3.0.0 (helm 4) | --wait --rollback-on-failure --description "pipe:safe-upgrade" |
Helm v4 keeps --atomic as a deprecated alias for --rollback-on-failure (pkg/cmd/upgrade.go::MarkDeprecated), but emits a stderr WARNING on every invocation. The pipe migrates to the canonical name to avoid the per-run warning noise.
The SAFE_UPGRADE_DESCRIPTION = "pipe:safe-upgrade" marker is intentionally preserved. The RollbackAction pre-flight check searches release-history descriptions for that substring before authorising a rollback — so releases tagged by older helm-3 pipe builds remain rollback-safe under v3.0.0. You do NOT need to redeploy historical releases to keep ACTION=rollback working.
What did NOT change¶
- Chart-source URI schemes (
local://,repo://,oci://) — unchanged. ACTION=upgrade,ACTION=diff,ACTION=rollbacksemantics — unchanged.--set-string/--set-jsoninjection paths (META-01) — unchanged.--history-max,--timeout,--namespace,--create-namespacepassthrough — unchanged.- OCI registry auth via
REGISTRY_USERNAME/REGISTRY_PASSWORD— unchanged. - The
helm-diffplugin name (name: "diff") and thehelm diff upgradesubcommand the pipe invokes forACTION=diff— unchanged.
Cosign v2 → v3 — supply-chain bump¶
Breaking change
Image signing and verification use Cosign v3.1.1 (was 2.6.3). The pipe's cosign invocation surface (verify, --certificate-identity, --certificate-oidc-issuer) is identical between v2 and v3 — no consumer changes required for verifying v3.0.0+ images.
The v3 image is signed and the SBOM attestations are published with cosign 3.1.1 in the release pipeline. If you run cosign verify against v3.0.0 images, use cosign 3.x on your end for forward-compat — older cosign 2.x clients can still verify v3-signed images (the underlying Sigstore bundle format is compatible), but Sigstore's own recommendation is to track the major version.
# Same command shape, whether you run cosign 2.x or 3.x
cosign verify \
--certificate-identity-regexp '^https://github.com/yves-vogl/aws-eks-helm-deploy/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/yves-vogl/aws-eks-helm-deploy:3
Tag policy¶
Pin to :3.0.0 for production. :3 floats; :2 freezes.
The :3 rolling tag auto-updates to the latest v3.x patch. :2 stays frozen at the last helm-3 build through 2026-11-11 (Helm v3 EOL) and is sunset afterwards. :latest always points to the freshly-published release across any major and is reserved for ad-hoc inspection — never use it in CI.
v3.x consumers (new active line)¶
# bitbucket-pipelines.yml — production (patch-pinned, recommended)
image: ghcr.io/yves-vogl/aws-eks-helm-deploy:3.0.0
# bitbucket-pipelines.yml — rolling v3 major (auto-update within v3.x)
image: ghcr.io/yves-vogl/aws-eks-helm-deploy:3
v2.x consumers (frozen at the last helm-3 build until 2026-11-11)¶
The :2 tag continues to resolve to the most recent v2.x patch on GHCR through Helm v3 EOL (2026-11-11). After that date, no new images are published under :2. Pipelines that need to remain on Helm v3 until then can continue pinning to :2 (or to a specific :2.x.y patch) with no action required.
# bitbucket-pipelines.yml — staying on v2.x temporarily (until 2026-11-11)
image: ghcr.io/yves-vogl/aws-eks-helm-deploy:2
After 2026-11-11, :2 consumers should plan to either bump to :3 (recommended) or accept that they are running an unsupported helm-3 binary with no upstream security backports.
v1.x consumers (frozen indefinitely on Docker Hub)¶
Unchanged from the v2 guide — see §"Distribution change" in the v1 → v2 migration. The Docker Hub freeze at yvogl/aws-eks-helm-deploy:1.3.0 is permanent.
Verification¶
kstatus wait — observable change¶
After upgrading to v3, run a SAFE_UPGRADE=true deploy and compare the helm upgrade stderr against a v2 baseline. Differences you should expect:
- Wait-progress lines reference resources by their kstatus condition (e.g.
Reconciling,Ready) instead of the helm-3 polling messages. - Custom-resource readiness is correctly observed — if your charts include CRs with
status.conditions, the watcher now waits for them.
If your CI parses Helm stderr (e.g. for deploy-monitoring metrics), capture a v2 + v3 sample of the same chart and update parsers as needed. The pipe's own structured logs (the JSON lines on stdout) are unchanged.
Cosign verification¶
# Latest v3 image
cosign verify \
--certificate-identity-regexp '^https://github.com/yves-vogl/aws-eks-helm-deploy/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/yves-vogl/aws-eks-helm-deploy:3
# Retrieve the SPDX SBOM
cosign verify-attestation --type spdxjson \
--certificate-identity-regexp '^https://github.com/yves-vogl/aws-eks-helm-deploy/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/yves-vogl/aws-eks-helm-deploy:3
# Verify SLSA build provenance
gh attestation verify --owner yves-vogl ghcr.io/yves-vogl/aws-eks-helm-deploy:3
Quick migration checklist¶
- Pin to v3 explicitly — change the
image:in yourbitbucket-pipelines.ymlfromghcr.io/yves-vogl/aws-eks-helm-deploy:2(or:2.x.y) toghcr.io/yves-vogl/aws-eks-helm-deploy:3.0.0. The:3floating tag is also available after launch. - Run a non-production deploy first — confirm the kstatus-wait stderr output does not break any downstream log parsing or alerting you rely on.
- Widen
--timeoutif you depend on tight wait windows — kstatus polling cadence differs from the helm-3 resource-poll loop; for tightly-timed deploys, give 10-20 % more wall-clock budget during the ramp. - No env-var changes required. Specifically: do NOT change
SAFE_UPGRADE,ACTION,CHART,CHART_VERSION,RELEASE_NAME,NAMESPACE,CREATE_NAMESPACE,HISTORY_MAX,REVISION,DRY_RUN,REPO_URL,REGISTRY_USERNAME,REGISTRY_PASSWORD, OIDC settings, or anySET_*/VALUES_*settings. The v2 schema is preserved. - Historical
SAFE_UPGRADE=truereleases remain rollback-safe. Thepipe:safe-upgrademarker is preserved across the migration, soACTION=rollbackworks against releases tagged by older v2.x builds without redeployment. - Bump your local
cosignto 3.x (optional) — v2.x cosign clients still verify v3-signed images, but Sigstore recommends tracking the major. :2continues to work through 2026-11-11. If you cannot migrate immediately, the v2.x line stays available until Helm v3 EOL.
Launch timeline¶
| Date | Event |
|---|---|
| 2026-06-24 | Content freeze. PR #71 merged to main. release-please opens a Release PR for v3.0.0 — held until August 2026. |
| ~ August 2026 | v3.0.0 release PR merged → v3.0.0 tag published → :3.0.0, :3, :latest floating tags updated on GHCR. |
| 2026-11-11 | Helm v3 EOL. :2 floating tag freezes at the last published v2.x patch. New v2.x patches stop. |
| 2026-11-12 onwards | :2 consumers should bump to :3 or document an explicit accept-risk for running an unsupported helm-3 runtime. |
For the rationale behind the August soak window and the SemVer-major bump, see ADR-0010.