Skip to content

Claude

Claude #546

Workflow file for this run

# Copyright (c) Facebook, Inc. and its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Claude — skill-based PR assistant (replaces claude-review.yml)
#
# This workflow uses izaitsevfb/claude-code-action (a fork that fixes
# forked-PR handling) with Claude Skills instead of inline prompts.
# Review logic lives in .claude/skills/pr-review/SKILL.md.
#
# Supported commands (comment on a PR):
# @claude /pr-review [context] — thorough code review
# @claude /query <question> — ask about the PR or codebase
#
# Differences from claude-review.yml (the legacy workflow):
# - Uses claude-code-action (higher-level) instead of claude-code-base-action
# - Review/query instructions are in Skills, not inline heredocs
# - Trigger phrase is @claude (not /claude-review or /claude-query)
# - Tag mode handles PR context, diff, and comment posting automatically
#
# Security model:
# - Hardcoded user allowlist gates workflow execution
# - Read-only tools enforced via --allowedTools
# - Fork PRs handled securely by the action fork
name: Claude
on:
# Tag mode: action detects @claude in comments and responds inline
issue_comment:
types: [created]
# Agent mode: manual trigger for testing (log-only when dry_run is true)
workflow_dispatch:
inputs:
pr_number:
description: PR number to review
required: true
type: number
model:
description: Claude model to use
required: false
type: choice
options:
- claude-opus-4-6
- claude-opus-4-1-20250805
- claude-sonnet-4-20250514
- claude-4-0-sonnet-20250805
default: claude-opus-4-6
additional_context:
description: Additional instructions for the review (e.g. focus on memory safety)
required: false
type: string
default: ''
dry_run:
description: Log review output only — do not post a comment on the PR
required: false
type: boolean
default: false
# Restrict default permissions — jobs declare only what they need
permissions:
contents: read
jobs:
claude-assistant:
name: Claude Assistant
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
actions: read
id-token: write
# Gate: workflow_dispatch always runs; issue_comment requires PR context,
# @claude mention, and an authorized user
if: >-
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '@claude') &&
contains(fromJSON('["kgpai", "mbasmanova", "pedroerp", "yuhta", "kagamiori", "bikramSingh91", "kevinwilfong", "xiaoxmeng", "kKPulla", "juwentus1234", "penescu", "srsuryadev", "jainxrohit", "pratikpugalia"]'), github.event.comment.user.login)
)
steps:
# For workflow_dispatch, checkout the PR merge ref so Claude has the
# PR code. For issue_comment, default ref is fine — the action handles
# diff fetching internally.
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 1
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/pull/{0}/merge', inputs.pr_number) || '' }}
persist-credentials: false
# Build prompt and claude_args in bash to avoid format() curly-brace
# issues with user-supplied additional_context, and to keep the logic
# readable. Outputs are only set for workflow_dispatch; for
# issue_comment (tag mode), prompt stays empty so the action uses
# tag mode and CLAUDE.md provides skill routing.
- name: Build prompt and args
id: config
if: github.event_name == 'workflow_dispatch'
env:
INPUT_PR_NUMBER: ${{ inputs.pr_number }}
INPUT_MODEL: ${{ inputs.model }}
INPUT_DRY_RUN: ${{ inputs.dry_run }}
INPUT_ADDITIONAL_CONTEXT: ${{ inputs.additional_context }}
run: |
# --- Prompt ---
PROMPT="Review the PR currently checked out in the Velox project current workspace. Use the /pr-review skill."
if [ "$INPUT_DRY_RUN" = "true" ]; then
PROMPT="$PROMPT Output the review to the workflow log only. Do NOT post any comments on the PR."
else
PROMPT="$PROMPT Post the final output as a comment on the original PR ${INPUT_PR_NUMBER}."
fi
if [ -n "$INPUT_ADDITIONAL_CONTEXT" ]; then
PROMPT="$PROMPT Additional reviewer instructions: ${INPUT_ADDITIONAL_CONTEXT}"
fi
# Write multi-line safe output
{
echo "prompt<<PROMPT_EOF"
echo "$PROMPT"
echo "PROMPT_EOF"
} >> "$GITHUB_OUTPUT"
# --- Allowed tools ---
TOOLS="Skill"
# Comment-posting tools only when NOT dry_run
if [ "$INPUT_DRY_RUN" != "true" ]; then
TOOLS="$TOOLS,Bash(gh pr comment:*)"
TOOLS="$TOOLS,mcp__github_inline_comment__create_inline_comment"
fi
# Read-only PR tools (always available for workflow_dispatch)
TOOLS="$TOOLS,Bash(gh pr diff:*),Bash(gh pr view:*)"
# Codebase exploration tools
TOOLS="$TOOLS,Read,Glob,Grep"
ARGS="--model ${INPUT_MODEL:-claude-opus-4-6} --allowedTools ${TOOLS}"
echo "claude_args=$ARGS" >> "$GITHUB_OUTPUT"
- name: Run Claude Code
uses: izaitsevfb/claude-code-action@ececd56fb999d06b4dd2477437bc408938295d76 # forked-pr-fix
with:
trigger_phrase: "@claude"
# prompt is only set for workflow_dispatch (agent mode).
# For issue_comment (tag mode), prompt must be empty so the action
# uses tag mode; CLAUDE.md provides skill routing instead.
prompt: ${{ steps.config.outputs.prompt || '' }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# Tool access (workflow_dispatch uses computed args from setup step):
# - Skill: invoke /pr-review and /query skills
# - Read,Glob,Grep: codebase exploration (used by skills)
# - mcp__github_inline_comment: post inline comments (excluded in dry_run)
# - Bash(gh pr comment/diff/view): gh CLI for PR data (comment excluded in dry_run)
claude_args: ${{ steps.config.outputs.claude_args || '--model claude-opus-4-6 --allowedTools Skill,mcp__github_inline_comment__create_inline_comment,Read,Glob,Grep' }}
settings: '{"alwaysThinkingEnabled": true}'
# Notify unauthorized users who try to invoke @claude
unauthorized-notice:
name: Unauthorized Notice
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
if: >-
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '@claude') &&
!contains(fromJSON('["kgpai", "mbasmanova", "pedroerp", "yuhta", "kagamiori", "bikramSingh91", "kevinwilfong", "xiaoxmeng", "kKPulla", "juwentus1234", "penescu", "srsuryadev", "jainxrohit", "pratikpugalia"]'), github.event.comment.user.login)
steps:
- name: Post unauthorized notice
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `👋 @${context.payload.comment.user.login}, \`@claude\` commands are currently restricted to a small group of users during this initial rollout.\n\nIf you'd like a Claude review, please ask a maintainer to run this command.`
});