Auto-update auto-merge PRs when main is pushed (#526) #1
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
| name: Auto-update PRs | |
| # When commits land on main, update every open PR targeting main that has | |
| # auto-merge enabled, so the branch is current with main. This lets GitHub | |
| # auto-merge actually fire instead of waiting for someone to click | |
| # "Update branch". | |
| # | |
| # Uses the "Update pull request branch" API: | |
| # PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch | |
| # This honors the repo's merge-queue / merge method settings (merge or rebase). | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: auto-update-prs-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| update: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Update auto-merge-enabled PRs targeting main | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| # List open PRs targeting main that have auto-merge enabled. Skip | |
| # drafts and PRs whose head branch lives in a different repository | |
| # (forks, sibling repos), since update-branch can't push to those | |
| # with GITHUB_TOKEN. Match the full nameWithOwner so a same-org | |
| # fork or sibling repo isn't mistaken for the canonical repo. | |
| prs=$(gh pr list \ | |
| --base main \ | |
| --state open \ | |
| --limit 500 \ | |
| --json number,isDraft,headRepository,headRepositoryOwner,autoMergeRequest \ | |
| --jq ".[] | |
| | select(.isDraft == false) | |
| | select(.autoMergeRequest != null) | |
| | select((.headRepositoryOwner.login + \"/\" + .headRepository.name) == \"${GH_REPO}\") | |
| | .number") | |
| if [ -z "$prs" ]; then | |
| echo "No auto-merge-enabled PRs to update." | |
| exit 0 | |
| fi | |
| for pr in $prs; do | |
| echo "::group::PR #$pr" | |
| # 202 = update queued, 422 = already up to date or has conflicts. | |
| # We tolerate 422 so one stuck PR doesn't fail the whole job, but | |
| # any other non-success status (auth, rate limit, outage) fails | |
| # loudly so regressions don't silently no-op the workflow. | |
| set +e | |
| output=$(gh api \ | |
| --method PUT \ | |
| -H "Accept: application/vnd.github+json" \ | |
| "/repos/${GH_REPO}/pulls/${pr}/update-branch" 2>&1) | |
| exit_code=$? | |
| set -e | |
| if [ $exit_code -eq 0 ]; then | |
| echo "Update queued for PR #$pr" | |
| elif echo "$output" | grep -q "HTTP 422"; then | |
| echo "Skipped PR #$pr (HTTP 422: already up to date, has conflicts, or not updatable)" | |
| else | |
| echo "::error::Unexpected failure updating PR #$pr" | |
| echo "$output" | |
| echo "::endgroup::" | |
| exit 1 | |
| fi | |
| echo "::endgroup::" | |
| done |