Lock closed issues #71
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: Lock closed issues | |
| on: | |
| schedule: | |
| - cron: "0 0 * * *" # Run daily at midnight | |
| workflow_dispatch: | |
| permissions: | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| lock: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Lock old issues and PRs | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const daysBeforeLock = 3; | |
| const lockDate = new Date(); | |
| lockDate.setDate(lockDate.getDate() - daysBeforeLock); | |
| // Exclude patterns (case-insensitive) | |
| const excludePatterns = [ | |
| /automated pr/i, | |
| /\[bot\]/i, | |
| /dependabot/i | |
| ]; | |
| // Search for closed, unlocked issues older than 3 days (paginated, oldest first) | |
| let page = 1; | |
| let totalLocked = 0; | |
| while (true) { | |
| const issues = await github.rest.search.issuesAndPullRequests({ | |
| q: `repo:${context.repo.owner}/${context.repo.repo} is:closed is:unlocked updated:<${lockDate.toISOString().split('T')[0]}`, | |
| sort: 'updated', | |
| order: 'asc', | |
| per_page: 100, | |
| page: page | |
| }); | |
| if (issues.data.items.length === 0) break; | |
| console.log(`Page ${page}: ${issues.data.items.length} items (total available: ${issues.data.total_count})`); | |
| for (const item of issues.data.items) { | |
| // Skip excluded items | |
| const shouldExclude = excludePatterns.some(pattern => pattern.test(item.title)); | |
| if (shouldExclude) { | |
| console.log(`Skipped #${item.number}: "${item.title}" (matches exclude pattern)`); | |
| continue; | |
| } | |
| try { | |
| // Lock the issue/PR silently | |
| await github.rest.issues.lock({ | |
| ...context.repo, | |
| issue_number: item.number, | |
| lock_reason: 'resolved' | |
| }); | |
| totalLocked++; | |
| console.log(`Locked #${item.number} (${item.pull_request ? 'PR' : 'Issue'})`); | |
| } catch (error) { | |
| console.log(`Failed to lock #${item.number}: ${error.message}`); | |
| } | |
| } | |
| page++; | |
| // GitHub search API limit: max 10000 results (100 pages * 100) - temporarily increased | |
| if (page > 100) break; | |
| } | |
| console.log(`Total locked: ${totalLocked} issues/PRs`); |