safeMoveDeps reads the destination charts/ directory and then moves
in new charts and deletes ones missing from that snapshot. Separate
Manager instances calling downloadAll concurrently against the same
ChartPath can race on this read-then-write, e.g. one call's freshly
moved-in chart being deleted by another call's "delete outdated
charts" pass because it wasn't in that call's earlier snapshot.
Signed-off-by: Anis Khan <2815766+aniskhan001@users.noreply.github.com>
Manager.downloadAll derives its scratch directory as tmpcharts-<pid>
(added in #13120 to fix#13110, a race between separate helm process
invocations sharing a chart directory). That fix does not cover the
case where downloadAll is called concurrently by multiple goroutines
within a single process - e.g. a caller embedding Helm as a library
that renders several profiles against the same chart path in parallel
(this is how Skaffold's built-in Helm renderer works). All such calls
share one PID, so they still resolve to the same tmpcharts-<pid> path
and race on it: one goroutine's deferred os.RemoveAll can delete the
directory out from under another goroutine's in-flight download,
surfacing as:
lstat .../tmpcharts-<pid>: no such file or directory
Switch to os.MkdirTemp, which atomically allocates a directory with a
guaranteed-unique name, while keeping the PID as a prefix for
debuggability. Adds TestDownloadAllConcurrent, which reproduces the
race under -race with the old code and passes reliably with the fix.
Fixes#32532
Signed-off-by: Anis Khan <2815766+aniskhan001@users.noreply.github.com>
TestInstallRelease_Wait_Interrupted and
TestInstallRelease_RollbackOnFailure_Interrupted assert that the detached
installation goroutine has exited by sleeping a fixed 10s -- exactly the
FailingKubeClient WaitDuration the goroutine blocks on. Sleeping the same
duration the goroutine takes is a zero-margin race: if the goroutine
finishes a hair after the fixed sleep elapses (scheduler jitter under load),
getGoroutineCount() has not decremented yet and the assertion flakes.
Replace the fixed sleep + point-in-time assert with is.Eventually polling
getGoroutineCount() (30s ceiling, 10ms tick). It returns as soon as the
goroutine has actually finished and no longer races the exact wait
duration. Test-only; no change to install behavior.
Signed-off-by: Nikolaus Schuetz <nikolauspschuetz@gmail.com>
If the CLI-side description validation is removed, the unicode/utf8 import becomes unused and should also be dropped.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: MrJack <36191829+biagiopietro@users.noreply.github.com>
Move description length validation to the beginning of Run(), before
IsReachable(), so programmatic callers get an immediate validation
error instead of a potentially misleading cluster reachability failure.
Signed-off-by: MrJack <36191829+biagiopietro@users.noreply.github.com>
Remove duplicate rollback-with-description.txt fixture that had
identical content to rollback.txt.
Signed-off-by: MrJack <36191829+biagiopietro@users.noreply.github.com>
Add a new --description flag to the helm rollback command that allows
users to specify a custom description explaining why the rollback was
performed. This description is stored in the release metadata.
Changes:
- Add Description field to the Rollback action struct
- Add --description flag to the rollback CLI command
- Add 512 character limit validation for the description
- Default to 'Rollback to <version>' when no description is provided
The description flag is optional and follows the same pattern used by
the install and upgrade commands.
Closes #XXXX
Signed-off-by: MrJack <36191829+biagiopietro@users.noreply.github.com>