Problem
In 0.38, DependentsSuccessfulCommitStatusReconciler watches PromotionStrategy without a predicate:
Watches(&promoterv1alpha1.PromotionStrategy{}, r.enqueueDependentsSuccessfulCommitStatusForPromotionStrategy()).
Every PromotionStrategy informer event enqueues matching DSCS resources — including status-only updates that do not affect gate evaluation (Ready condition changes, observedGeneration, instanceID, environment history, etc.).
In practice, most DSCS reconciles are no-ops: every environment has active.dry.sha == proposed.dry.sha, so the controller skips CommitStatus writes and only refreshes status.environments. Those reconciles still perform a PS Get, DAG walk, and DSCS status SSA patch.
This adds significant reconcile volume on busy clusters where PromotionStrategy status changes frequently (e.g. from the existing CTP → PS feedback via Owns(ChangeTransferPolicy)).
Impact
- High DSCS reconcile count driven by PS status churn, mostly no-op work.
- Controller contention (CPU, API server) that can inflate reconcile durations for other controllers in the same process.
- Not a cross-controller cascade: no-op DSCS reconciles do not write CommitStatus resources and nothing watches DSCS, so they do not directly re-queue PromotionStrategy or ChangeTransferPolicy. The PS ↔ CTP loop remains the primary driver of PS/CTP reconcile frequency.
Proposal
Add a field-selective predicate on the PromotionStrategy watch, similar to existing patterns in the codebase:
applicationPredicate on Argo CD Application watches (only health/sync/revision changes)
promotionStrategyCreatePredicate on ArgoCDCommitStatus (create-only — DSCS needs updates, but not all of them)
Enqueue DSCS when gate-relevant PromotionStrategy state changes:
Spec
spec.environments (affects inferred linear DAG when DSCS spec.environments is omitted)
Status (per environment)
branch
active.dry.sha, active.dry.commitTime
proposed.dry.sha, proposed.hydrated.sha
proposed.note.drySha (used by getEffectiveHydratedDrySha)
active.commitStatuses[].key and .phase (upstream health via checkCommitStatusesPassing)
Always enqueue on PromotionStrategy create and delete.
Sketch
Watches(
&promoterv1alpha1.PromotionStrategy{},
r.enqueueDependentsSuccessfulCommitStatusForPromotionStrategy(),
builder.WithPredicates(promotionStrategyGateRelevantPredicate()),
)
The predicate UpdateFunc should compare a gate-relevant projection of old vs new status.environments (and spec.environments), not raw object equality.
Testing
- Unit tests for the predicate: ignore Ready/history-only status changes; allow SHA, note, and commit-status phase transitions.
- Controller test: PS status patch that does not change gate-relevant fields does not enqueue DSCS; upstream health phase flip does enqueue.
Related code
internal/controller/dependentssuccessfulcommitstatus_controller.go — SetupWithManager, updateDependentsSuccessfulCommitStatus, isUpstreamPending
internal/controller/argocdcommitstatus_controller.go — applicationPredicate, promotionStrategyCreatePredicate as precedents
Problem
In 0.38,
DependentsSuccessfulCommitStatusReconcilerwatchesPromotionStrategywithout a predicate:Every PromotionStrategy informer event enqueues matching DSCS resources — including status-only updates that do not affect gate evaluation (Ready condition changes,
observedGeneration,instanceID, environmenthistory, etc.).In practice, most DSCS reconciles are no-ops: every environment has
active.dry.sha == proposed.dry.sha, so the controller skips CommitStatus writes and only refreshesstatus.environments. Those reconciles still perform a PSGet, DAG walk, and DSCS status SSA patch.This adds significant reconcile volume on busy clusters where PromotionStrategy status changes frequently (e.g. from the existing CTP → PS feedback via
Owns(ChangeTransferPolicy)).Impact
Proposal
Add a field-selective predicate on the PromotionStrategy watch, similar to existing patterns in the codebase:
applicationPredicateon Argo CD Application watches (only health/sync/revision changes)promotionStrategyCreatePredicateon ArgoCDCommitStatus (create-only — DSCS needs updates, but not all of them)Enqueue DSCS when gate-relevant PromotionStrategy state changes:
Spec
spec.environments(affects inferred linear DAG when DSCSspec.environmentsis omitted)Status (per environment)
branchactive.dry.sha,active.dry.commitTimeproposed.dry.sha,proposed.hydrated.shaproposed.note.drySha(used bygetEffectiveHydratedDrySha)active.commitStatuses[].keyand.phase(upstream health viacheckCommitStatusesPassing)Always enqueue on PromotionStrategy create and delete.
Sketch
The predicate
UpdateFuncshould compare a gate-relevant projection of old vs newstatus.environments(andspec.environments), not raw object equality.Testing
Related code
internal/controller/dependentssuccessfulcommitstatus_controller.go—SetupWithManager,updateDependentsSuccessfulCommitStatus,isUpstreamPendinginternal/controller/argocdcommitstatus_controller.go—applicationPredicate,promotionStrategyCreatePredicateas precedents