- only cache kube client when creation succeeds
- add regression test for two failed reachability checks
Signed-off-by: Mohammad Abdolirad <m.abdolirad@gmail.com>
* fix: protect FailingKubeClient.RecordedWaitOptions from concurrent access
Add a sync.Mutex to guard the append to RecordedWaitOptions in
GetWaiterWithOptions, fixing a data race detected by -race when
concurrent goroutines (e.g. upgrade + rollback) both call
GetWaiterWithOptions on the same FailingKubeClient instance.
Fixes race failures in TestUpgradeRelease_Interrupted_RollbackOnFailure
and TestInstallRelease_RollbackOnFailure_Interrupted.
Signed-off-by: Terry Howe <thowe@nvidia.com>
* fix: extract appendRecordedWaitOptionsLocked helper with defer unlock
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
---------
Signed-off-by: Terry Howe <thowe@nvidia.com>
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Commands like 'helm registry login', 'helm push', and 'helm pull' were
writing success messages ("Login Succeeded", "Pushed:", "Pulled:",
"Digest:") to stderr instead of stdout. The root cause was that
newDefaultRegistryClient and newRegistryClientWithTLS hard-coded
os.Stderr as the registry client writer, ignoring the out io.Writer
that main() passes as os.Stdout.
Thread out io.Writer through newRegistryClient, newDefaultRegistryClient,
and newRegistryClientWithTLS, and update all call sites in pkg/cmd.
Fixes#13464
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
When lookup cannot find the requested resource (apierrors.IsNotFound),
add slog.Debug() calls with structured fields (apiVersion, kind,
namespace, name) so that users running helm template --debug can see
why lookup returned an empty map instead of silently swallowing the
not-found result.
Fixes: https://github.com/helm/helm/issues/32101
Signed-off-by: Ogulcan Aydogan <ogulcanaydogan@hotmail.com>
Return the actual error from io.Copy in Digest() instead of nil.
The previous code swallowed the error and returned an empty string
as a valid SHA-256 digest, which could silently break chart
provenance verification.
Also fix encodeRelease() in pkg/storage/driver/util.go:
- Close the gzip writer on the w.Write() error path to avoid
leaking resources.
- Check the error return from gzip.Writer.Close(), which flushes
remaining compressed data and can fail.
Assisted-by: Grok/xAI
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Before this change, hooks with `helm.sh/hook: test` but Kind != Pod
(ConfigMap, Secret, ...) led to `helm test --logs` fail with
`unable to get pod <name>`.
Signed-off-by: Gregory Man <man.gregory@gmail.com>
slog.Error on line 157 passes printf-style positional args (%q, %s)
instead of key-value pairs. The slog API treats these as unkeyed
attributes, producing garbled log output.
Two nearby slog.Warn calls wrap fmt.Sprintf unnecessarily. Convert
all three calls to use proper structured key-value arguments.
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Assisted-by: Grok/grok-4
- Distinguish unowned resources from those whose ownership could not be
verified (e.g. RBAC/network errors). Unverifiable resources are now
returned in a separate list with the underlying error so log output
and the "kept" summary describe what actually happened.
- Only prefix the kept summary with the resource-policy header when
there are policy-kept resources, so users with only ownership-skipped
resources don't see a misleading header.
- Update verifyOwnershipBeforeDelete doc comment to reflect that
not-found resources are excluded from all returned lists.
- Assert success of Releases.Create in uninstall tests so fixture
setup failures are surfaced immediately.
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
- Close log stream after reading (prevents connection/fd leak)
- Strengthen tests to assert on output headers rather than error paths
- Remove unused import
Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
When a test pod contains multiple containers (e.g. Istio/Consul/Vault
sidecars), 'helm test --logs' failed with 'a container name must be
specified'. This happened because GetPodLogs called the Kubernetes log
API without specifying a container name.
The fix fetches the pod spec first, then iterates over all containers
(init containers + regular containers) and requests logs for each one
explicitly. Errors from individual containers are collected and returned
together via errors.Join rather than aborting on the first failure.
Also fixes a typo: hooksByWight -> hooksByWeight.
Closes#6902
Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
Helm now requires Go 1.26 (#32078); the cloner[T] type-assertion fallback
in transport.go was a defensive shim for Go versions before
http.Transport.Clone() existed. The fallback path is unreachable on
supported Go versions.
Refs: #31386
Signed-off-by: Ogulcan Aydogan <ogulcanaydogan@hotmail.com>
The previous change suppressed ctx.Err() whenever there were no
resource-specific errors, which incorrectly swallowed context.Canceled
and other non-deadline errors signalling an external interruption.
Refine the condition: only suppress context.DeadlineExceeded when there
are no resource-specific errors (resources are Unknown/NotFound, meaning
the delete wait succeeded or resources were already gone). Any other
context error — including context.Canceled — is always propagated.
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
During informer initialization there is a brief window where watched
resources appear as Unknown before their real statuses are delivered.
The statusObserver skips Unknown resources when waiting for deletion
(they may have been deleted before the watch started), but if *all*
resources are in that transient Unknown state the skipped-resource list
is empty. AggregateStatus on an empty slice returns the desired status,
causing cancel() to be called immediately — before any real status event
has arrived.
Guard against this by tracking the count of Unknown-skipped resources.
When every resource was Unknown-skipped and none have a definitive status
yet, defer the early-cancel decision until at least one resource reports
a real status. This preserves the correct behaviour for resources that
were genuinely deleted before the watch started (they eventually receive
a NotFound or stay Unknown, and the aggregate succeeds), while fixing
the race for resources that are transiently Unknown at startup.
Also tighten the ctx.Err() check in waitForDelete: only append a
deadline error when there are resource-specific errors to accompany it.
A timeout while all resources are Unknown or NotFound is not itself an
error — the resources are in an acceptable state for a delete wait.
Fixes: TestStatusWaitForDelete/error_when_not_all_objects_are_deleted
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
`isVersionRange` checked for `x`/`X` across the entire version
string, misclassifying exact versions like `1.0.0-fix`,
`2.0.0-next`, or `1.0.0+exp` as ranges.
Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
From Matt's comment
> The check for " || " should remove the spaces and have "||". Spaces around the || aren't required.
Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
When using version ranges like ^1 or ~1.10, Helm incorrectly showed
warnings about falling back to closest version. Only show the warning
when an exact version is requested but not found.
Fixes: https://github.com/helm/helm/issues/31757
Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
Only user-supplied nils should survive coalescing. Chart-default nils
defaults, not just user overrides. This caused:
- %!s(<nil>) in templates using Bitnami common.secrets.key (#31919)
- pluck fallbacks returning nil instead of falling through to globals
(#31971)
Fixes#31919Fixes#31971
Signed-off-by: Johannes Lohmer <jojo.dev@lohmer.com>
Three test cases that cover the regression scenarios introduced
by the #31644 nil preservation fix:
- subchart default nils should be cleaned up
when parent doesn't set those keys (#31919)
- user-supplied null should erase subchart defaults (#31919)
- subchart default nil should not shadow global values via pluck (#31971)
Tests are expected to fail until the regression is fixed.
Signed-off-by: Johannes Lohmer <jojo.dev@lohmer.com>
When running 'helm pull --debug', no debug output was printed because
the HTTP getter did not emit any slog.Debug messages. This adds
slog.Debug calls to log the URL being fetched and the response status
when debug-level logging is enabled.
Fixeshelm/helm#31098
Signed-off-by: Cairon <cairon-ab@users.noreply.github.com>
Move implementation to pkg/kubeenv per review; kube.RetryingRoundTripper
remains a type alias for API compatibility. pkg/cli uses kubeenv only.
Signed-off-by: Sumit Solanki <sumit.solanki@ibm.com>
The previous fix (increasing timeout / reducing deletion delay) did not
work because the flakiness is not a timing problem at all.
Root cause: fluxcd/cli-utils HasSynced() returns true after the initial
list item is *popped* from DeltaFIFO, which is before AddFunc delivers
the ResourceUpdateEvent to the collector. This creates a race where the
SyncEvent can arrive at the statusObserver *before* the pod's Current
status is recorded. When that happens:
- statusObserver sees pod as Unknown
- Unknown is skipped for WaitForDelete (by design, to handle resources
that were already deleted before watching started)
- AggregateStatus([], NotFoundStatus) == NotFoundStatus → cancel()
- The watch context is cancelled before DeleteFunc can fire
- Final check: pod still Current → error
The test intent is to verify that waitForDeleteCtx (not the cancelled
generalCtx) is selected. A non-existent resource satisfies this:
- With waitForDeleteCtx=Background(): informer syncs with empty list
→ Unknown → cancel → success ✓
- With generalCtx (cancelled, wrong): context immediately done
→ ctx.Err() appended → error returned ✓
Remove the goroutine-based deletion and the pod creation to eliminate
the race while preserving the context-selection assertion.
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
TestMethodContextOverridesGeneralContext/WaitForDelete used a 1s
timeout with a 500ms deletion delay, leaving only ~500ms for the
fake watcher to propagate the delete event. On loaded CI runners
this window is too tight and causes intermittent failures.
Increase the timeout to 5s and reduce the deletion delay to 100ms
so there is ample headroom. Apply the same deletion-delay reduction
to TestStatusWaitForDelete which shares the same pattern.
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
When Deployed() succeeds but releaserToV1Release() fails, prepareUpgrade
returned err (nil) instead of cerr (the conversion error), causing a
silent nil return that could lead to nil pointer dereferences downstream.
Closes#32007
Signed-off-by: Rhys McNeill <rhysmcneill7@hotmail.co.uk>
Move the retrying HTTP round-tripper used by EnvSettings into pkg/cli so
pkg/cli no longer imports pkg/kube, avoiding import cycles for Helm
library consumers while preserving retry behavior for transient API
server errors.
Add pkg/cli/roundtripper_test.go with parity coverage for the moved logic.
Signed-off-by: Sumit Solanki <sumit.solanki@ibm.com>
Made-with: Cursor
Move the retrying round tripper used by EnvSettings into pkg/cli so
pkg/cli no longer imports pkg/kube. This preserves retry behavior while
breaking the import edge that triggers cycles for Helm library consumers
(such as the kustomize integration described in #31965).
Signed-off-by: Sumit Solanki <sumit.solanki@ibm.com>
The toTOML doc comment said "returns empty string on marshal error"
but the implementation actually returns err.Error(). Fix the comment
to match the real behavior. Also mention mustToToml as the strict
alternative.
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Add `mustToToml` that panics on marshal error, consistent with
`mustToYaml` and `mustToJson`. This makes it possible for chart authors
to get a hard failure when TOML serialization fails, rather than having
to inspect the output manually.
`toToml` behavior is unchanged in this commit.
Closes#31430
Signed-off-by: Ilya Kiselev <kis-ilya-a@yandex.ru>
Remove pre-Go modules import path comments from pkg/kube test files
(ready_test.go, resource_test.go, statuswait_test.go) for consistency
with the rest of the package.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Import path comments (e.g. `// import "helm.sh/helm/v4/pkg/kube"`) are
a pre-Go modules convention no longer needed in module-aware builds.
Some files in pkg/kube had these comments while others did not, causing
inconsistency that triggered downstream Kythe indexing errors.
Remove the import comments from all affected files to make the package
declaration consistent across the directory.
Fixes#31846
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: abhay1999 <abhaychaurasiya19@gmail.com>
- Clarify --show-rollback flag help text to specify it only affects table output
- Add RollbackRevision JSON round-trip tests for pkg/release/v1 and internal/release/v2
- Add omitempty behavior verification for zero rollback_revision
Signed-off-by: MrJack <36191829+biagiopietro@users.noreply.github.com>
Replace the always-visible ROLLBACK column with an opt-in --show-rollback
flag to avoid breaking the default table output (HIP-0004). JSON and YAML
formats continue to include rollback_revision when present via omitempty.
Signed-off-by: MrJack <36191829+biagiopietro@users.noreply.github.com>
The import comment in pkg/kube/statuswait.go still referenced
helm.sh/helm/v3/pkg/kube while all other files in the package
correctly reference helm.sh/helm/v4/pkg/kube. This mismatch
causes downstream processing errors (e.g. kythe) when vendoring
Helm.
Fixes#31846
Signed-off-by: rohansood10 <rohansood10@users.noreply.github.com>
Introduce release/v2 that mirrors pkg/release/v1 but uses *v3.Chart
from internal/chart/v3. The code is structurally identical to v1 with
only import paths changed to reference internal/chart/v3 instead of
pkg/chart/v2.
- Add internal/release/v2 with Release, Info, Hook types
- Add internal/release/v2/util with filter, sorter, manifest utilities
- Update pkg/release/common.go with v2Accessor and v2HookAccessor
- Copy all test files from pkg/release/v1 and add a v2 test in common_test.go
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
When multiple processes try to download the same chart version
concurrently (e.g., via Terraform), they can race to write the
destination file. On Windows, this results in 'Access Denied'
errors because the file cannot be renamed while another process
has a handle to the destination.
This commit introduces 'PlatformAtomicWriteFile' to the fileutil
package. On Unix-like systems, it simply delegates to AtomicWriteFile,
maintaining existing behavior. On Windows, it coordinates writes using
a lock file (.lock). It acquires the lock, then performs the atomic
write.
Crucially, this implementation ensures that existing files are
overwritten (rather than skipped). This ensures that if a chart is
republished with the same version, the local cache is correctly updated,
preventing stale data issues.
Fixes#31633
Signed-off-by: Orgad Shaneh <orgad.shaneh@audiocodes.com>
* feat(create): add hidden --chart-api-version flag
Add --chart-api-version flag to helm create command to allow selecting
chart API version (v2 or v3) when creating a new chart.
- Default is v2 (existing behavior unchanged)
- v3 uses internal/chart/v3 scaffold generator
- Invalid versions return clear error message
- Works with --starter flag
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
* Add HELM_EXPERIMENTAL_CHART_V3 feature gate to create command
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
* make chartv3 private and use loader to load the chart
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
* Hide chart-api-version flag until chart v3 is officially released
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
* Conditionally hide the --chart-api-version flag if chart v3 is not enabled
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
* Add internal gates package for internal feature gates
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
* Add doc for internal/gates package
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
---------
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
The --hide-notes and --render-subchart-notes flags have no effect for
`helm template` since template output never includes notes. Mark these
flags as deprecated and hide them from help output.
The flags are preserved for backwards compatibility in Helm 4 and will
be removed in Helm 5.
Fixes#31752
Signed-off-by: Scott Rigby <scott@r6by.com>
Improve the description to explain the three usage scenarios:
- --wait alone defaults to 'watcher' strategy
- --wait=<value> uses the specified strategy
- flag omitted defaults to 'hookOnly'
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
Signed-off-by: Manuel Alonso Gonzalez <434575+manute@users.noreply.github.com>
Signed-off-by: Manuel Alonso Gonzalez <m.alonso@Manuels-MacBook-Pro.local>
The --api-versions flag was undocumented in the template command's
help text. This adds usage documentation and examples showing both
comma-separated and multiple flag usage patterns.
Fixes#13198
Signed-off-by: majiayu000 <1835304752@qq.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: majiayu000 <1835304752@qq.com>
Tests were failing for cli-utils watcher because upstream k8s made
changes that impacted cli-utils. In k8s WatchListClient is now
enabled by default. Fake clients used for testing don't know this
semantic. cli-utils leverages reflection in k8s to handle this.
The Helm tests didn't handle this well.
The tests are updated to use PrependReactor and PrependWatchReactor
in the same way that cli-utils does for testing. This works without
wrapping the client.
Signed-off-by: Matt Farina <matt.farina@suse.com>