ci: auto-update PR branches when main advances#5957
Merged
Conversation
GitHub's auto-merge button waits for required checks to pass AND for the head to be up-to-date with the base. With `strict_required_status_checks_policy: true` on the `main` ruleset this means a PR with green CI but a stale head sits open forever until someone clicks "Update branch" by hand — defeating the whole point of auto-merge. This workflow runs on every push to `main`, finds every open PR with `autoMergeRequest != null` whose `mergeStateStatus == "BEHIND"`, and calls `PUT /pulls/:num/update-branch` (the API behind the UI's "Update branch" button) on each. Once the branch is up-to-date, CI re-runs against the new merge commit and auto-merge fires the squash merge automatically. GitHub merge queue would be a cleaner solution but isn't available on this user-owned repo — the rulesets API rejects the `merge_queue` rule with an empty validation error, so we use this workflow instead. Same end behavior, no plan dependency. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a GitHub Actions workflow to automatically “Update branch” for open PRs that have auto-merge enabled but are BEHIND main, so they can re-run CI and complete auto-merge under strict required status checks.
Changes:
- Introduces
.github/workflows/auto-update-pr-branches.ymltriggered on pushes tomain(and manual dispatch). - Uses
gh pr list+jqto find auto-merge-enabled PRs withmergeStateStatus == "BEHIND". - Calls
PUT /repos/:owner/:repo/pulls/:num/update-branchper PR, warning (not failing) on per-PR update failures.
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read # required for actions/checkout (not strictly needed here, but cheap) |
Comment on lines
+76
to
+80
| if ! gh api -X PUT \ | ||
| "repos/${GH_REPO}/pulls/${NUM}/update-branch" \ | ||
| -H "Accept: application/vnd.github+json" \ | ||
| --silent 2>&1; then | ||
| echo "::warning::Could not update PR #${NUM} (likely conflict or stale ref)" |
2 tasks
MarkusNeusinger
added a commit
that referenced
this pull request
May 7, 2026
) ## Summary First run of \`auto-update-pr-branches.yml\` after #5957 found 0 BEHIND PRs even though three were stuck behind main (#5916, #5870, #5902). Two issues: 1. **Timing.** The workflow runs ~4s after the push to main, but GitHub recomputes \`mergeStateStatus\` and the cached PR head SHA asynchronously. Right after the push the field is still UNKNOWN and the cached head can be stale → \`update-branch\` returns *expected head sha didn't match current head ref*. Add a 30s sleep at the start. 2. **Over-strict filter.** The script only iterated PRs where \`mergeStateStatus == "BEHIND"\`, skipping UNKNOWN candidates — exactly the ones we wanted to fix. Drop the filter: after a push to main, every open auto-merge PR is behind, and \`update-branch\` is a no-op when the head is already up-to-date. Also: - Bump permissions to \`contents: write\` (update-branch creates a merge commit on the head ref). - Drop \`--silent\` and capture stderr so the actual GitHub error lands in the log. Verified manually: calling \`PUT /pulls/{num}/update-branch\` from the CLI on #5916 and #5870 worked and they auto-merged within seconds. The 422 on #5902 was a real history-divergence conflict (4 ahead / 58 behind / merge_base differs) — separate problem. ## Test plan - [ ] After this merges, push something to main and confirm the workflow finds N>0 PRs (where N is open auto-merge PRs). - [ ] Confirm any genuinely stuck PR (conflict) gets a clear error in the log instead of \`likely conflict or stale ref\`. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.github/workflows/auto-update-pr-branches.yml. Triggers on every push tomainand on manual dispatch.autoMergeRequest != null) whosemergeStateStatus == "BEHIND", then callsPUT /pulls/:num/update-branchon each (the API behind the UI's "Update branch" button).Why
Auto-merge fires only when CI is green AND the head is up-to-date with the base — but it does not update the branch on its own. With
strict_required_status_checks_policy: trueon themainruleset, that means a PR with green CI but a stale head sits open forever waiting for someone to click "Update branch". This workflow closes that gap so polish/impl PRs squash-merge themselves end-to-end.GitHub's native merge queue would be the cleaner answer but the rulesets API rejects the
merge_queuerule on this repo with an empty validation error (tried full payload, isolated ruleset, classic branch protection). Likely an account-level feature toggle that isn't surfaced via API. This workflow does the same job without that dependency and works on every plan.Test plan
daily-regen) and letmainadvancemainand updates the BEHIND PRActions → Auto-update PR brancheslog for the "Found N PR(s) BEHIND" notice