Skip to content

chore: auto-close stale release PRs after 3 hours of inactivity - #9655

Open
cryptodev-2s wants to merge 21 commits into
mainfrom
chore/close-stale-release-prs
Open

chore: auto-close stale release PRs after 3 hours of inactivity#9655
cryptodev-2s wants to merge 21 commits into
mainfrom
chore/close-stale-release-prs

Conversation

@cryptodev-2s

@cryptodev-2s cryptodev-2s commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Explanation

Abandoned release/* PRs can sit open and block other engineers from starting a new release. There is no automated cleanup today, so stale release candidates have to be closed by hand.

This PR adds a scheduled GitHub Actions workflow (every 30 minutes, plus workflow_dispatch) that:

  • Finds open same-repo PRs whose head branch starts with release/
  • Closes them after 3 hours of inactivity (updated_at)
  • Leaves a comment explaining why
  • Deletes the release branch only when its tip SHA is unchanged

Fork heads, PRs in the merge queue, PRs with auto-merge enabled, and PRs labeled release:keep-open are skipped. The releasing docs are updated to describe this policy.

Before destructive actions, the workflow:

  • Fetches a fresh GraphQL snapshot and skips if the PR is no longer eligible (open / skip label / fork / 3h / merge-queue or auto-merge)
  • Closes before commenting so a failed close does not reset the stale timer
  • Re-fetches the branch tip immediately before deleteRef and skips deletion unless the SHA still matches
  • Comments only after a successful close and the delete attempt; tip-move skips and real delete failures get distinct note wording (successful deletes rely on GitHub’s normal closed-PR UI)
  • Continues past per-PR API failures so one error does not abort the rest of the run

Flow

flowchart TD
  trigger(["cron every 30m / workflow_dispatch"]) --> checkout[Checkout and setup]
  checkout --> listOpen[List open PRs via REST paginate]
  listOpen --> candidates[Filter candidates:<br/>same-repo release/*,<br/>no release:keep-open]

  candidates --> more{"More candidates?"}
  more -->|no| done([Done])
  more -->|yes| snap[GraphQL snapshot]

  snap --> elig{"Eligible?<br/>OPEN, not fork, not skip label,<br/>updatedAt older than 3h,<br/>not merge-queue / auto-merge"}
  elig -->|no| more
  elig -->|yes| closePR[Close PR]

  closePR --> closeOk{Close succeeded?}
  closeOk -->|no| more
  closeOk -->|yes| getRef[git.getRef for head branch]

  getRef --> tipOk{"Tip SHA still matches<br/>snapshot headRefOid?"}
  tipOk -->|refresh failed| keepRefresh[Keep branch:<br/>kept-refresh-failed]
  tipOk -->|moved| keepMoved[Keep branch:<br/>kept-head-moved]
  tipOk -->|unchanged| deleteRef[git.deleteRef]

  deleteRef --> delOk{Delete succeeded?}
  delOk -->|yes| deleted[Branch deleted]
  delOk -->|no| keepFail[Keep branch:<br/>kept-delete-failed]

  keepRefresh --> comment[Comment with outcome]
  keepMoved --> comment
  deleted --> comment
  keepFail --> comment
  comment --> more
Loading

References

N/A

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Test plan

  • Confirm workflow checks / actionlint pass on this PR
  • Optionally run via workflow_dispatch against a throwaway stale release/* PR and verify comment, close, and branch delete
  • Confirm a recently updated release PR is left alone
  • Confirm a PR with release:keep-open is left alone
  • Confirm a late push (head SHA change) causes branch deletion to be skipped and the comment says the branch was kept

Note

Medium Risk
The workflow can close PRs and delete release/* branches with contents: write, but scope is narrow (same-repo release branches, merge/auto-merge skips, SHA-checked deletes); mis-timed closes could still disrupt an in-progress release.

Overview
Adds automated cleanup for abandoned release PRs so they do not block new releases.

A new scheduled workflow (every 30 minutes, plus manual dispatch) runs scripts/close-stale-release-prs.mts, which finds open same-repo PRs on release/* heads, skips forks, merge-queue/auto-merge, and PRs labeled release:keep-open, then closes PRs inactive for 3 hours (updatedAt). It closes before commenting, deletes the branch only if the tip SHA still matches a fresh snapshot, posts an explanatory comment, and continues on per-PR API failures.

Releasing docs document the 3-hour policy and the opt-out label. Root devDependencies add @actions/core and @actions/github for the script.

Reviewed by Cursor Bugbot for commit 7a05448. Bugbot is set up for automated code reviews on this repo. Configure here.

Abandoned release/* PRs block others from starting new releases; close them, delete the branch, and document the escape-hatch label.
@cryptodev-2s
cryptodev-2s requested a review from a team as a code owner July 24, 2026 15:39
Comment thread .github/workflows/close-stale-release-prs.yml Outdated
Comment thread .github/workflows/close-stale-release-prs.yml Outdated
Re-fetch each PR before acting, close before commenting, and continue on per-PR failures so a merge race or failed close cannot leave a misleading comment or abort the whole run.
Comment thread .github/workflows/close-stale-release-prs.yml Outdated
Wrap per-PR pulls.get and GraphQL merge-queue lookups in try/catch so one transient failure does not abort the rest of the stale-close loop.
Abort if updated_at, head SHA/ref, labels, staleness, or merge-queue state changed after the earlier refresh so a late push is not discarded.
Compare the complete label set on the final pre-close refresh, and re-fetch the branch ref immediately before deleteRef so a late push is not discarded.
Comment thread .github/workflows/close-stale-release-prs.yml Outdated
Post the stale-close comment only after the delete attempt so it reports whether the branch was removed, skipped due to a tip move, or failed to delete.
Comment thread .github/workflows/close-stale-release-prs.yml Outdated

@mcmire mcmire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some comments below, but they assume that adding this workflow makes sense. That said, maybe there is a preexisting action we can use? This feels like something we shouldn't have to reinvent. For instance if we automatically assign a release label to release PRs then perhaps we can use something like this with the only-pr-labels option: https://github.com/marketplace/actions/close-stale-issues. There are also quite a few actions in the GitHub marketplace that do a similar thing.

- name: Close inactive release PRs
uses: actions/github-script@v8
env:
STALE_HOURS: '3'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these environment variables? Why not set them as variables inside the script? This way you don't have to parse them as numbers.

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 0c750f5ab5: these are now script constants (STALE_HOURS / EXEMPT_LABEL) instead of workflow env vars.

Comment thread .github/workflows/close-stale-release-prs.yml Outdated
…tants

Move the github-script body to .github/scripts and replace env-parsed STALE_HOURS/EXEMPT_LABEL with script constants, per review feedback.
@cryptodev-2s

cryptodev-2s commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

I made some comments below, but they assume that adding this workflow makes sense. That said, maybe there is a preexisting action we can use? This feels like something we shouldn't have to reinvent. For instance if we automatically assign a release label to release PRs then perhaps we can use something like this with the only-pr-labels option: https://github.com/marketplace/actions/close-stale-issues. There are also quite a few actions in the GitHub marketplace that do a similar thing.

I evaluated actions/stale. It handles general day-based staleness and label filtering, but this workflow needs a three-hour window, release/* branch targeting, merge-queue/auto-merge exemptions, and head-SHA verification before deletion. Supporting those guarantees would still require custom logic, so the extracted script remains the safer fit.

…c lint

Break the script into named functions for eligibility, merge-state, close, delete, and comment, and satisfy jsdoc/require-param-description.
@cryptodev-2s
cryptodev-2s requested review from Mrtenz and mcmire July 24, 2026 22:49
@mcmire

mcmire commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

@cryptodev-2s Ah I didn't realize that was the official stale action. Yeah, I looked through some other (non-official) stale actions and didn't really find anything. I'll continue looking at this PR.

Comment thread .github/workflows/close-stale-release-prs.yml Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
Use SKIP_LABEL and a single stale duration, rename helpers/vars, detect forks via head.repo.fork, and simplify the close comment to only call out branch-delete failures.
Comment thread .github/scripts/close-stale-release-prs.cjs Outdated
…ckages

Replace the github-script CJS entrypoint with an executable tsx script that uses @actions/github and @actions/core, and fetch PR eligibility via a single GraphQL snapshot query.
@socket-security

socket-security Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​actions/​github@​9.1.19710010086100
Added@​actions/​core@​3.0.19910010086100

View full report

@socket-security

socket-security Bot commented Jul 28, 2026

Copy link
Copy Markdown

Caution

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Block Medium
System shell access: npm @actions/exec in module child_process

Module: child_process

Location: Package overview

From: ?npm/@actions/core@3.0.1npm/@actions/exec@3.0.0

ℹ Read more on: This package | This alert | What is shell access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should avoid accessing the shell which can reduce portability, and make it easier for malicious shell access to be introduced.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@actions/exec@3.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @actions/github in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/@actions/github@9.1.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@actions/github@9.1.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @actions/http-client in module http

Module: http

Location: Package overview

From: ?npm/@actions/github@9.1.1npm/@actions/http-client@3.0.2

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@actions/http-client@3.0.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @actions/http-client in module https

Module: https

Location: Package overview

From: ?npm/@actions/github@9.1.1npm/@actions/http-client@3.0.2

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@actions/http-client@3.0.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @actions/http-client in module http

Module: http

Location: Package overview

From: ?npm/@actions/core@3.0.1npm/@actions/http-client@4.0.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@actions/http-client@4.0.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @actions/http-client in module https

Module: https

Location: Package overview

From: ?npm/@actions/core@3.0.1npm/@actions/http-client@4.0.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@actions/http-client@4.0.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm tunnel in module net

Module: net

Location: Package overview

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/tunnel@0.0.6

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/tunnel@0.0.6. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm tunnel in module tls

Module: tls

Location: Package overview

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/tunnel@0.0.6

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/tunnel@0.0.6. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm tunnel in module http

Module: http

Location: Package overview

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/tunnel@0.0.6

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/tunnel@0.0.6. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm tunnel in module https

Module: https

Location: Package overview

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/tunnel@0.0.6

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/tunnel@0.0.6. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Low
Publisher changed: npm content-type is now published by blakeembrey instead of dougwilson

New Author: blakeembrey

Previous Author: dougwilson

From: ?npm/@actions/github@9.1.1npm/content-type@2.0.0

ℹ Read more on: This package | This alert | What is new author?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Scrutinize new collaborator additions to packages because they now have the ability to publish code into your dependency tree. Packages should avoid frequent or unnecessary additions or changes to publishing rights.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/content-type@2.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm undici is 75.0% likely to have a medium risk anomaly

Notes: The analyzed code appears to implement a standard in-memory cache batch operation flow (put/delete) with careful handling of response bodies by buffering and storing bytes for caching. No signs of malware, data exfiltration, backdoors, or obfuscated behavior were found. The primary security considerations relate to memory usage from buffering potentially large response bodies and ensuring robust validation within batch operations to prevent cache state corruption. Overall risk is moderate, driven by in-memory data handling rather than external communication.

Confidence: 0.75

Severity: 0.60

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/undici@6.28.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/undici@6.28.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm undici is 68.0% likely to have a medium risk anomaly

Notes: The analyzed code implements a conventional HTTP/WebSocket-like upgrade handler with proper input validation, abort signal integration, and asynchronous callback management. It does not exhibit malicious activity such as data exfiltration or backdoors. The deliberate onHeaders error path is consistent with protocol expectations to reject non-upgrade responses. Overall security risk remains low to moderate, contingent on integration context, but no indicators of malware or obfuscation are detected in this fragment.

Confidence: 0.68

Severity: 0.50

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/undici@6.28.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/undici@6.28.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm undici is 65.0% likely to have a medium risk anomaly

Notes: The code is a focused error-handling helper for HTTP responses that safely parses small payloads to include in an error object. It includes protective measures (chunk limits, controlled parsing, microtask-based callbacks) but uses unusual, brittle content-type checks and suppresses stack traces for debugging concealment. There is no evidence of malicious activity, data exfiltration, or backdoors within this fragment. The main risk is potential silent data loss if payloads exceed the chunk limit or mismatched content-type handling leads to missing payloads, but this is a functional trade-off rather than malicious. Suggested improvements include robust content-type parsing, clearer error signaling when payload is truncated, and optional logging to aid debugging without exposing stack traces in production.

Confidence: 0.65

Severity: 0.58

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/undici@6.28.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/undici@6.28.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm undici is 77.0% likely to have a medium risk anomaly

Notes: The script performs an in-place, lossy re-encoding of a local file from UTF-8 to Latin-1 and rewrites it without backups or validation. This is unsafe due to potential data loss and code corruption, and could be exploited to tamper with source files in a supply chain. It does not exhibit active malware behavior, but its destructive nature warrants removal or strict safeguards (backups, explicit intent, error handling).

Confidence: 0.77

Severity: 0.65

From: ?npm/@actions/core@3.0.1npm/@actions/github@9.1.1npm/undici@6.28.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/undici@6.28.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Rename to .mts so TypeScript treats the file as ESM and can import the ESM-only @actions packages, unblocking lint:tsc.
Comment thread scripts/close-stale-release-prs.mts
Rename commentOnPull to commentOnPullRequest, and stop describing intentional tip-move skips as failed branch deletions.
@cryptodev-2s
cryptodev-2s enabled auto-merge July 28, 2026 12:18
One GraphQL eligibility check plus tip verification before delete is enough for this cron job.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 12e7ee4. Configure here.

Comment thread scripts/close-stale-release-prs.mts Outdated

@mcmire mcmire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks better. Small suggestions for now but I will do another higher-level review a bit later.

Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated
Comment thread scripts/close-stale-release-prs.mts Outdated

@mcmire mcmire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple more minor suggestions, but overall this looks pretty good.

Comment thread scripts/close-stale-release-prs.mts Outdated
* @returns True when the PR is a candidate for stale close.
*/
function isReleasePrCandidate(pullRequest: ListedPullRequest): boolean {
if (!pullRequest.head.ref.startsWith('release/')) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's worth it to reuse the same check we use in update-changelogs.yml to determine whether this is a release branch? I realize that means part of this logic will live in the action and not the script. Alternatively we could not worry about it for now and refactor it in another PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #9685 against this branch with a shared .github/actions/is-release-pr used by both update-changelogs and the stale closer (release/* prefilter, then the same merge-base + action-is-release check). Is that what you had in mind?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's a bit more complex than I imagined. Maybe we can merge this PR and then we can discuss further in that PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to do a follow up after the merge

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

@mcmire mcmire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple more things.

Comment on lines +31 to +32
persist-credentials: false
cache-node-modules: true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need these two options? persist-credentials no longer stores the token in the repo in actions/checkout@v6 (we are using v7 in action-checkout-and-setup). And since we aren't running the checkout step in one job and reusing the result in another job we don't need to cache Node modules.

Suggested change
persist-credentials: false
cache-node-modules: true


concurrency:
group: close-stale-release-prs
cancel-in-progress: false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think this is the default: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#concurrency

Suggested change
cancel-in-progress: false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants