Restrict @claude bot to mcp org only, fix fork behavior (#819)
Written by Claude Code, reviewed by me. ## Summary Fixes `@claude` to work on external fork PRs by: 1. Restricting triggers to modelcontextprotocol org members only 2. Properly checking out fork PR code via `refs/pull/N/head` ## Background The `@claude` GitHub app was failing on external forks ([example](https://github.com/modelcontextprotocol/registry/actions/runs/19938435814/job/57169634431)) because the action tried to fetch branches by name, which doesn't work for forks. ## Changes ### Org membership check - Fetches the member list from [`modelcontextprotocol/access`](https://github.com/modelcontextprotocol/access) repo's `users.ts` - Only org members can trigger `@claude` (prevents strangers from using it) - Uses `github.triggering_actor` so the person commenting must be an org member ### Fork PR checkout fix - Detects when a comment is on a fork PR - Uses `refs/pull/{number}/head` to checkout fork code (instead of branch name) - This works because GitHub exposes all PRs via special refs on the base repo ## How it works 1. Org member comments `@claude` on a fork PR 2. Workflow checks if commenter is in the `modelcontextprotocol/access` member list 3. Workflow detects it's a fork PR and checks out via `refs/pull/N/head` 4. Claude runs with access to the fork's code 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8b861e5e1a
commit
370453317d
1 changed files with 33 additions and 0 deletions
33
.github/workflows/claude.yml
vendored
33
.github/workflows/claude.yml
vendored
|
|
@ -25,10 +25,43 @@ jobs:
|
|||
id-token: write
|
||||
actions: read
|
||||
steps:
|
||||
# Only allow modelcontextprotocol org members to trigger @claude
|
||||
# This enables @claude to work on external fork PRs when triggered by org members
|
||||
# Members list is fetched from modelcontextprotocol/access repo
|
||||
- name: Check if org member
|
||||
run: |
|
||||
ACTOR="${{ github.triggering_actor }}"
|
||||
USERS_URL="https://raw.githubusercontent.com/modelcontextprotocol/access/main/src/config/users.ts"
|
||||
|
||||
# Fetch users.ts and extract GitHub usernames
|
||||
MEMBERS=$(curl -fsSL "$USERS_URL" | grep -oE 'github:\s*"[^"]+"' | sed 's/github:\s*"//;s/"$//')
|
||||
|
||||
if echo "$MEMBERS" | grep -qxF "$ACTOR"; then
|
||||
echo "User $ACTOR is a member of modelcontextprotocol org"
|
||||
else
|
||||
echo "::error::User $ACTOR is not a member of the modelcontextprotocol org. Only org members can trigger @claude."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# For PR comments, get PR details to checkout the correct branch (including forks)
|
||||
- name: Get PR details
|
||||
id: pr
|
||||
if: github.event.issue.pull_request
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
PR_DATA=$(gh api ${{ github.event.issue.pull_request.url }})
|
||||
echo "number=$(echo "$PR_DATA" | jq -r '.number')" >> $GITHUB_OUTPUT
|
||||
echo "head_ref=$(echo "$PR_DATA" | jq -r '.head.ref')" >> $GITHUB_OUTPUT
|
||||
echo "head_repo=$(echo "$PR_DATA" | jq -r '.head.repo.full_name')" >> $GITHUB_OUTPUT
|
||||
echo "is_fork=$(echo "$PR_DATA" | jq -r '.head.repo.fork')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
|
||||
with:
|
||||
fetch-depth: 1
|
||||
# For fork PRs, checkout via PR ref; otherwise use the branch directly
|
||||
ref: ${{ steps.pr.outputs.is_fork == 'true' && format('refs/pull/{0}/head', steps.pr.outputs.number) || steps.pr.outputs.head_ref || github.ref }}
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude
|
||||
|
|
|
|||
Loading…
Reference in a new issue