Skip to content

ci: auto-update PR branches when main advances#5957

Merged
MarkusNeusinger merged 1 commit into
mainfrom
claude/auto-update-pr-branches
May 7, 2026
Merged

ci: auto-update PR branches when main advances#5957
MarkusNeusinger merged 1 commit into
mainfrom
claude/auto-update-pr-branches

Conversation

@MarkusNeusinger
Copy link
Copy Markdown
Owner

Summary

  • New workflow .github/workflows/auto-update-pr-branches.yml. Triggers on every push to main and on manual dispatch.
  • Lists all open PRs with auto-merge enabled (autoMergeRequest != null) whose mergeStateStatus == "BEHIND", then calls PUT /pulls/:num/update-branch on each (the API behind the UI's "Update branch" button).
  • Failure on any one PR (conflict, deleted ref) is logged as a warning and doesn't block the others.

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: true on the main ruleset, 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_queue rule 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

  • After merge, queue an auto-merge PR (e.g. an auto-polish run from daily-regen) and let main advance
  • Confirm this workflow runs on the next push to main and updates the BEHIND PR
  • Confirm CI re-runs against the updated branch and auto-merge fires the squash merge
  • Sanity-check Actions → Auto-update PR branches log for the "Found N PR(s) BEHIND" notice

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>
Copilot AI review requested due to automatic review settings May 7, 2026 20:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.yml triggered on pushes to main (and manual dispatch).
  • Uses gh pr list + jq to find auto-merge-enabled PRs with mergeStateStatus == "BEHIND".
  • Calls PUT /repos/:owner/:repo/pulls/:num/update-branch per 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)"
@MarkusNeusinger MarkusNeusinger merged commit 7029511 into main May 7, 2026
11 checks passed
@MarkusNeusinger MarkusNeusinger deleted the claude/auto-update-pr-branches branch May 7, 2026 20:17
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>
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