Skip to content

ci(stack): retry slim pickup when a merge-queued PR holds the branch - #6957

Merged
jgoux merged 3 commits into
developfrom
ci/slim-pickup-merge-queue-retry
Oct 2, 2026
Merged

jgoux merged 3 commits into
developfrom
ci/slim-pickup-merge-queue-retry

Conversation

@jgoux

@jgoux jgoux commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

slim-release-published.yml force-pushes one branch per service release line. When that branch's PR sits in the merge queue, GitHub rejects the push (GH006) and the job used to fail, dropping the planned pin until the next upstream release. On 2026-10-01 this lost edge-runtime v1.77.4-r0: the v1.77.3-r0 and v1.77.4-r0 dispatches both hit slim-bump/edge-runtime while #6930 was queued (restored by #6955).

When a push is rejected because the branch is queued for merging, the Apply step now:

  • waits for the queue to merge or drop that PR, polling isInMergeQueue for up to 30 minutes and within the app token's lifetime;
  • stops processing the current plan, so no remaining item is built from the pre-merge base;
  • re-sends the same dispatch so a fresh run re-plans from the updated default branch, at most three times in a row (tracked by a validated client_payload.replay counter).

The concurrency group now keeps every pending run (queue: max) instead of replacing the pending one, so a replay can never cancel a newer dispatch and its release-visibility wait. A failed queue lookup or dispatch, a queue that holds the branch past the deadline, an exhausted replay budget, and any other push rejection still fail the run with the manual recovery command. ADR 0026 documents the behavior.

@jgoux
jgoux requested a review from a team as a code owner October 2, 2026 09:43
@jgoux jgoux self-assigned this Oct 2, 2026

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superseded by a newer AI review

🤖 AI Review

Both independent reviews were available. Claude's single minor finding is confirmed: a persistent push rejection mentioning "merge queue" can cause unlimited redispatches that each succeed. Codex reported no findings.

Findings

Severity Location Category Sources Claim
🟡 MINOR .github/workflows/slim-release-published.yml:167 error-handling claude Any push rejection containing "merge queue" enters the hand-off path. If the first queue lookup returns false and no pending run exists, the workflow redispatches the same payload and exits successfully. A persistent rejection mentioning the merge queue can therefore retrigger the workflow indefinitely without reaching the manual-recovery failure.

Stats

Claude findings: 1 · Codex findings: 0 · Confirmed: 1 · Refuted: 0 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread .github/workflows/slim-release-published.yml Outdated

@avallete avallete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at fc02fad. The hand-off logic works, and the replay counter bounds the re-dispatch chain flagged on the earlier head. Approve-level, with non-blocking suggestions inline. The main one is concurrency.queue: max.

Dogfood

I extracted the "Apply planned updates" script verbatim and ran it under bash -eo pipefail, with git, gh, bun and pnpm stubbed and sleep fast-forwarded. The GitHub probes are read-only.

Scenario Result
Push succeeds → PR create/edit path ✅
Non-merge-queue push rejection → exit 1 with manual steps ✅
Real GH006 text, queue true→false, pending run exists → exit 0, no dispatch, remaining plan items skipped ✅
Same, no pending run, replay unset → dispatch with replay=1, all payload fields set → exit 0 ✅
replay=2 → dispatch replay=3; replay=3, 01, 1; echo x → exit 1, no dispatch ✅
Queue lookup fails / prints an unexpected value → exit 1 ✅
Queue stays true → exit 1 at the deadline (~1800 s, 61 lookups) ✅
gh run list fails / dispatch fails → exit 1 ✅
Re-dispatched payload (edge-runtime, v1.77.4, 0, v1.77.4-r0) passes validate-payload ✅

Probes against the live repo:

  • The 2026-10-01 failure (run 36844058874) rejected the push with A pull request for this branch has been added to a merge queue. Branches that are queued for merging cannot be updated., so the grep gate matches the real message.
  • The isInMergeQueue query returns exactly true for a branch that is currently queued, and false for slim-bump/edge-runtime and for a nonexistent branch.
  • gh run list --status pending plus the jq filter returns 0 when nothing is pending. Runs created before this PR have the display title slim-release-published without a service, so the match only applies to runs dispatched after it merges.
  • actionlint is clean.

Not exercised: the restricted app token (contents + pull-requests write) reading isInMergeQueue. The probes used a user token.

Suggestions

  1. concurrency.queue: max (workflow line 17, outside the diff). This is the race ADR 0026 calls non-atomic: a newer dispatch can become pending between the gh run list lookup and the re-send, and the default queue: single then cancels it in favour of the replay. The replay only plans that newer release if it is already listed. queue: max keeps up to 100 pending runs in the group and is valid with cancel-in-progress: false (see control workflow concurrency). With it, the eviction cannot happen, the pending-run lookup is only a deduplication step, and the ADR caveat can be removed. One caveat: actionlint 1.7.12 does not know the key yet.
  2. Narrower rejection match. See the inline comment.
  3. Recovery wording after the queue has cleared. See the inline comment.
  4. Comment length. See the inline comment.

Minor ADR notes:

  • The pending lookup does not see a newer run that is still requested/queued (a few seconds wide), so the window is slightly wider than "arriving between them".
  • "waits up to 30 minutes" is really the lesser of 30 minutes and the token-bound cap of about 50 minutes into the step.

Comment thread .github/workflows/slim-release-published.yml Outdated
Comment thread .github/workflows/slim-release-published.yml Outdated
Comment thread .github/workflows/slim-release-published.yml Outdated
@avallete

avallete commented Oct 2, 2026

Copy link
Copy Markdown
Member

/ai-review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Review

Both independent reviews completed and reported no findings. After reading the full changed workflow, payload validation, diff, and trusted conventions, I found no concrete defects to add.

Findings

No issues found.

Stats

Claude findings: 0 · Codex findings: 0 · Confirmed: 0 · Refuted: 0 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: manual · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

@jgoux
jgoux added this pull request to the merge queue Oct 2, 2026
Merged via the queue into develop with commit ec7ebef Oct 2, 2026
59 checks passed
@jgoux
jgoux deleted the ci/slim-pickup-merge-queue-retry branch October 2, 2026 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants