Skip to content

Filter PromotionStrategy watch events for DependentsSuccessfulCommitStatus reconciler #2011

Description

@crenshaw-dev

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions