// ForcePending overrides the pessimistic lock that a pending-install/upgrade/rollback
// revision holds, marking that revision as failed before proceeding. It exists to recover
// releases left stuck by an abruptly terminated Helm process (SIGKILL, CI runner death).
//
// This is a disaster-recovery escape hatch: if another Helm process really is still
// operating on the release, using this causes concurrent writes and corrupt history.
ForcePendingbool
// ServerSideApply enables changes to be applied via Kubernetes server-side apply
// Can be the string: "true", "false" or "auto"
// When "auto", sever-side usage will be based upon the releases previous usage
@ -245,7 +252,31 @@ func (u *Upgrade) prepareUpgrade(ctx context.Context, name string, chart *chartv
// Concurrent `helm upgrade`s will either fail here with `errPending` or when creating the release with "already exists". This should act as a pessimistic lock.
iflastRelease.Info.Status.IsPending(){
returnnil,nil,false,errPending
if!u.ForcePending{
returnnil,nil,false,errPending
}
// The operator explicitly asked to break the lock. Record the stuck revision as
// failed so it stops blocking and `helm history` shows why it was superseded.
// Mutating the in-memory copy also lets the currentRelease lookup below fall back
// to it when there is no deployed revision (a stuck pending-install).
wasStatus:=lastRelease.Info.Status
u.cfg.Logger().Warn("Overriding a pending release. If another Helm process is still operating on this release, its history may be corrupted.",
f.BoolVar(&client.ForceConflicts,"force-conflicts",false,"if set server-side apply will force changes against conflicts")
f.BoolVar(&client.ForcePending,"force-pending",false,"force the upgrade when the previous release is stuck in a pending-* status, marking it failed first. Disaster recovery only: risks a split-brain deployment if another Helm process is still running")
f.StringVar(&client.ServerSideApply,"server-side","auto","must be \"true\", \"false\" or \"auto\". Object updates run in the server instead of the client (\"auto\" defaults the value from the previous chart release's method)")
f.BoolVar(&client.DisableOpenAPIValidation,"disable-openapi-validation",false,"if set, the upgrade process will not validate rendered templates against the Kubernetes OpenAPI Schema")