From d5caaac2199d1bd2d0b1f7b52737a258d089b11e Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Mon, 27 Apr 2026 06:38:57 -0700 Subject: [PATCH] feat(reusable): disable auto-merge when a new commit is pushed (#10) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reusable workflow that consumers call from their pr-guards.yml on pull_request:synchronize. When a new commit is pushed to an open PR that has auto-merge enabled, this disables auto-merge and posts a comment so the operator must explicitly re-engage after verifying. Background: on 2026-04-27, PR #2174 in molecule-core auto-merged with only the first commit because the second commit was pushed AFTER the merge queue had locked the PR's SHA. The second commit ended up orphaned on a merged-and-deleted branch (the wider "automatically delete head branches" repo setting now blocks the push entirely; this workflow catches the race window where the PR is queued but not yet merged). Defense in depth — if both fixes are active: 1. Repo setting "delete branch on merge" prevents pushes to a merged branch (post-merge orphan case). 2. This workflow catches in-queue races (push lands while the queue is processing) by force-disabling auto-merge so the operator must re-engage explicitly. Together they cover the full lifecycle of "auto-merge enabled → new commits arrive" without relying on operator discipline. Co-authored-by: Claude Opus 4.7 (1M context) --- .../workflows/disable-auto-merge-on-push.yml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/disable-auto-merge-on-push.yml diff --git a/.github/workflows/disable-auto-merge-on-push.yml b/.github/workflows/disable-auto-merge-on-push.yml new file mode 100644 index 0000000..312128e --- /dev/null +++ b/.github/workflows/disable-auto-merge-on-push.yml @@ -0,0 +1,53 @@ +name: Disable auto-merge on push + +# Reusable guard against the "I enabled auto-merge then pushed more +# commits" race. Background: on 2026-04-27, PR #2174 in molecule-core +# auto-merged with only the first commit because the second commit +# was pushed AFTER the merge queue had already locked the PR's SHA. +# The second commit ended up orphaned on a merged-and-deleted branch. +# +# Mechanism: on every `pull_request: synchronize` event (= new commit +# pushed to an open PR), check if auto-merge is enabled. If yes, +# disable it and post a comment. This forces the operator to +# re-engage `gh pr merge --auto` after the new push, with the +# re-engagement acting as the verification step. +# +# Call from each repo's .github/workflows/ via a thin wrapper: +# +# name: pr-guards +# on: +# pull_request: +# types: [synchronize] +# permissions: +# pull-requests: write +# jobs: +# disable-auto-merge-on-push: +# uses: Molecule-AI/molecule-ci/.github/workflows/disable-auto-merge-on-push.yml@main +# +# False-positive behavior: if a CI bot pushes (e.g. dependency-update +# rebase, secret rotation), this also disables auto-merge for that +# PR. That's acceptable — the operator who originally enabled +# auto-merge gets notified and re-engages, which is exactly the +# verify-after-machine-edits behavior we want. + +on: + workflow_call: + +jobs: + guard: + name: Disable auto-merge on push + runs-on: ubuntu-latest + if: github.event.pull_request.auto_merge != null + permissions: + pull-requests: write + steps: + - name: Disable auto-merge + env: + GH_TOKEN: ${{ github.token }} + PR: ${{ github.event.pull_request.number }} + REPO: ${{ github.repository }} + NEW_SHA: ${{ github.event.pull_request.head.sha }} + run: | + set -eu + gh pr merge "$PR" --disable-auto -R "$REPO" || true + gh pr comment "$PR" -R "$REPO" --body "🔒 Auto-merge disabled — new commit (\`${NEW_SHA:0:7}\`) pushed after auto-merge was enabled. The merge queue locks SHAs at entry, so subsequent pushes can race. Verify the new commit and re-enable with \`gh pr merge --auto\`."