Skip to content

ci(automerge): add reusable fleet automerge workflow with self-aware readiness - #17

Merged
github-actions[bot] merged 1 commit into
mainfrom
ci/reusable-automerge
Sep 23, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
ci/reusable-automerge

Conversation

@cmarko89

Copy link
Copy Markdown
Contributor

Summary

Adds .github/workflows/reusable-automerge.yml, the single fleet implementation of PR auto-merge, and converts this repo's automerge.yml into a thin caller (local path, so changes here self-test on their own PR).

Why

13 repos carried hand-copied automerge.yml files that had drifted into 5 variants with 3 different readiness rules. On repos that gate on CLEAN only, a draft marked ready after its checks went green strands open forever. The running automerge job is itself a non-required check, so the PR reads UNSTABLE for that run's whole life, native auto-merge is refused ("unstable status"), and no later event fires. This stranded Emkraan/apollo#1037 on 2026-09-22.

Readiness rule

Ready = CLEAN, or UNSTABLE where every non-green check on the head commit belongs to the automerge workflow itself (matched by workflow name or run id, so two concurrent automerge runs on one SHA do not wait on each other). A red or pending non-required check still blocks. An unreadable check rollup fails closed. The rollup is read with GITHUB_TOKEN, since the deploy-bot App token cannot read checks.

Kept from the existing variants

  • Deploy-bot App token as the merging identity when configured, with GITHUB_TOKEN retry (the App cannot merge .github/workflows/** changes)
  • Merge-queue repos: enqueuePullRequest when ready
  • Direct mergePullRequest with expectedHeadOid; poll-and-merge on the "clean status" auto-merge race
  • workflow_run head-SHA matching when pull_requests is empty
  • Closing linked issues on merge (GitHub skips this for bot merges)
  • Paginated schedule/dispatch sweep of open non-draft PRs

Verification

  • The script run under Node with a mocked GitHub API across 16 scenarios, including the #1037 case, concurrent automerge runs, a failing non-required check, a failing commit status, an unreadable rollup, merge queue, an App-refused workflow-file merge, the clean-status race, DIRTY, linked-issue close, sweep, head-SHA fallback and GITHUB_TOKEN-only.
  • The PR and rollup GraphQL queries validated read-only against the live API.
  • Live: this PR opens as a draft and is marked ready after CI is green, the exact #1037 path. It should self-merge.

Rollout

After merge, each fleet repo's automerge.yml is replaced by a thin caller pinned to @main (the existing ha-shared-workflows precedent). The Apollo standard update (github-repo-standard.md S8 and fleet-compliance.py S8-automerge) lands alongside.

…readiness

One implementation replaces 13 hand-copied automerge.yml variants that had drifted into 3 readiness rules. A PR is ready when CLEAN, or UNSTABLE where every non-green check belongs to the automerge workflow itself: the running automerge job pins the PR UNSTABLE, so gating on CLEAN alone stranded readied drafts (apollo#1037). Non-required red checks still block. Adds the app-token-with-GITHUB_TOKEN-fallback identity, merge-queue enqueue, head_sha matching, linked-issue closing, expectedHeadOid merges and the paginated sweep. This repo's own caller uses the local path so changes self-test.
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.

1 participant