Repository navigation
Auto closing old stale PRs #42981
Description
Activity
- addedtsc-agendaIssues and PRs to discuss during Technical Steering Committee meetings.Issues and PRs to discuss during Technical Steering Committee meetings.
on May 5, 2022 My experience is that non-humans closing things comes across as hostile (lacking compassion, etc). Using a bot to auto-tag stale issues with a human manually closing them later is fine; using a bot to auto-close them is a problem.
Reacted by Richard Lau, Beth Griggs and Dominic Saadi@ljharb I understand where you are coming from but I think the problem is that
a human manually closing them laterdoes not occur. I see issues where people periodically comment "is this still active" a number of times which streches over months or possibly longer. In the node-addon-api repo I've seen the stale autotagging and knowing that they will be closed without action has helped raised the visibility of stale issues/PRs and people being proactive because they want to avoid the autoclose when it does not make sense.@mhdawson in my experience it causes a bunch of much noisier "bump" comments, or, it gets closed (and in some projects, auto-locked) and then the problem is forgotten, which is much worse than the open issue being forgotten.
There's no value in optimizing for "fewer open issues" - the goal should be to optimize for fewer bugs.
@ljharb I see it as optimizing it for "more value added work" versus "fewer open issues". In this case we are talking only about PR's (I excluded issues as the dynamics are different there). I think a 1 year + stale PR only wastes peoples time (if they go look at PRs and try to help review/land) versus adding value at some point.
I certainly agree that confining it to just PRs, and having the stale period be a full year (with a warning comment and a waiting period after that), drastically reduces my concerns (but doesn't eliminate them)
I'm +1 with @mhdawson proposal.
+1
I think a bot auto-closing is friendlier than a human closing it.
If we have hundreds of open pull requests, they're equally "forgotten" as if we close them.
Reacted by Michaël ZassoAlso +1. I was going through some old PRs this morning that have 0% chance of getting merged but I didn't feel like closing them because you just know it's going to turn into a tedious back-and-forth when the author disagrees. Better to have a bot do it.
edit: I agree however with @ljharb about "bump" comments. I would make the bot strongly discourage them.
Also +1 to the suggestion.
Discussed in the last TSC meeting no objection to proceed.
- addedtsc-agendaIssues and PRs to discuss during Technical Steering Committee meetings.Issues and PRs to discuss during Technical Steering Committee meetings.and removedtsc-agendaIssues and PRs to discuss during Technical Steering Committee meetings.Issues and PRs to discuss during Technical Steering Committee meetings.
on Jun 1, 2022 I agree to the motivation - reducing the backlog and keeping it small and healthy. On the other hand, there are class of PRs (and the human behind those PRs) that can get hurt a little:
- PRs that are pending on collaborators
- PRs that have objections from reviewers with no path forward suggested
- PRs that were carried away (transformed) in the review and went out of OP's control and skill
- PRs that reveals flakes in the CI
- PRs whose OP is genuinely busy with other matters
I am not saying that all the PRs belong to these categories, or all these types can cause pains to the owners. My personal opinion is that we should make our PR abandonment process as friendly as possible (complimenting with the onboarding process) - a human touch would be much comforting for the owner.
Can I propose TSC members tasked with reviewing stale PRs each week (in small numbers) and address this one in an incremental, yet sustainable and firendly manner?
Reacted by Jordan Harband- removedtsc-agendaIssues and PRs to discuss during Technical Steering Committee meetings.Issues and PRs to discuss during Technical Steering Committee meetings.
on Jun 15, 2022 9 remaining items
That could explain it. The issues showed a force push 7 months ago but not that one (unless I just missed that somehow). Otherwise I would have been looking for something like that.
The problem is that a force push will affect all of our use of the stale actions (not just this new one) if they occur within every 6 months.
- added a commit that references this issue
on Jul 6, 2023 - added a commit that references this issue
on Jul 6, 2023 - added 2 commits that reference this issue
on Aug 14, 2023 - added a commit that references this issue
on Feb 18, 2024 github-actions commented
on Jun 25, 2026 on Jun 25, 2026 – with GitHub ActionsContributorMore actionsThis issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.- addedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jun 25, 2026 Reviving this. I've been triaging the networking-related backlog and that led me to look into why old PRs aren't getting cleaned up from the autonomous
stalebot. I did some digging and determined that both of our stale automations share a root issue.Research
Just to clarify, as far as I understand there are two stale automation systems in place. The first one is fully automatic, 240 day counter powered by the stale.yml workflow. The second is manual, 30 day counter powered by the closed-stalled.yml workflow.
I've come across the same issue Beth and Michael were discussing in this thread previously; "phantom" updates.
You can see this affecting the automatic flow in #58259 :
- 2026-04-20 01:43 — bot adds
stale+ posts the 30-day warning - 2026-04-25 01:42 — bot removes
stale - in between: no commits, no comments, no reviews
Unfortunately the UI confusingly collapse them into one line "added stale and removed stale on Apr 19". GH API demonstrates it better:
gh api repos/nodejs/node/issues/58259/timeline --paginate \ --jq '.[] | (.created_at // .submitted_at // .committer.date // "") as $t | select($t >= "2026-04-19" and $t <= "2026-04-26") | "\($t) \(.event // .type) by \(.actor.login // .user.login // .committer.name // "?")"' \ | sort 2026-04-20T01:43:38Z commented by github-actions[bot] 2026-04-20T01:43:39Z labeled by github-actions[bot] 2026-04-25T01:42:14Z unlabeled by github-actions[bot]The manual flow is a little more resilient (things do actually get closed) because of the shorter timeline, but its not immune. #40883 is a good example of an affected phantom update:
gh api repos/nodejs/node/issues/40883/timeline --paginate \ --jq '.[] | (.created_at // .submitted_at // .committer.date // "") as $t | select($t >= "2025-03-28T18:34:37Z" and $t <= "2025-04-03T00:01:37Z") | "\($t[:19]) \(.event // .type)\(if .label then " [" + .label.name + "]" else "" end) by \(.actor.login // .user.login // .committer.name // "?")"' 2025-03-28T18:34:37 labeled [stalled] by bjohansebas 2025-03-28T18:34:46 commented by github-actions[bot] 2025-04-03T00:01:37 unlabeled [stalled] by github-actions[bot]Both workflows rely on
actions/stalewhich measures inactivity byupdated_at. The problem is thatupdated_atgets bumped by things that aren't true PR activity.Thus, I believe Beth's force-push main suspicion is correct, but it's hard to definitely prove because GitHub doesn't expose why
updated_atis changed.I tried searching
mainbranch commit history to see if there was anything that stood out, but I can't find anything definitive either. My best suspicion is any base-branch movement (and possibly GitHub-internal mergeability recomputation) can bump an open PR'supdated_atcausing the "phantom" updates.Decision Point
I think the solution is relatively straightforward and depends on one question:
Do we accept that these phantom updates reset the staleness counter?
- If yes, then the window will keep getting reset by repo activity, and the only way to close more PRs is to make the window short enough to beat the churn. Drop 240 days to something meaningfully shorter. The manual 30 day is likely okay to remain as is. This is a simple config change, but we remain susceptible to the phantom updates.
- If no, then we make the workflows resilient by measuring genuine activity instead of relying on
updated_at. It could be something likemax(last commit committedDate, last non-bot comment, last review). This should meaningfully eliminate the phantom updates and enable our automations to actually close things out as expected.
I personally prefer the later "no" option, and believe we should fix the automation for real.
Reacted by Beth Griggs- 2026-04-20 01:43 — bot adds
- removedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jul 15, 2026 As a triager and maintainer of several of our spaces, I don't mind us being more aggressive in closure. The project thrives on momentum. I don't mean it has to be 30 days or else, but would anyone consider no communication for 8 months to be acceptable? The PR is unlikely to land simply due to drift and conflicts. I've personally witnessed a lot more drive by PRs now that never get any response upon providing feedback. If people don't come back right away to nurture a changeset, they likely aren't. (I state this with much empathy, from both sides) Even a
60day staleness seems acceptable. nodejs/help uses 180 albeit without any of the triggers you identified here resetting things.As to whether or not we accept the phantom updates, it sounds a bit out of our control, but building something ourselves feels counterproductive in a different way (maintenance, not expected with norms).
Perhaps we engage upstream? actions/stale recently had some good feedback/resolution- your analysis might help them narrow down another edge case
Hm yes I think I'd most-prefer to see this fixed upstream in
actions/stale.Maybe the best solution is to reduce timing to something like you said, 60 days for auto, 30 manual. And we hope
actions/stalefixes its issue?Worth noting that https://github.com/actions/stale/releases/tag/v10.3.0 which we just adoptedlast month has a fix for stale labeling itself resetting the timers...
Reacted by Ethan ArrowoodOkay so maybe things are better now - just need to wait a full month to see if it actually catches and cleans everything up.
Reacted by Efe Karasakal
Our backlog of feature requests has gone down from 249 to 87 with the stale feature request automation we put in place. A number of older ones are still open and we did not get too many complaints so I think it was easy enough for people to keep feature requests open that were still active/needed etc. while at the same time closing those that would likely never get addressed.
Looking at our PRs we have 340 open, 117 which are older than 1 year (https://github.com/nodejs/node/pulls?q=is%3Apr+is%3Aopen+created%3A%3C2021-05-05+).
When I look at those, in many cases the last comment is also a long time ago.
My thought is that for a PR 1 year old, which does not have any comments/updates in the last 6 months it's very unlikely that it's ever going to land. The longer it goes, the more likelyhood of conflicts etc. and that the original poster will no longer be around to help get it over the finish line.
Even in some cases where the PR looks like it was ready to land, we need something to kick it to our attention, or to get the originator to remind us its ready to land if they still care.
It's strange that 106 of those old PRs show as updated on Feb 24th, even though I can't see how they were updated when I look at the issues. Ignoring this issue I think it would be resonable to use an approach similar to what we did for feature requests with a different set of criteria.
PRs older than 1 year, no comments in last 5 months -> warn that PR is considered stale and will be closed if there is no comment in the next month
PRs older than 1 year, no comments in last 6 months -> close with appropriate message.
Thoughts?