Skip to content

ci: auto-close PRs that try to publish servers via the repo#1393

Open
rdimitrov wants to merge 3 commits into
mainfrom
accidental-spark
Open

ci: auto-close PRs that try to publish servers via the repo#1393
rdimitrov wants to merge 3 commits into
mainfrom
accidental-spark

Conversation

@rdimitrov

Copy link
Copy Markdown
Member

Summary

We keep getting PRs (e.g. #1385, #1368, #1367, #1363, #1354) that try to "publish" an MCP server by adding files under servers/ or editing data/seed.json. That isn't how publishing works — servers are published with the mcp-publisher CLI against the live registry API. This adds automation that detects those PRs, comments with a pointer to the publishing quickstart, labels them invalid, and closes them.

How it works (two stages, no pull_request_target)

pull_request_target is intentionally avoided. Instead:

  • Stage 1 — detect-invalid-publish-prs.yml runs on pull_request (opened/reopened) with a read-only token. It only reads the changed file paths and, if the PR exclusively touches servers/** and/or data/seed.json (and the author isn't a MEMBER/OWNER/COLLABORATOR), records just the PR number as a short-lived artifact. It can't comment or close anything.
  • Stage 2 — close-invalid-publish-prs.yml runs via workflow_run in the trusted base-repo context (write token). It picks up the flagged PR number, independently re-validates the PR from the API (still open, external author, files still match, not already labeled), then comments, labels invalid, and closes.

Trust boundary

The only thing crossing from the untrusted stage to the privileged stage is the PR number, sanitized to digits only. Stage 2 never trusts stage 1's verdict — it re-derives every decision. Neither stage ever checks out or runs PR code.

Safety against false positives

  • Fires only when a PR touches exclusively servers/** and/or data/seed.json — a real code PR that also happens to touch seed data is left alone.
  • Skips MEMBER/OWNER/COLLABORATOR authors, so maintainers editing dev seed data aren't auto-closed.
  • Idempotent: skips PRs already labeled invalid (e.g. if a maintainer reopens one).

Notes

  • Like any pull_request/workflow_run automation, this only takes effect once merged to main — it is not retroactive and won't run on this PR. The currently-open offending PRs should be closed manually.
  • Pinned action SHAs match the repo's existing convention (upload-artifact reuses the SHA already in ci.yml).

🤖 Generated with Claude Code

rdimitrov and others added 3 commits June 25, 2026 10:34
Some contributors try to "publish" an MCP server by opening a PR that adds
files under servers/ or edits data/seed.json, which is not how publishing
works. Add a two-stage workflow that detects these PRs and closes them with a
comment pointing at the mcp-publisher quickstart.

Stage 1 (detect) runs on pull_request with a read-only token and only records
the flagged PR number as an artifact. Stage 2 (close) runs via workflow_run in
the trusted base context, re-validates the PR from the API, then comments,
labels `invalid`, and closes. This avoids pull_request_target; the only input
crossing the trust boundary is a sanitized PR number.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Use the paginated REST pulls/files endpoint instead of `gh pr view --json
  files`, which caps at 100 files with no pagination and could truncate a
  large PR into a false match.
- Capture PR labels into a variable before grepping so a transient gh failure
  can't fail open on the idempotency guard.
- Add an empty-file-list guard to stage 2 for parity with stage 1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GitHub renders single newlines in a comment paragraph as line breaks, so the
hard-wrapped second paragraph showed mid-sentence breaks. Put it on one line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants