Skip to content

Auto-Merge

Auto-Merge #95

Workflow file for this run

name: Auto-Merge
on:
# Trigger when PR checks complete
pull_request_review:
types: [submitted]
check_suite:
types: [completed]
# Default permissions: read-only
# Write permissions are granted explicitly at job level
permissions:
contents: read
jobs:
auto-merge:
name: Auto-Merge Approved PRs
runs-on: ubuntu-latest
# Only run on PRs targeting main - check appropriate event context
# Skip for Dependabot PRs (they should never auto-merge)
# Note: We let jobs with no valid PR pass the condition and handle it in the steps
if: |
github.actor != 'dependabot[bot]' && (
(github.event_name == 'pull_request_review' && github.event.pull_request.base.ref == 'main') ||
(github.event_name == 'check_suite')
)
permissions:
contents: write # Required to merge PRs
pull-requests: write # Required to add comments and labels
steps:
- name: Get PR number
id: pr
run: |
if [ "${{ github.event_name }}" = "pull_request_review" ]; then
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
echo "base_ref=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "check_suite" ]; then
# Get PR number from check suite (with null safety)
PR_COUNT="${{ toJSON(github.event.check_suite.pull_requests) != '[]' && '1' || '0' }}"
if [ "$PR_COUNT" = "1" ]; then
PR_NUMBER="${{ github.event.check_suite.pull_requests[0].number }}"
BASE_REF="${{ github.event.check_suite.pull_requests[0].base.ref }}"
# Only proceed if targeting main
if [ "$BASE_REF" = "main" ]; then
echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "base_ref=$BASE_REF" >> $GITHUB_OUTPUT
else
echo "PR #$PR_NUMBER targets $BASE_REF (not main), skipping"
exit 0
fi
else
echo "No PR found in check_suite event, skipping"
exit 0
fi
else
echo "Unsupported event type, skipping"
exit 0
fi
- name: Check if PR should auto-merge
id: should-merge
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.pr.outputs.number }}
run: |
if [ -z "$PR_NUMBER" ]; then
echo "No PR number, skipping"
echo "should_merge=false" >> $GITHUB_OUTPUT
exit 0
fi
# Get PR details
PR_JSON=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER)
# Check if PR has auto-merge label
HAS_LABEL=$(echo "$PR_JSON" | jq -r '.labels[]? | select(.name == "auto-merge") | .name' || echo "")
# Check if PR is approved
REVIEWS=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER/reviews)
APPROVED=$(echo "$REVIEWS" | jq -r '[.[] | select(.state == "APPROVED")] | length')
# Check if PR is mergeable
MERGEABLE=$(echo "$PR_JSON" | jq -r '.mergeable')
STATE=$(echo "$PR_JSON" | jq -r '.mergeable_state')
DRAFT=$(echo "$PR_JSON" | jq -r '.draft')
echo "📊 PR Status:"
echo " PR #$PR_NUMBER"
echo " Has auto-merge label: $HAS_LABEL"
echo " Approved reviews: $APPROVED"
echo " Mergeable: $MERGEABLE"
echo " Mergeable state: $STATE"
echo " Draft: $DRAFT"
# Require: auto-merge label + approval + mergeable + not draft
if [ "$HAS_LABEL" = "auto-merge" ] && \
[ "$APPROVED" -gt "0" ] && \
[ "$MERGEABLE" = "true" ] && \
[ "$STATE" = "clean" ] && \
[ "$DRAFT" = "false" ]; then
echo "✅ PR ready for auto-merge"
echo "should_merge=true" >> $GITHUB_OUTPUT
else
echo "⏸️ PR not ready for auto-merge"
echo "should_merge=false" >> $GITHUB_OUTPUT
fi
- name: Auto-merge PR
if: steps.should-merge.outputs.should_merge == 'true'
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.pr.outputs.number }}
run: |
echo "🚀 Auto-merging PR #$PR_NUMBER"
# Merge the PR (squash by default)
gh pr merge $PR_NUMBER \
--squash \
--auto \
--delete-branch \
--subject "Auto-merge: PR #$PR_NUMBER"
echo "✅ PR #$PR_NUMBER queued for auto-merge"
- name: Comment on PR
if: steps.should-merge.outputs.should_merge == 'true'
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.pr.outputs.number }}
run: |
gh pr comment $PR_NUMBER --body "$(cat <<'EOF'
🤖 **Auto-Merge Enabled**
This PR has been approved and all checks have passed. It will be automatically merged once any remaining required checks complete.
If you need to make changes, remove the \`auto-merge\` label to prevent automatic merging.
EOF
)"