@@ -21,8 +21,6 @@ import (
2121 "errors"
2222 "fmt"
2323
24- "github.com/fluxcd/pkg/apis/meta"
25- "github.com/fluxcd/pkg/runtime/conditions"
2624 "github.com/fluxcd/pkg/ssa/jsondiff"
2725 "helm.sh/helm/v4/pkg/kube"
2826 helmreleasecommon "helm.sh/helm/v4/pkg/release/common"
@@ -147,14 +145,17 @@ func DetermineReleaseState(ctx context.Context, cfg *action.ConfigFactory, req *
147145 }
148146
149147 // Verify if postrender digest or common metadata digest has changed
150- // if config has not been processed. For the processed or partially processed generation,
151- // the updated observation will only be reflected at the end of a successful
152- // reconciliation. Comparing here would result the reconciliation to
153- // get stuck in this check due to a mismatch forever. The value can't
154- // change without a new generation. Hence, compare the observed digest
155- // for new generations only.
156- ready := conditions .Get (req .Object , meta .ReadyCondition )
157- if ready != nil && ready .ObservedGeneration != req .Object .Generation {
148+ // for new generations only. The observed digests are updated after
149+ // each successful release action, so comparing here will not cause
150+ // an infinite loop within the same reconciliation.
151+ //
152+ // We use the top-level status.observedGeneration rather than the
153+ // Ready condition's ObservedGeneration, because the latter can be
154+ // inadvertently advanced by the patch helper's conflict resolution
155+ // (patchStatusConditions re-fetches the object from the API server,
156+ // and conditions.Set always sets ObservedGeneration to the latest
157+ // metadata.generation).
158+ if req .Object .Status .ObservedGeneration != req .Object .Generation {
158159 var postrenderersDigest string
159160 if req .Object .Spec .PostRenderers != nil {
160161 postrenderersDigest = postrender .Digest (digest .Canonical , req .Object .Spec .PostRenderers ).String ()
0 commit comments