Files
2026-07-13 12:28:55 +08:00

113 lines
4.1 KiB
YAML

name: Close stale pull requests
on:
schedule:
- cron: "17 3 * * *"
workflow_dispatch:
permissions:
issues: write
pull-requests: write
jobs:
close-stale-pull-requests:
if: github.repository == 'anomalyco/models.dev'
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v8
env:
REVIEWER: rekram1-node
with:
script: |
const { owner, repo } = context.repo
const now = Date.now()
const weekAgo = now - 7 * 24 * 60 * 60 * 1000
const monthAgo = now - 30 * 24 * 60 * 60 * 1000
const pulls = await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: "open",
per_page: 100,
})
const feedbackPulls = new Set()
for (const qualifier of ["commenter", "reviewed-by"]) {
const results = await github.paginate(
github.rest.search.issuesAndPullRequests,
{
q: `repo:${owner}/${repo} is:pr is:open ${qualifier}:${process.env.REVIEWER}`,
per_page: 100,
},
)
for (const result of results) feedbackPulls.add(result.number)
}
for (const pull of pulls) {
let feedbackAt = 0
if (feedbackPulls.has(pull.number)) {
const [comments, reviews, reviewComments] = await Promise.all([
github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: pull.number,
per_page: 100,
}),
github.paginate(github.rest.pulls.listReviews, {
owner,
repo,
pull_number: pull.number,
per_page: 100,
}),
github.paginate(github.rest.pulls.listReviewComments, {
owner,
repo,
pull_number: pull.number,
per_page: 100,
}),
])
const feedbackTimes = [
...comments
.filter((comment) => comment.user?.login === process.env.REVIEWER)
.map((comment) => Date.parse(comment.updated_at)),
...reviews
.filter((review) => review.user?.login === process.env.REVIEWER && review.submitted_at)
.map((review) => Date.parse(review.submitted_at)),
...reviewComments
.filter((comment) => comment.user?.login === process.env.REVIEWER)
.map((comment) => Date.parse(comment.updated_at)),
]
feedbackAt = Math.max(0, ...feedbackTimes)
}
// Refetch after loading feedback so activity during this run cannot be missed.
const { data: currentPull } = await github.rest.pulls.get({
owner,
repo,
pull_number: pull.number,
})
const updatedAt = Date.parse(currentPull.updated_at)
const monthStale = updatedAt < monthAgo
const feedbackStale = feedbackAt > 0 && feedbackAt < weekAgo && updatedAt <= feedbackAt
if (!monthStale && !feedbackStale) continue
const reason = monthStale
? "it has not been updated in 30 days"
: `it has not been updated since feedback from @${process.env.REVIEWER} was left 7 days ago`
await github.rest.issues.createComment({
owner,
repo,
issue_number: pull.number,
body: `Closing this pull request as stale because ${reason}. Feel free to reopen it or submit a new pull request if the work is resumed.`,
})
await github.rest.pulls.update({
owner,
repo,
pull_number: pull.number,
state: "closed",
})
}