Skip to content

Conversation

Shreychit
Copy link

Automate triage of low-effort docs/README PRs

This adds a GitHub Action (.github/workflows/anti-spam-pr.yml) that automatically labels, comments on, and closes low-effort, README/docs-only PRs (e.g., “add my name”, tiny cosmetic edits) that tend to spike during events and create triage noise.

Why
• Maintainer time gets pulled into spammy PRs that add no user value.
• We cannot prevent PRs from being opened, but we can safely auto-triage them the moment they’re created.

What it does
• Runs on pull_request_target (executes in the base repo context).
• Inspects the PR diff via the GitHub API only (no checkout, no untrusted code execution).
• If the PR appears to be low-effort docs-only:
• Auto-creates (if missing) and applies labels: spam, invalid, autoclosed
• Posts an explanatory comment
• Closes the PR (optional lock is toggleable)

Heuristics (conservative defaults)

A PR is considered “likely spam” when:
• Only docs files are changed (README/docs/.github) with a tiny diff (configurable),
• No linked issue or closing keyword in the body (Closes #123, Fixes #123),
• Common spam wording in title/body (“add my name”, “portfolio”, etc.),
• Stricter if the account is very new (configurable),
• Skips trusted collaborators (admin/maintain/write) and known bots,
• Ignores code paths (lib/, benchmarks/, test/, *.js|mjs|cjs|ts|json) to avoid blocking real changes.

Express-specific: we treat lib/, benchmarks/, test/ and code extensions as “code touch” and keep such PRs open.

Safety & permissions
• Uses pull_request_target to have write-perms for labeling/closing while never running PR code.
• Explicit minimal permissions: contents: read, pull-requests: write, issues: write.
• No actions/checkout step; all logic is API-only.

Maintainer controls (in-file tunables)

At the top of the workflow:
• MAX_DOCS_ONLY_CHANGES (default: 20) – tiny-diff threshold
• NEW_ACCOUNT_WINDOW_DAYS (default: 14) – “very new” author window
• ENABLE_LOCK (default: false) – lock threads after close
• LABELS – set of labels applied/created

“Soft launch” (label-only)

If you want to trial this without auto-closing:
• Comment out the pulls.update({ state: 'closed' }) line.
• Keep labeling + commenting for a week, monitor false positives, then re-enable closing.

Evidence / testing
• The action has been tested on a forked sandbox to:
• Auto-close README-only tiny-diff PRs (with screenshots/logs),
• Allow legitimate docs/code PRs (with linked issues).
• You can also review the job logs (Actions → Auto-close spammy PRs) to see the decision notices:
• onlyDocs, onlyReadme, touchesCode, hasLinkedIssue, accountAgeDays, decision=SPAM→close|OK→keep open.

Edge cases & recovery
• Misclassification: Maintainers can remove the autoclosed label and click Reopen.
• Contributors with real docs work: Link an issue or add more context; these won’t be flagged.
• Events (e.g., Hacktoberfest): Labels make it clear why PRs are closed and help deter repeats.

Non-goals / limitations
• Does not block PR creation (GitHub doesn’t allow that).
• Not a replacement for human review—just reduces obvious spam.

Files added
• .github/workflows/anti-spam-pr.yml – the action (about ~100 lines, self-contained)

@emreisik95
Copy link

I just come to here for doing it, absolutely good idea.

@abs007
Copy link

abs007 commented Oct 5, 2025

Maintainers seem to want github/ai-moderator. Try pushing code to implement that maybe? link.

I feel like some of these checks would wrongly classify genuine PRs

@Shreychit
Copy link
Author

Update: Switched to GitHub’s official AI Moderator setup.
• Issues/Comments: github/ai-moderator
• PRs: ai-assessment-comment-labeler flags README/docs-only tiny diffs; on YES we label + auto-close (skips trusted, minimal perms, no untrusted code).

@anay-208
Copy link

anay-208 commented Oct 5, 2025

I don't think AI should be used for closing the PR, though it can be labelled as Low Effort.

Because AI can make mistakes

@merlinaudio
Copy link

When there's a mistake (unlikely but happens of course), couldn't the PR submitter just ping maintainers?

@tausiq2003
Copy link

what you think about this @abs007 #6805 (comment)

@anay-208
Copy link

anay-208 commented Oct 5, 2025

@merlinaudio Yes, that can be done, but I think it should be done in the future once its confirmed there are close to no false-positives

@Davis-3450
Copy link

Hope this works

@mohdlatif
Copy link

I really like the initiative to use AI, but it could potentially be bypassed through prompt injection.

@sunillshastry
Copy link

Fantastic job!

@worty76
Copy link

worty76 commented Oct 6, 2025

I don't think AI should be used for closing the PR, though it can be labelled as Low Effort.

Because AI can make mistakes

I agree with this. Automatically adding labels and posting comments should be enough.

@Devashish08
Copy link

@mohdlatif if some one have enough knowledge of prompt injections i don't think they will be raising these spammy PR in first place

@tausiq2003
Copy link

@mohdlatif if some one have enough knowledge of prompt injections i don't think they will be raising these spammy PR in first place

true its just overengineering, they are just spamming Reame.md not need of AI, plus i have justified yesterday. so a github action is enough to stop these spamming, anyways if one of both prs gets merged that will be good.

@ishaaqsuffyan
Copy link

Yeah this is so screwed. Please implement this for useless PRs

@0xshae
Copy link

0xshae commented Oct 6, 2025

I don't think AI should be used for closing the PR, though it can be labelled as Low Effort.
Because AI can make mistakes

adding to this,

i think automating the warning/labeling is a good idea but think that we could be cautious about the immediate closure of the PR. an instant bot closure, even for low-effort PRs, could be discouraging for a genuine, but mistaken, first-time contributor and carries the risk of AI flagging a genuine PR.

i suggest implementing a modified approach by allowing a "Review Window" and modifying the workflow slightly:

Stage 1: Label and Wait. The action should apply the spam, invalid, and autoclosed labels and post the explanatory comment, but not close the PR immediately.

Stage 2: Auto-Close Delay. A separate scheduled action (or logic added to the existing one) could close the PR after 24 to 48 hours (Review Window) if the autoclosed label is still present.

this is much better because now it saves time on the action and also provides a safety net/check if AI closes a false positive by allowing a certain "Review Window" for the maintainers to intervene.

@AnkanMisra
Copy link

+1 for automation
Adding a short delay before auto-closing (as @0xshae suggested) would help prevent genuine PRs from being closed too quickly

@Shreychit
Copy link
Author

Would you like me to add a grace period before auto-closing?
on AI “YES” we just label + comment, then a tiny scheduled workflow (e.g., every 15 min) closes PRs with that label after 1 hour unless a maintainer removes it or adds triaged:accepted.
If that sounds good, I’ll implement.

@0xshae @abs007 @tausiq2003

@tausiq2003
Copy link

Would you like me to add a grace period before auto-closing? on AI “YES” we just label + comment, then a tiny scheduled workflow (e.g., every 15 min) closes PRs with that label after 1 hour unless a maintainer removes it or adds triaged:accepted. If that sounds good, I’ll implement.

@0xshae @abs007 @tausiq2003

sounds good 👍

@0xshae
Copy link

0xshae commented Oct 7, 2025

Would you like me to add a grace period before auto-closing? on AI “YES” we just label + comment, then a tiny scheduled workflow (e.g., every 15 min) closes PRs with that label after 1 hour unless a maintainer removes it or adds triaged:accepted. If that sounds good, I’ll implement.

@0xshae @abs007 @tausiq2003

@Shreychit Could we stretch the window to 6 hours or 12 hours? just to ensure maintainers get ample time to intervene

@imbkz
Copy link

imbkz commented Oct 8, 2025

I think yes Ai can help us

@SreedharAvvari
Copy link

I think yes Ai can help us

#6814 - @imbkz Wasn't this you buddy??

@imbkz
Copy link

imbkz commented Oct 8, 2025

I think yes Ai can help us

#6814 - @imbkz Wasn't this you buddy??

I intentionally raised this PR to evaluate how the system handles scenarios that many students might replicate after watching that YouTube video.

@anay-208
Copy link

anay-208 commented Oct 8, 2025

Stage 2: Auto-Close Delay. A separate scheduled action (or logic added to the existing one) could close the PR after 24 to 48 hours (Review Window) if the autoclosed label is still present.

this is much better because now it saves time on the action and also provides a safety net/check if AI closes a false positive by
allowing a certain "Review Window" for the maintainers to intervene.

Let's say that if a maintainer, by any chance, wasn't able to see it within 2 days, it'll still automatically close it.

If a maintainer has verified that it is low effort, they could:

  • Manually close the PR in a click
  • If the user has provided additional info(after bot message), so it doesn't qualify as a "low-effort" PR, moderator could remove the tag and review it as normal

@UlisesGascon
Copy link
Member

Thanks @Shreychit for taking the time to contribute ❤️! Unfortunately, this PR is a duplicate of #5449.

For context on how we’re using GitHub Actions to handle this kind of spam moderation, please see: #5449 (comment).

The main problem with these spam PRs from people following that video isn’t the PR itself — we can close those quickly during triage. The bigger issue is the wave of off-topic, abusive, or spam comments that follow, which often end up bullying folks who are just learning GitHub and spamming notifications for real contributors (example: #6814).

That’s why we lock every spam PR, to stop it from becoming a time drain for maintainers.

Note for triage: I’ll lock this one too, to keep the discussion focused in #5449

@UlisesGascon UlisesGascon self-assigned this Oct 8, 2025
@expressjs expressjs locked as resolved and limited conversation to collaborators Oct 8, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Utilize the new hurtin query string lib in node