name: Stale PR Management on: schedule: # Runs daily at midnight UTC - cron: "0 0 * * *" pull_request: types: - labeled jobs: stale-prs: runs-on: ubuntu-latest permissions: pull-requests: write issues: write steps: - name: Handle stale label uses: actions/github-script@v7 with: script: | console.log('github object:', typeof github); console.log('github.rest:', typeof github?.rest); console.log('context.eventName:', context.eventName); const now = new Date(); const owner = context.repo.owner; const repo = context.repo.repo; // --- PR labeled event --- if (context.eventName === "pull_request" && context.payload.action === "labeled") { const label = context.payload.label?.name; if (label === "stale") { await github.rest.issues.createComment({ owner, repo, issue_number: context.payload.pull_request.number, body: "This PR has been marked as stale. It will be closed if no new commits are added in 7 days." }); } return; // exit, nothing else to do } // --- Scheduled run --- 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." }); } }