name: Stale PR Management on: schedule: - cron: "0 0 * * *" # Daily at midnight UTC workflow_dispatch: # Allow manual trigger for testing jobs: stale-prs: runs-on: ubuntu-latest permissions: pull-requests: write issues: write contents: read steps: - name: Handle stale PRs uses: actions/github-script@v7 with: script: | const now = new Date(); const owner = context.repo.owner; const repo = context.repo.repo; const { data: prs } = await github.rest.pulls.list({ owner, repo, state: "open", per_page: 100 }); for (const pr of prs) { const hasStale = pr.labels.some(l => l.name === "stale"); if (!hasStale) continue; const { data: commits } = await github.rest.pulls.listCommits({ owner, repo, pull_number: pr.number }); const lastCommitDate = new Date(commits[commits.length - 1].commit.author.date); const diffDays = (now - lastCommitDate) / (1000 * 60 * 60 * 24); if (diffDays > 7) { await github.rest.pulls.update({ owner, repo, pull_number: pr.number, state: "closed" }); await github.rest.issues.createComment({ owner, repo, issue_number: pr.number, body: "Closing stale PR due to inactivity." }); } else if (diffDays <= 7) { await github.rest.issues.removeLabel({ owner, repo, issue_number: pr.number, name: "stale" }); await github.rest.issues.createComment({ owner, repo, issue_number: pr.number, body: "Recent activity detected. Removing stale label." }); } }