mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
* feat: add path_to_claude_code_executable input for custom Claude Code installations Adds optional input to specify a custom Claude Code executable path, bypassing automatic installation. This enables: - Using pre-installed Claude Code binaries - Testing with specific versions for debugging - Custom installation paths in unique environments Includes warning that older versions may cause compatibility issues with new features. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * test: add workflow to test custom Claude Code executable path Adds test workflow that: - Manually installs Claude Code via install script - Uses the new path_to_claude_code_executable input - Verifies the custom executable path works correctly - Validates output and execution success 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
314 lines
14 KiB
YAML
314 lines
14 KiB
YAML
name: "Claude Code Action Official"
|
|
description: "General-purpose Claude agent for GitHub PRs and issues. Can answer questions and implement code changes."
|
|
branding:
|
|
icon: "at-sign"
|
|
color: "orange"
|
|
|
|
inputs:
|
|
trigger_phrase:
|
|
description: "The trigger phrase to look for in comments or issue body"
|
|
required: false
|
|
default: "@claude"
|
|
assignee_trigger:
|
|
description: "The assignee username that triggers the action (e.g. @claude)"
|
|
required: false
|
|
label_trigger:
|
|
description: "The label that triggers the action (e.g. claude)"
|
|
required: false
|
|
default: "claude"
|
|
base_branch:
|
|
description: "The branch to use as the base/source when creating new branches (defaults to repository default branch)"
|
|
required: false
|
|
branch_prefix:
|
|
description: "The prefix to use for Claude branches (defaults to 'claude/', use 'claude-' for dash format)"
|
|
required: false
|
|
default: "claude/"
|
|
allowed_bots:
|
|
description: "Comma-separated list of allowed bot usernames, or '*' to allow all bots. Empty string (default) allows no bots."
|
|
required: false
|
|
default: ""
|
|
|
|
# Mode configuration
|
|
mode:
|
|
description: "Execution mode for the action. Valid modes: 'tag' (default - triggered by mentions/assignments), 'agent' (for automation with no trigger checking), 'experimental-review' (experimental mode for code reviews with inline comments and suggestions)"
|
|
required: false
|
|
default: "tag"
|
|
|
|
# Claude Code configuration
|
|
model:
|
|
description: "Model to use (provider-specific format required for Bedrock/Vertex)"
|
|
required: false
|
|
anthropic_model:
|
|
description: "DEPRECATED: Use 'model' instead. Model to use (provider-specific format required for Bedrock/Vertex)"
|
|
required: false
|
|
fallback_model:
|
|
description: "Enable automatic fallback to specified model when primary model is unavailable"
|
|
required: false
|
|
allowed_tools:
|
|
description: "Additional tools for Claude to use (the base GitHub tools will always be included)"
|
|
required: false
|
|
default: ""
|
|
disallowed_tools:
|
|
description: "Tools that Claude should never use"
|
|
required: false
|
|
default: ""
|
|
custom_instructions:
|
|
description: "Additional custom instructions to include in the prompt for Claude"
|
|
required: false
|
|
default: ""
|
|
direct_prompt:
|
|
description: "Direct instruction for Claude (bypasses normal trigger detection)"
|
|
required: false
|
|
default: ""
|
|
override_prompt:
|
|
description: "Complete replacement of Claude's prompt with custom template (supports variable substitution)"
|
|
required: false
|
|
default: ""
|
|
mcp_config:
|
|
description: "Additional MCP configuration (JSON string) that merges with the built-in GitHub MCP servers"
|
|
additional_permissions:
|
|
description: "Additional permissions to enable. Currently supports 'actions: read' for viewing workflow results"
|
|
required: false
|
|
default: ""
|
|
claude_env:
|
|
description: "Custom environment variables to pass to Claude Code execution (YAML format)"
|
|
required: false
|
|
default: ""
|
|
settings:
|
|
description: "Claude Code settings as JSON string or path to settings JSON file"
|
|
required: false
|
|
default: ""
|
|
|
|
# Auth configuration
|
|
anthropic_api_key:
|
|
description: "Anthropic API key (required for direct API, not needed for Bedrock/Vertex)"
|
|
required: false
|
|
claude_code_oauth_token:
|
|
description: "Claude Code OAuth token (alternative to anthropic_api_key)"
|
|
required: false
|
|
github_token:
|
|
description: "GitHub token with repo and pull request permissions (optional if using GitHub App)"
|
|
required: false
|
|
use_bedrock:
|
|
description: "Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API"
|
|
required: false
|
|
default: "false"
|
|
use_vertex:
|
|
description: "Use Google Vertex AI with OIDC authentication instead of direct Anthropic API"
|
|
required: false
|
|
default: "false"
|
|
|
|
max_turns:
|
|
description: "Maximum number of conversation turns"
|
|
required: false
|
|
default: ""
|
|
timeout_minutes:
|
|
description: "Timeout in minutes for execution"
|
|
required: false
|
|
default: "30"
|
|
use_sticky_comment:
|
|
description: "Use just one comment to deliver issue/PR comments"
|
|
required: false
|
|
default: "false"
|
|
use_commit_signing:
|
|
description: "Enable commit signing using GitHub's commit signature verification. When false, Claude uses standard git commands"
|
|
required: false
|
|
default: "false"
|
|
experimental_allowed_domains:
|
|
description: "Restrict network access to these domains only (newline-separated). If not set, no restrictions are applied. Provider domains are auto-detected."
|
|
required: false
|
|
default: ""
|
|
path_to_claude_code_executable:
|
|
description: "Optional path to a custom Claude Code executable. If provided, skips automatic installation and uses this executable instead. WARNING: Using an older version may cause problems if the action begins taking advantage of new Claude Code features. This input is typically not needed unless you're debugging something specific or have unique needs in your environment."
|
|
required: false
|
|
default: ""
|
|
|
|
outputs:
|
|
execution_file:
|
|
description: "Path to the Claude Code execution output file"
|
|
value: ${{ steps.claude-code.outputs.execution_file }}
|
|
branch_name:
|
|
description: "The branch created by Claude Code for this execution"
|
|
value: ${{ steps.prepare.outputs.CLAUDE_BRANCH }}
|
|
|
|
runs:
|
|
using: "composite"
|
|
steps:
|
|
- name: Install Bun
|
|
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # https://github.com/oven-sh/setup-bun/releases/tag/v2.0.2
|
|
with:
|
|
bun-version: 1.2.11
|
|
|
|
- name: Install Dependencies
|
|
shell: bash
|
|
run: |
|
|
cd ${GITHUB_ACTION_PATH}
|
|
bun install
|
|
|
|
- name: Prepare action
|
|
id: prepare
|
|
shell: bash
|
|
run: |
|
|
bun run ${GITHUB_ACTION_PATH}/src/entrypoints/prepare.ts
|
|
env:
|
|
MODE: ${{ inputs.mode }}
|
|
TRIGGER_PHRASE: ${{ inputs.trigger_phrase }}
|
|
ASSIGNEE_TRIGGER: ${{ inputs.assignee_trigger }}
|
|
LABEL_TRIGGER: ${{ inputs.label_trigger }}
|
|
BASE_BRANCH: ${{ inputs.base_branch }}
|
|
BRANCH_PREFIX: ${{ inputs.branch_prefix }}
|
|
ALLOWED_TOOLS: ${{ inputs.allowed_tools }}
|
|
DISALLOWED_TOOLS: ${{ inputs.disallowed_tools }}
|
|
CUSTOM_INSTRUCTIONS: ${{ inputs.custom_instructions }}
|
|
DIRECT_PROMPT: ${{ inputs.direct_prompt }}
|
|
OVERRIDE_PROMPT: ${{ inputs.override_prompt }}
|
|
MCP_CONFIG: ${{ inputs.mcp_config }}
|
|
OVERRIDE_GITHUB_TOKEN: ${{ inputs.github_token }}
|
|
ALLOWED_BOTS: ${{ inputs.allowed_bots }}
|
|
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
USE_STICKY_COMMENT: ${{ inputs.use_sticky_comment }}
|
|
DEFAULT_WORKFLOW_TOKEN: ${{ github.token }}
|
|
ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }}
|
|
USE_COMMIT_SIGNING: ${{ inputs.use_commit_signing }}
|
|
ALL_INPUTS: ${{ toJson(inputs) }}
|
|
|
|
- name: Install Base Action Dependencies
|
|
if: steps.prepare.outputs.contains_trigger == 'true'
|
|
shell: bash
|
|
run: |
|
|
echo "Installing base-action dependencies..."
|
|
cd ${GITHUB_ACTION_PATH}/base-action
|
|
bun install
|
|
echo "Base-action dependencies installed"
|
|
cd -
|
|
|
|
# Install Claude Code if no custom executable is provided
|
|
if [ -z "${{ inputs.path_to_claude_code_executable }}" ]; then
|
|
echo "Installing Claude Code..."
|
|
curl -fsSL https://claude.ai/install.sh | bash -s 1.0.90
|
|
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
else
|
|
echo "Using custom Claude Code executable: ${{ inputs.path_to_claude_code_executable }}"
|
|
# Add the directory containing the custom executable to PATH
|
|
CLAUDE_DIR=$(dirname "${{ inputs.path_to_claude_code_executable }}")
|
|
echo "$CLAUDE_DIR" >> "$GITHUB_PATH"
|
|
fi
|
|
|
|
- name: Setup Network Restrictions
|
|
if: steps.prepare.outputs.contains_trigger == 'true' && inputs.experimental_allowed_domains != ''
|
|
shell: bash
|
|
run: |
|
|
chmod +x ${GITHUB_ACTION_PATH}/scripts/setup-network-restrictions.sh
|
|
${GITHUB_ACTION_PATH}/scripts/setup-network-restrictions.sh
|
|
env:
|
|
EXPERIMENTAL_ALLOWED_DOMAINS: ${{ inputs.experimental_allowed_domains }}
|
|
|
|
- name: Run Claude Code
|
|
id: claude-code
|
|
if: steps.prepare.outputs.contains_trigger == 'true'
|
|
shell: bash
|
|
run: |
|
|
|
|
# Run the base-action
|
|
bun run ${GITHUB_ACTION_PATH}/base-action/src/index.ts
|
|
env:
|
|
# Base-action inputs
|
|
CLAUDE_CODE_ACTION: "1"
|
|
INPUT_PROMPT_FILE: ${{ runner.temp }}/claude-prompts/claude-prompt.txt
|
|
INPUT_ALLOWED_TOOLS: ${{ env.ALLOWED_TOOLS }}
|
|
INPUT_DISALLOWED_TOOLS: ${{ env.DISALLOWED_TOOLS }}
|
|
INPUT_MAX_TURNS: ${{ inputs.max_turns }}
|
|
INPUT_MCP_CONFIG: ${{ steps.prepare.outputs.mcp_config }}
|
|
INPUT_SETTINGS: ${{ inputs.settings }}
|
|
INPUT_SYSTEM_PROMPT: ""
|
|
INPUT_APPEND_SYSTEM_PROMPT: ${{ env.APPEND_SYSTEM_PROMPT }}
|
|
INPUT_TIMEOUT_MINUTES: ${{ inputs.timeout_minutes }}
|
|
INPUT_CLAUDE_ENV: ${{ inputs.claude_env }}
|
|
INPUT_FALLBACK_MODEL: ${{ inputs.fallback_model }}
|
|
INPUT_EXPERIMENTAL_SLASH_COMMANDS_DIR: ${{ github.action_path }}/slash-commands
|
|
INPUT_ACTION_INPUTS_PRESENT: ${{ steps.prepare.outputs.action_inputs_present }}
|
|
INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE: ${{ inputs.path_to_claude_code_executable }}
|
|
|
|
# Model configuration
|
|
ANTHROPIC_MODEL: ${{ inputs.model || inputs.anthropic_model }}
|
|
GITHUB_TOKEN: ${{ steps.prepare.outputs.GITHUB_TOKEN }}
|
|
NODE_VERSION: ${{ env.NODE_VERSION }}
|
|
DETAILED_PERMISSION_MESSAGES: "1"
|
|
|
|
# Provider configuration
|
|
ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }}
|
|
CLAUDE_CODE_OAUTH_TOKEN: ${{ inputs.claude_code_oauth_token }}
|
|
ANTHROPIC_BASE_URL: ${{ env.ANTHROPIC_BASE_URL }}
|
|
CLAUDE_CODE_USE_BEDROCK: ${{ inputs.use_bedrock == 'true' && '1' || '' }}
|
|
CLAUDE_CODE_USE_VERTEX: ${{ inputs.use_vertex == 'true' && '1' || '' }}
|
|
|
|
# AWS configuration
|
|
AWS_REGION: ${{ env.AWS_REGION }}
|
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
|
AWS_SESSION_TOKEN: ${{ env.AWS_SESSION_TOKEN }}
|
|
ANTHROPIC_BEDROCK_BASE_URL: ${{ env.ANTHROPIC_BEDROCK_BASE_URL || (env.AWS_REGION && format('https://bedrock-runtime.{0}.amazonaws.com', env.AWS_REGION)) }}
|
|
|
|
# GCP configuration
|
|
ANTHROPIC_VERTEX_PROJECT_ID: ${{ env.ANTHROPIC_VERTEX_PROJECT_ID }}
|
|
CLOUD_ML_REGION: ${{ env.CLOUD_ML_REGION }}
|
|
GOOGLE_APPLICATION_CREDENTIALS: ${{ env.GOOGLE_APPLICATION_CREDENTIALS }}
|
|
ANTHROPIC_VERTEX_BASE_URL: ${{ env.ANTHROPIC_VERTEX_BASE_URL }}
|
|
|
|
# Model-specific regions for Vertex
|
|
VERTEX_REGION_CLAUDE_3_5_HAIKU: ${{ env.VERTEX_REGION_CLAUDE_3_5_HAIKU }}
|
|
VERTEX_REGION_CLAUDE_3_5_SONNET: ${{ env.VERTEX_REGION_CLAUDE_3_5_SONNET }}
|
|
VERTEX_REGION_CLAUDE_3_7_SONNET: ${{ env.VERTEX_REGION_CLAUDE_3_7_SONNET }}
|
|
|
|
- name: Update comment with job link
|
|
if: steps.prepare.outputs.contains_trigger == 'true' && steps.prepare.outputs.claude_comment_id && always()
|
|
shell: bash
|
|
run: |
|
|
bun run ${GITHUB_ACTION_PATH}/src/entrypoints/update-comment-link.ts
|
|
env:
|
|
REPOSITORY: ${{ github.repository }}
|
|
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
|
|
CLAUDE_COMMENT_ID: ${{ steps.prepare.outputs.claude_comment_id }}
|
|
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
GITHUB_TOKEN: ${{ steps.prepare.outputs.GITHUB_TOKEN }}
|
|
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
|
TRIGGER_COMMENT_ID: ${{ github.event.comment.id }}
|
|
CLAUDE_BRANCH: ${{ steps.prepare.outputs.CLAUDE_BRANCH }}
|
|
IS_PR: ${{ github.event.issue.pull_request != null || github.event_name == 'pull_request_review_comment' }}
|
|
BASE_BRANCH: ${{ steps.prepare.outputs.BASE_BRANCH }}
|
|
CLAUDE_SUCCESS: ${{ steps.claude-code.outputs.conclusion == 'success' }}
|
|
OUTPUT_FILE: ${{ steps.claude-code.outputs.execution_file || '' }}
|
|
TRIGGER_USERNAME: ${{ github.event.comment.user.login || github.event.issue.user.login || github.event.pull_request.user.login || github.event.sender.login || github.triggering_actor || github.actor || '' }}
|
|
PREPARE_SUCCESS: ${{ steps.prepare.outcome == 'success' }}
|
|
PREPARE_ERROR: ${{ steps.prepare.outputs.prepare_error || '' }}
|
|
USE_STICKY_COMMENT: ${{ inputs.use_sticky_comment }}
|
|
USE_COMMIT_SIGNING: ${{ inputs.use_commit_signing }}
|
|
|
|
- name: Display Claude Code Report
|
|
if: steps.prepare.outputs.contains_trigger == 'true' && steps.claude-code.outputs.execution_file != ''
|
|
shell: bash
|
|
run: |
|
|
# Try to format the turns, but if it fails, dump the raw JSON
|
|
if bun run ${{ github.action_path }}/src/entrypoints/format-turns.ts "${{ steps.claude-code.outputs.execution_file }}" >> $GITHUB_STEP_SUMMARY 2>/dev/null; then
|
|
echo "Successfully formatted Claude Code report"
|
|
else
|
|
echo "## Claude Code Report (Raw Output)" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "Failed to format output (please report). Here's the raw JSON:" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo '```json' >> $GITHUB_STEP_SUMMARY
|
|
cat "${{ steps.claude-code.outputs.execution_file }}" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
- name: Revoke app token
|
|
if: always() && inputs.github_token == '' && steps.prepare.outputs.skipped_due_to_workflow_validation_mismatch != 'true'
|
|
shell: bash
|
|
run: |
|
|
curl -L \
|
|
-X DELETE \
|
|
-H "Accept: application/vnd.github+json" \
|
|
-H "Authorization: Bearer ${{ steps.prepare.outputs.GITHUB_TOKEN }}" \
|
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
|
${GITHUB_API_URL:-https://api.github.com}/installation/token
|