PR Inactivity Closer #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: PR Inactivity Closer | |
| on: | |
| schedule: | |
| - cron: '0 0 * * *' # Runs daily at midnight UTC | |
| workflow_dispatch: # Allows manual triggering from the Actions tab | |
| permissions: | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| close-inactive-prs: | |
| name: Close Inactive PRs | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Process Inactive Pull Requests | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const label = 'inactive'; | |
| const daysThreshold = 5; | |
| const cutoffDate = new Date(); | |
| cutoffDate.setDate(cutoffDate.getDate() - daysThreshold); | |
| core.info(`Cutoff date for 5 days of inactivity: ${cutoffDate.toISOString()}`); | |
| // Ensure the inactivity label exists in the repository | |
| try { | |
| await github.rest.issues.getLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name: label, | |
| }); | |
| } catch { | |
| core.info(`Creating label '${label}'...`); | |
| await github.rest.issues.createLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name: label, | |
| color: '6b7280', | |
| description: 'This PR was closed due to inactivity.', | |
| }); | |
| } | |
| // Fetch all open PRs | |
| const { data: openPRs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| per_page: 100, | |
| }); | |
| core.info(`Scanning ${openPRs.length} open pull requests...`); | |
| for (const pr of openPRs) { | |
| const updatedAt = new Date(pr.updated_at); | |
| if (updatedAt < cutoffDate) { | |
| core.info(`PR #${pr.number} (@${pr.user.login}) is inactive. Last updated: ${pr.updated_at}. Closing...`); | |
| // 1. Add inactivity label | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| labels: [label], | |
| }); | |
| // 2. Post explanatory comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| body: `🤖 Hey @${pr.user.login}, this pull request has been automatically closed because it has been inactive for 5 days.\n\nIf you are still interested in fixing the issue and contributing, please feel free to pull the latest changes, resolve any conflicts, and reopen this PR at any time! We'd love to review your work. Thank you! ❤️`, | |
| }); | |
| // 3. Close the PR | |
| await github.rest.pulls.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: pr.number, | |
| state: 'closed', | |
| }); | |
| core.info(`Successfully closed PR #${pr.number}.`); | |
| } else { | |
| core.info(`PR #${pr.number} is active. Last updated: ${pr.updated_at}. Skipping.`); | |
| } | |
| } |