name: Auto-merge # Merges a pull request once its CI run passes, so the owner does not have to # click merge on every change. Safety rails: # - only when the CI workflow concluded "success"; # - only for PRs opened by the repo owner, never an external contributor; # - skipped on any PR labelled "hold" or "no-automerge" — apply the label at # PR creation, because otherwise the merge may happen before you can. on: workflow_run: workflows: ["CI"] types: [completed] permissions: contents: write pull-requests: write jobs: merge: # The server check keeps this off Gitea, which mirrors this repo. There the # gh calls have no GitHub to talk to, so every push to main would end in a # failed "merge" run and a red mark on a branch that is perfectly fine. if: > github.server_url == 'https://github.com' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' runs-on: ubuntu-latest steps: - name: Merge the PR whose CI just passed env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} BRANCH: ${{ github.event.workflow_run.head_branch }} run: | pr=$(gh pr list --repo "$REPO" --head "$BRANCH" --state open \ --json number,author,labels --limit 1) num=$(echo "$pr" | jq -r '.[0].number // empty') if [ -z "$num" ]; then echo "No open PR for branch '$BRANCH' — nothing to merge." exit 0 fi author=$(echo "$pr" | jq -r '.[0].author.login') owner="${REPO%%/*}" if [ "$author" != "$owner" ]; then echo "PR #$num is by '$author' (not the owner '$owner') — leaving it for manual review." exit 0 fi if echo "$pr" | jq -r '.[0].labels[].name' | grep -qiE '^(hold|no-automerge)$'; then echo "PR #$num carries a hold/no-automerge label — skipping auto-merge." exit 0 fi echo "CI is green — auto-merging PR #$num." gh pr merge "$num" --repo "$REPO" --merge --delete-branch