mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-07-28 12:06:55 -03:00
Add an opt-in allowlist so a vetted external developer who already has a plugin live in this marketplace — but cannot use the submission form (e.g. an enterprise partner without a Claude account) — can open a reviewable PR instead of having it auto-closed. - .github/external-contributors.json: username -> allowed_sources map (doubles as the allowlist and the per-author source scope). - close-external-prs.yml: skip the auto-close for allowlisted authors (reads the list from the trusted base checkout). Grants ONLY the right to open a PR; CI + maintainer approval are unchanged. - external-pr-scope-guard.yml: required check for allowlisted external authors. Fails unless the PR touches ONLY marketplace.json and the delta is additions-only, with every added entry's source.url under that author's allowed_sources. Anthropic members are unrestricted. Reads head marketplace.json as data via the API (no untrusted checkout). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.7 KiB
YAML
69 lines
2.7 KiB
YAML
name: Close External PRs
|
|
|
|
on:
|
|
pull_request_target:
|
|
types: [opened]
|
|
|
|
permissions:
|
|
pull-requests: write
|
|
issues: write
|
|
|
|
jobs:
|
|
check-membership:
|
|
if: vars.DISABLE_EXTERNAL_PR_CHECK != 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
# pull_request_target: this checks out the BASE repo (trusted), so the allowlist
|
|
# we read below is this repo's version, never the fork's.
|
|
- uses: actions/checkout@v4
|
|
- name: Check if author has write access
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const fs = require('fs');
|
|
const author = context.payload.pull_request.user.login;
|
|
|
|
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
username: author
|
|
});
|
|
|
|
if (['admin', 'write'].includes(data.permission)) {
|
|
console.log(`${author} has ${data.permission} access, allowing PR`);
|
|
return;
|
|
}
|
|
|
|
// Allowlisted external contributors (e.g. enterprise partners who cannot use the
|
|
// submission form) may OPEN a PR. This does NOT grant merge: all CI still runs,
|
|
// the external-pr-scope-guard check constrains what they can change, and an
|
|
// Anthropic maintainer approval is still required by branch protection.
|
|
try {
|
|
const list = JSON.parse(fs.readFileSync('.github/external-contributors.json', 'utf8'));
|
|
const allowed = (list.contributors || []).some(
|
|
c => (c.github_username || '').toLowerCase() === author.toLowerCase()
|
|
);
|
|
if (allowed) {
|
|
console.log(`${author} is an allowlisted external contributor, allowing PR (scope guard + maintainer review still apply)`);
|
|
return;
|
|
}
|
|
} catch (e) {
|
|
console.log(`Could not read external-contributors allowlist: ${e.message}`);
|
|
}
|
|
|
|
console.log(`${author} has ${data.permission} access, closing PR`);
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.payload.pull_request.number,
|
|
body: `Thanks for your interest! This repo only accepts contributions from Anthropic team members. If you'd like to submit a plugin to the marketplace, please submit your plugin [here](https://clau.de/plugin-directory-submission).`
|
|
});
|
|
|
|
await github.rest.pulls.update({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: context.payload.pull_request.number,
|
|
state: 'closed'
|
|
});
|