Skip to content

Auto Approve

Auto Approve #513

Workflow file for this run

name: Auto Approve
on:
# Trigger when check runs complete
check_suite:
types: [completed]
# Also trigger on workflow run completion for reusable workflows
workflow_run:
workflows: ["PR Tests"]
types: [completed]
# Trigger when Copilot (or any reviewer) submits a review
pull_request_review:
types: [submitted]
permissions: read-all
jobs:
auto-approve:
runs-on: ubuntu-latest
# Only run on pull requests, not pushes
if: |
github.event.check_suite.pull_requests[0] != null ||
github.event.workflow_run.pull_requests[0] != null ||
github.event.pull_request != null
permissions:
pull-requests: write
steps:
- name: Get PR number
id: pr
run: |
if [ "${{ github.event_name }}" == "check_suite" ]; then
PR_NUMBER="${{ github.event.check_suite.pull_requests[0].number }}"
elif [ "${{ github.event_name }}" == "pull_request_review" ]; then
PR_NUMBER="${{ github.event.pull_request.number }}"
else
PR_NUMBER="${{ github.event.workflow_run.pull_requests[0].number }}"
fi
echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "PR number: $PR_NUMBER"
- name: Check required statuses
id: check
env:
GH_TOKEN: ${{ github.token }}
run: |
PR_NUMBER="${{ steps.pr.outputs.number }}"
if [ -z "$PR_NUMBER" ]; then
echo "No PR number found, skipping"
echo "should_approve=false" >> $GITHUB_OUTPUT
exit 0
fi
# Get PR head SHA
HEAD_SHA=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER --jq '.head.sha')
echo "Head SHA: $HEAD_SHA"
# Check Copilot review - must verify Copilot has actually reviewed first
# Copilot leaves "COMMENTED" reviews (never "APPROVED" or "CHANGES_REQUESTED")
# We need to: 1) Confirm a review exists, 2) Check for UNRESOLVED comments
# Note: Copilot uses "copilot-pull-request-reviewer[bot]" for reviews
COPILOT_REVIEW=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER/reviews" --jq '[.[] | select(.user.login == "copilot-pull-request-reviewer[bot]")] | length')
# Use GraphQL to count unresolved Copilot review threads
REPO_OWNER="${{ github.repository_owner }}"
REPO_NAME="${{ github.repository }}"
REPO_NAME="${REPO_NAME#*/}" # Extract repo name from owner/repo
UNRESOLVED_THREADS=$(gh api graphql -f query="query { repository(owner: \"$REPO_OWNER\", name: \"$REPO_NAME\") { pullRequest(number: $PR_NUMBER) { reviewThreads(first: 100) { nodes { isResolved comments(first: 1) { nodes { author { login } } } } } } } }" \
--jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false and .comments.nodes[0].author.login == "copilot-pull-request-reviewer")] | length')
COPILOT_OK="false"
if [ "$COPILOT_REVIEW" -eq 0 ]; then
echo "Copilot review: Not yet reviewed (no review found)"
elif [ "$UNRESOLVED_THREADS" -eq 0 ]; then
echo "Copilot review: Reviewed with no unresolved issues"
COPILOT_OK="true"
else
echo "Copilot review: Found $UNRESOLVED_THREADS unresolved threads - issues need addressing"
fi
echo "Copilot OK: $COPILOT_OK"
# Check Unity Tests status (commit status, not check run)
UNITY_STATUS=$(gh api repos/${{ github.repository }}/commits/$HEAD_SHA/status --jq '.statuses[] | select(.context == "Unity Tests") | .state' | head -1)
echo "Unity Tests status: $UNITY_STATUS"
# If Unity Tests doesn't exist (skipped scenario), check if Skip Unity Tests completed
if [ -z "$UNITY_STATUS" ]; then
SKIP_STATUS=$(gh api repos/${{ github.repository }}/commits/$HEAD_SHA/check-runs --jq '.check_runs[] | select(.name == "Skip Unity Tests") | .conclusion' | head -1)
echo "Skip Unity Tests status: $SKIP_STATUS"
if [ "$SKIP_STATUS" == "skipped" ] || [ "$SKIP_STATUS" == "success" ]; then
UNITY_STATUS="success"
fi
fi
# Determine if we should approve
if [ "$COPILOT_OK" == "true" ] && [ "$UNITY_STATUS" == "success" ]; then
echo "All required checks passed and Copilot found no issues!"
echo "should_approve=true" >> $GITHUB_OUTPUT
else
echo "Required checks not yet passed or Copilot found issues"
echo "should_approve=false" >> $GITHUB_OUTPUT
fi
- name: Check if already approved
id: existing
if: steps.check.outputs.should_approve == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
PR_NUMBER="${{ steps.pr.outputs.number }}"
# Check for existing approval from github-actions bot
EXISTING=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER/reviews --jq '[.[] | select(.user.login == "github-actions[bot]" and .state == "APPROVED")] | length')
if [ "$EXISTING" -gt 0 ]; then
echo "Already approved by bot"
echo "already_approved=true" >> $GITHUB_OUTPUT
else
echo "Not yet approved by bot"
echo "already_approved=false" >> $GITHUB_OUTPUT
fi
- name: Auto approve PR
if: steps.check.outputs.should_approve == 'true' && steps.existing.outputs.already_approved == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
PR_NUMBER="${{ steps.pr.outputs.number }}"
gh pr review $PR_NUMBER -R ${{ github.repository }} --approve --body "Auto-approved: Copilot review found no issues and Unity Tests passed (or were skipped for non-code changes)."
echo "PR #$PR_NUMBER approved!"