Skip to content

PR Inactivity Closer #1

PR Inactivity Closer

PR Inactivity Closer #1

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.`);
}
}