Auto Approve Pull Requests #785
This file contains 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 Approve Pull Requests | |
on: | |
pull_request_target: | |
types: [ opened, synchronize, reopened ] | |
check_suite: | |
types: [ completed ] | |
permissions: | |
pull-requests: write | |
checks: read | |
jobs: | |
auto-approve: | |
runs-on: ubuntu-latest | |
if: github.event_name == 'pull_request_target' || (github.event_name == 'check_suite' && github.event.check_suite.pull_requests[0]) | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ github.event.pull_request.head.sha }} | |
- name: Verify required status checks | |
id: check-status | |
uses: actions/github-script@v7 | |
with: | |
github-token: ${{ secrets.BOT_TOKEN }} | |
script: | | |
const retryInterval1 = 270 * 1000; // 270 seconds | |
await new Promise(resolve => setTimeout(resolve, retryInterval1)); | |
const { owner, repo } = context.repo; | |
const pr = context.payload.pull_request || context.payload.check_suite.pull_requests[0]; | |
const sha = pr.head.sha; | |
console.log(`Processing PR #${pr.number}, HEAD SHA: ${sha}`); | |
// Get required status checks for the base branch | |
const { data: branch } = await github.rest.repos.getBranch({ | |
owner, | |
repo, | |
branch: pr.base.ref, | |
}); | |
const requiredChecks = branch.protection?.required_status_checks?.contexts || []; | |
console.log('Required status checks:', requiredChecks); | |
// Function to check the status of required checks | |
async function checkRequiredStatusChecks() { | |
const { data: checks } = await github.rest.checks.listForRef({ | |
owner, | |
repo, | |
ref: sha, | |
per_page: 100, | |
}); | |
console.log('Found status checks:', checks.check_runs.length); | |
// Filter out non-required checks | |
const requiredCheckRuns = checks.check_runs.filter(check => requiredChecks.includes(check.name)); | |
console.log('Required status checks found:', requiredCheckRuns.length); | |
// Check for any failed or pending required checks | |
const failedChecks = requiredCheckRuns.filter(check => check.status === 'completed' && check.conclusion !== 'success'); | |
const pendingChecks = requiredCheckRuns.filter(check => check.status !== 'completed'); | |
if (failedChecks.length > 0) { | |
const failedNames = failedChecks.map(f => f.name).join(', '); | |
console.log(`Failed checks: ${failedNames}`); | |
throw new Error('Some required status checks have failed'); | |
} | |
if (pendingChecks.length > 0) { | |
const pendingNames = pendingChecks.map(p => p.name).join(', '); | |
console.log(`Pending checks: ${pendingNames}`); | |
return false; // Still pending | |
} | |
console.log('All required status checks have passed successfully'); | |
return true; // All checks passed | |
} | |
// Poll for status checks until they complete | |
const maxRetries = 15; | |
const retryInterval = 30 * 1000; // 30 seconds | |
for (let i = 0; i < maxRetries; i++) { | |
const allChecksPassed = await checkRequiredStatusChecks(); | |
if (allChecksPassed) { | |
return true; | |
} | |
console.log(`Retrying in ${retryInterval / 1000} seconds... (${i + 1}/${maxRetries})`); | |
await new Promise(resolve => setTimeout(resolve, retryInterval)); | |
} | |
throw new Error('Timeout waiting for required status checks to complete'); | |
- name: Auto approve PR | |
if: steps.check-status.outputs.result == 'true' | |
uses: hmarr/auto-approve-action@v4 | |
with: | |
github-token: ${{ secrets.BOT_TOKEN }} | |
pull-request-number: ${{ github.event.pull_request.number }} | |
review-message: "LGTM" |