feat(deployer): terminate only a proven-stale Argo CD operation (v7) #171

Merged
binjovi-bot merged 1 commit from feat/argocd-deployer-proven-stale into trunk 2026-09-02 13:24:57 +00:00
Owner

Why

builder-images binjovi-argocd-deployer v6 (ef1d828, live in Binjovi) terminates every Running Argo CD operation whose revision is not the released one. Binjovi supersedes an older deployment request when a newer one starts, but the older deployer pod keeps polling until its timeout (no Workflow deletion on supersede). So the v6 observer of release N can terminate the operation of release N+1. Argo CD never retries a terminated revision, so release N+1 then fails and rolls back. The registry v0.1.8 -> v0.1.9 sequence on 2026-09-02 had exactly this shape (two releases minutes apart).

What (v7)

  • superseded_revision: an operation is stale only when its revision is a proven ancestor of the released revision in the deployer's clone of main (git merge-base --is-ancestor). A symbolic ref, an unknown commit, and a descendant of the release are left alone.
  • terminate_operation: the merge patch carries the snapshot resourceVersion. A 409 Conflict is logged and repeated on the next poll; Forbidden stays fatal.
  • Failed-operation count matches on syncResult.revision OR operationState.operation.sync.revision.
  • Guard runs the deployer under a stub PATH (fake kubectl + git wrapper answering only rev-parse/merge-base) against a fixture clone: exactly 4 patches (stale-running/conflict/fallback/short), none for released/symbolic/newer/unknown/terminating/succeeded/no-revision/unwatched; Forbidden must be fatal. VERSION 7.

Supersedes PR 170 (closed; it predates v6 on trunk).

After release

Bump manifests/workload.yaml in binjovi to registry.sean.farm/build/binjovi-argocd-deployer:v7@sha256:<digest> and release binjovi.

https://claude.ai/code/session_01LeVatedQ4sCA1u6LHjo7B5

## Why builder-images `binjovi-argocd-deployer` v6 (ef1d828, live in Binjovi) terminates every Running Argo CD operation whose revision is not the released one. Binjovi supersedes an older deployment request when a newer one starts, but the older deployer pod keeps polling until its timeout (no Workflow deletion on supersede). So the v6 observer of release N can terminate the operation of release N+1. Argo CD never retries a terminated revision, so release N+1 then fails and rolls back. The registry v0.1.8 -> v0.1.9 sequence on 2026-09-02 had exactly this shape (two releases minutes apart). ## What (v7) - `superseded_revision`: an operation is stale only when its revision is a proven ancestor of the released revision in the deployer's clone of `main` (`git merge-base --is-ancestor`). A symbolic ref, an unknown commit, and a descendant of the release are left alone. - `terminate_operation`: the merge patch carries the snapshot `resourceVersion`. A 409 Conflict is logged and repeated on the next poll; Forbidden stays fatal. - Failed-operation count matches on `syncResult.revision` OR `operationState.operation.sync.revision`. - Guard runs the deployer under a stub PATH (fake kubectl + git wrapper answering only rev-parse/merge-base) against a fixture clone: exactly 4 patches (stale-running/conflict/fallback/short), none for released/symbolic/newer/unknown/terminating/succeeded/no-revision/unwatched; Forbidden must be fatal. VERSION 7. Supersedes PR 170 (closed; it predates v6 on trunk). ## After release Bump `manifests/workload.yaml` in binjovi to `registry.sean.farm/build/binjovi-argocd-deployer:v7@sha256:<digest>` and release binjovi. https://claude.ai/code/session_01LeVatedQ4sCA1u6LHjo7B5
feat(deployer): terminate only a proven-stale Argo CD operation
All checks were successful
binjovi/ci Binjovi completed the frozen plan
eb9dd12764
binjovi-argocd-deployer v7. Trunk v6 terminates every Running operation
whose revision is not the released one. Binjovi supersedes an older
deployment request when a newer one starts, but the older deployer pod
keeps polling until its timeout, so v6 can terminate the operation of
the NEWER release. Argo CD never retries a terminated revision, so that
newer release then fails and rolls back. The registry v0.1.8 -> v0.1.9
sequence on 2026-09-02 had exactly this shape.

v7 terminates an operation only when its revision is a proven ancestor
of the released revision in the deployer's clone of main
(git merge-base --is-ancestor). A symbolic ref, an unknown commit and
a descendant of the release are not stale; nothing touches them.

The terminate patch carries the resourceVersion of the snapshot. A
Conflict (409) is not fatal: the next poll takes a new snapshot and
repeats the request. A Forbidden answer stays fatal.

The failed-operation count accepts a match on syncResult.revision or
on operationState.operation.sync.revision, so a terminated or failed
operation is counted whichever field carries the resolved commit.

scripts/check-binjovi-argocd-deployer.sh runs the deployer under a stub
PATH (fake kubectl and a git wrapper that only answers rev-parse and
merge-base) against a fixture clone. It asserts one patch for each of
stale-running, stale-conflict, stale-fallback and stale-short, and no
patch for released, symbolic, newer, unknown, already-terminating,
succeeded, no-revision or unwatched applications. A Forbidden answer
must be fatal.

Claude-Session: https://claude.ai/code/session_01LeVatedQ4sCA1u6LHjo7B5
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
sean/builder-images!171
No description provided.