diff --git a/.github/workflows/stale_pr_close.yml b/.github/workflows/stale_pr_close.yml index e16a66afa..aa6355f7d 100644 --- a/.github/workflows/stale_pr_close.yml +++ b/.github/workflows/stale_pr_close.yml @@ -3,7 +3,7 @@ on: schedule: - cron: "0 0 * * *" workflow_dispatch: - pull_request_target: # Changed from pull_request + pull_request_target: types: - labeled @@ -15,7 +15,7 @@ jobs: issues: write contents: read steps: - - name: Handle stale label + - name: Handle stale PRs uses: actions/github-script@v7 with: script: | @@ -23,7 +23,7 @@ jobs: const owner = context.repo.owner; const repo = context.repo.repo; - // --- PR labeled event --- + // --- When stale label is added, comment immediately --- if (context.eventName === "pull_request_target" && context.payload.action === "labeled") { const label = context.payload.label?.name; if (label === "stale") { @@ -37,7 +37,7 @@ jobs: return; } - // --- Scheduled run --- + // --- Scheduled run: check all stale PRs --- const { data: prs } = await github.rest.pulls.list({ owner, repo, @@ -49,6 +49,25 @@ jobs: const hasStale = pr.labels.some(l => l.name === "stale"); if (!hasStale) continue; + // Get timeline events to find when stale label was added + const { data: events } = await github.rest.issues.listEvents({ + owner, + repo, + issue_number: pr.number, + per_page: 100 + }); + + // Find the most recent time the stale label was added + const staleLabelEvents = events + .filter(e => e.event === "labeled" && e.label?.name === "stale") + .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); + + if (staleLabelEvents.length === 0) continue; + + const staleLabelDate = new Date(staleLabelEvents[0].created_at); + const daysSinceStale = (now - staleLabelDate) / (1000 * 60 * 60 * 24); + + // Check for new commits since stale label was added const { data: commits } = await github.rest.pulls.listCommits({ owner, repo, @@ -56,22 +75,9 @@ jobs: }); 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) { + // If there are new commits after the stale label, remove it + if (lastCommitDate > staleLabelDate) { await github.rest.issues.removeLabel({ owner, repo, @@ -85,4 +91,19 @@ jobs: body: "Recent activity detected. Removing stale label." }); } + // If 7 days have passed since stale label, close the PR + else if (daysSinceStale > 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 (no commits for 7 days after stale label)." + }); + } }