|
|
@@ -1,14 +1,17 @@
|
|
|
name: External PR Scope Guard
|
|
|
|
|
|
-# Required status check that constrains what a NON-MEMBER pull request may change.
|
|
|
-# Members (write/admin) are unrestricted and skip this check. For a non-member PR this
|
|
|
-# fails unless the PR is an in-scope external contribution per .github/scripts/external-pr-scope.js:
|
|
|
-# it changes ONLY .claude-plugin/marketplace.json, the delta is additions-only (no existing
|
|
|
-# entry modified or removed), and every ADDED entry's source.url is a repo that ALREADY backs
|
|
|
-# a live plugin in this marketplace (the allowed set is derived from the live marketplace —
|
|
|
-# there is no maintained allowlist).
|
|
|
+# Advisory check that surfaces what a NON-MEMBER pull request may change.
|
|
|
+# Members (write/admin) and the repo's own automation bot (bump SHA PRs) are unrestricted and
|
|
|
+# skip this check. For a non-member PR this fails unless the PR is an in-scope external
|
|
|
+# contribution per .github/scripts/external-pr-scope.js: it changes ONLY
|
|
|
+# .claude-plugin/marketplace.json, the delta is additions-only (no existing entry modified or
|
|
|
+# removed), and every ADDED entry's source.url is a repo that ALREADY backs a live plugin in
|
|
|
+# this marketplace (the allowed set is derived from the live marketplace — there is no
|
|
|
+# maintained allowlist).
|
|
|
#
|
|
|
-# Add the scope-guard job as a REQUIRED status check in branch protection for it to block merge.
|
|
|
+# Do NOT add this job to branch protection as a required status check. The merge gate is the
|
|
|
+# `validate` + `scan` checks plus a maintainer approval; this guard is advisory signal for the
|
|
|
+# reviewer, not a hard gate. (Making it required would block the no-approval bump-merge path.)
|
|
|
#
|
|
|
# Security: runs on pull_request_target but checks out only the BASE repo (trusted) for the
|
|
|
# shared script; the head marketplace.json is fetched as DATA via the API and parsed, never executed.
|
|
|
@@ -29,17 +32,16 @@ jobs:
|
|
|
- uses: actions/github-script@v7
|
|
|
with:
|
|
|
script: |
|
|
|
- const author = context.payload.pull_request.user.login;
|
|
|
+ const { evaluate, isExemptAuthor } = require(`${process.env.GITHUB_WORKSPACE}/.github/scripts/external-pr-scope.js`);
|
|
|
|
|
|
- const { data: perm } = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
|
- owner: context.repo.owner, repo: context.repo.repo, username: author,
|
|
|
- });
|
|
|
- if (['admin', 'write'].includes(perm.permission)) {
|
|
|
- console.log(`${author} is ${perm.permission} (member) — scope guard not applicable.`);
|
|
|
+ // Members (write/admin) and the repo's own automation bot (bump SHA PRs) are
|
|
|
+ // unrestricted; only genuinely external contributions are scope-checked.
|
|
|
+ const ex = await isExemptAuthor({ github, context });
|
|
|
+ if (ex.exempt) {
|
|
|
+ console.log(`${ex.reason} — scope guard not applicable.`);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const { evaluate } = require(`${process.env.GITHUB_WORKSPACE}/.github/scripts/external-pr-scope.js`);
|
|
|
const result = await evaluate({ github, context });
|
|
|
|
|
|
if (!result.ok) {
|