Cleanup Stale Bot PRs #8
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: Cleanup Stale Bot PRs | |
| on: | |
| schedule: | |
| - cron: '0 6 * * 1' # Weekly on Mondays | |
| workflow_dispatch: | |
| permissions: | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| cleanup: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Close stale automated PRs | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const STALE_DAYS = 30; | |
| const staleDate = new Date(Date.now() - STALE_DAYS * 24 * 60 * 60 * 1000); | |
| // Use Search API to find PRs with the label | |
| // pulls.list doesn't support labels parameter | |
| const searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open label:automated-bug-fix`; | |
| const { data: searchResults } = await github.rest.search.issuesAndPullRequests({ | |
| q: searchQuery, | |
| per_page: 100 | |
| }); | |
| const prs = searchResults.items; | |
| for (const pr of prs) { | |
| const createdAt = new Date(pr.created_at); | |
| const updatedAt = new Date(pr.updated_at); | |
| // Only close if both created AND last updated over STALE_DAYS ago | |
| if (createdAt < staleDate && updatedAt < staleDate) { | |
| // Check if there are recent comments or review activity | |
| // Use 'since' parameter to let server filter comments, avoiding pagination issues | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| since: staleDate.toISOString(), | |
| per_page: 100 | |
| }); | |
| // If any comments were returned, there's recent activity | |
| const hasRecentActivity = comments.length > 0; | |
| if (!hasRecentActivity) { | |
| // Add stale label before closing | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| labels: ['stale', 'auto-closed'] | |
| }); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| body: `Closing this automated PR as it has been open for ${STALE_DAYS}+ days without activity or merge. The bug hunter may re-detect and fix this issue in a future run if still relevant.` | |
| }); | |
| await github.rest.pulls.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: pr.number, | |
| state: 'closed' | |
| }); | |
| core.info(`Closed stale PR #${pr.number}`); | |
| } else { | |
| core.info(`Skipping PR #${pr.number} - has recent activity`); | |
| } | |
| } | |
| } |