mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 15:04:13 +08:00
Compare commits
6 Commits
v1.0.27
...
boris/add-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91a8d6c8d8 | ||
|
|
8151408b90 | ||
|
|
154d0de144 | ||
|
|
3ba9f7c8c2 | ||
|
|
e5b07416ea | ||
|
|
b89827f8d1 |
132
.github/workflows/bump-claude-code-version.yml
vendored
132
.github/workflows/bump-claude-code-version.yml
vendored
@@ -1,132 +0,0 @@
|
|||||||
name: Bump Claude Code Version
|
|
||||||
|
|
||||||
on:
|
|
||||||
repository_dispatch:
|
|
||||||
types: [bump_claude_code_version]
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: "Claude Code version to bump to"
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
bump-version:
|
|
||||||
name: Bump Claude Code Version
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: release
|
|
||||||
timeout-minutes: 5
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.RELEASE_PAT }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Get version from event payload
|
|
||||||
id: get_version
|
|
||||||
run: |
|
|
||||||
# Get version from either repository_dispatch or workflow_dispatch
|
|
||||||
if [ "${{ github.event_name }}" = "repository_dispatch" ]; then
|
|
||||||
NEW_VERSION="${CLIENT_PAYLOAD_VERSION}"
|
|
||||||
else
|
|
||||||
NEW_VERSION="${INPUT_VERSION}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Sanitize the version to avoid issues enabled by problematic characters
|
|
||||||
NEW_VERSION=$(echo "$NEW_VERSION" | tr -d '`;$(){}[]|&<>' | tr -s ' ' '-')
|
|
||||||
|
|
||||||
if [ -z "$NEW_VERSION" ]; then
|
|
||||||
echo "Error: version not provided"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
|
|
||||||
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
|
||||||
env:
|
|
||||||
INPUT_VERSION: ${{ inputs.version }}
|
|
||||||
CLIENT_PAYLOAD_VERSION: ${{ github.event.client_payload.version }}
|
|
||||||
|
|
||||||
- name: Create branch and update base-action/action.yml
|
|
||||||
run: |
|
|
||||||
# Variables
|
|
||||||
TIMESTAMP=$(date +'%Y%m%d-%H%M%S')
|
|
||||||
BRANCH_NAME="bump-claude-code-${{ env.NEW_VERSION }}-$TIMESTAMP"
|
|
||||||
|
|
||||||
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# Get the default branch
|
|
||||||
DEFAULT_BRANCH=$(gh api repos/${GITHUB_REPOSITORY} --jq '.default_branch')
|
|
||||||
echo "DEFAULT_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# Get the latest commit SHA from the default branch
|
|
||||||
BASE_SHA=$(gh api repos/${GITHUB_REPOSITORY}/git/refs/heads/$DEFAULT_BRANCH --jq '.object.sha')
|
|
||||||
|
|
||||||
# Create a new branch
|
|
||||||
gh api \
|
|
||||||
--method POST \
|
|
||||||
repos/${GITHUB_REPOSITORY}/git/refs \
|
|
||||||
-f ref="refs/heads/$BRANCH_NAME" \
|
|
||||||
-f sha="$BASE_SHA"
|
|
||||||
|
|
||||||
# Get the current base-action/action.yml content
|
|
||||||
ACTION_CONTENT=$(gh api repos/${GITHUB_REPOSITORY}/contents/base-action/action.yml?ref=$DEFAULT_BRANCH --jq '.content' | base64 -d)
|
|
||||||
|
|
||||||
# Update the Claude Code version in the npm install command
|
|
||||||
UPDATED_CONTENT=$(echo "$ACTION_CONTENT" | sed -E "s/(npm install -g @anthropic-ai\/claude-code@)[0-9]+\.[0-9]+\.[0-9]+/\1${{ env.NEW_VERSION }}/")
|
|
||||||
|
|
||||||
# Verify the change would be made
|
|
||||||
if ! echo "$UPDATED_CONTENT" | grep -q "@anthropic-ai/claude-code@${{ env.NEW_VERSION }}"; then
|
|
||||||
echo "Error: Failed to update Claude Code version in content"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the current SHA of base-action/action.yml for the update API call
|
|
||||||
FILE_SHA=$(gh api repos/${GITHUB_REPOSITORY}/contents/base-action/action.yml?ref=$DEFAULT_BRANCH --jq '.sha')
|
|
||||||
|
|
||||||
# Create the updated base-action/action.yml content in base64
|
|
||||||
echo "$UPDATED_CONTENT" | base64 > action.yml.b64
|
|
||||||
|
|
||||||
# Commit the updated base-action/action.yml via GitHub API
|
|
||||||
gh api \
|
|
||||||
--method PUT \
|
|
||||||
repos/${GITHUB_REPOSITORY}/contents/base-action/action.yml \
|
|
||||||
-f message="chore: bump Claude Code version to ${{ env.NEW_VERSION }}" \
|
|
||||||
-F content=@action.yml.b64 \
|
|
||||||
-f sha="$FILE_SHA" \
|
|
||||||
-f branch="$BRANCH_NAME"
|
|
||||||
|
|
||||||
echo "Successfully created branch and updated Claude Code version to ${{ env.NEW_VERSION }}"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
|
|
||||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
||||||
|
|
||||||
- name: Create Pull Request
|
|
||||||
run: |
|
|
||||||
# Determine trigger type for PR body
|
|
||||||
if [ "${{ github.event_name }}" = "repository_dispatch" ]; then
|
|
||||||
TRIGGER_INFO="repository dispatch event"
|
|
||||||
else
|
|
||||||
TRIGGER_INFO="manual workflow dispatch by @${GITHUB_ACTOR}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create PR body with proper YAML escape
|
|
||||||
printf -v PR_BODY "## Bump Claude Code to ${{ env.NEW_VERSION }}\n\nThis PR updates the Claude Code version in base-action/action.yml to ${{ env.NEW_VERSION }}.\n\n### Changes\n- Updated Claude Code version from current to \`${{ env.NEW_VERSION }}\`\n\n### Triggered by\n- $TRIGGER_INFO\n\n🤖 This PR was automatically created by the bump-claude-code-version workflow."
|
|
||||||
|
|
||||||
echo "Creating PR with gh pr create command"
|
|
||||||
PR_URL=$(gh pr create \
|
|
||||||
--repo "${GITHUB_REPOSITORY}" \
|
|
||||||
--title "chore: bump Claude Code version to ${{ env.NEW_VERSION }}" \
|
|
||||||
--body "$PR_BODY" \
|
|
||||||
--base "${DEFAULT_BRANCH}" \
|
|
||||||
--head "${BRANCH_NAME}")
|
|
||||||
|
|
||||||
echo "PR created successfully: $PR_URL"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
|
|
||||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
||||||
GITHUB_ACTOR: ${{ github.actor }}
|
|
||||||
DEFAULT_BRANCH: ${{ env.DEFAULT_BRANCH }}
|
|
||||||
BRANCH_NAME: ${{ env.BRANCH_NAME }}
|
|
||||||
@@ -93,6 +93,10 @@ inputs:
|
|||||||
description: "Force tag mode with tracking comments for pull_request and issue events. Only applicable to pull_request (opened, synchronize, ready_for_review, reopened) and issue (opened, edited, labeled, assigned) events."
|
description: "Force tag mode with tracking comments for pull_request and issue events. Only applicable to pull_request (opened, synchronize, ready_for_review, reopened) and issue (opened, edited, labeled, assigned) events."
|
||||||
required: false
|
required: false
|
||||||
default: "false"
|
default: "false"
|
||||||
|
include_fix_links:
|
||||||
|
description: "Include 'Fix this' links in PR code review feedback that open Claude Code with context to fix the identified issue"
|
||||||
|
required: false
|
||||||
|
default: "true"
|
||||||
path_to_claude_code_executable:
|
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."
|
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
|
required: false
|
||||||
@@ -180,6 +184,7 @@ runs:
|
|||||||
BOT_ID: ${{ inputs.bot_id }}
|
BOT_ID: ${{ inputs.bot_id }}
|
||||||
BOT_NAME: ${{ inputs.bot_name }}
|
BOT_NAME: ${{ inputs.bot_name }}
|
||||||
TRACK_PROGRESS: ${{ inputs.track_progress }}
|
TRACK_PROGRESS: ${{ inputs.track_progress }}
|
||||||
|
INCLUDE_FIX_LINKS: ${{ inputs.include_fix_links }}
|
||||||
ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }}
|
ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }}
|
||||||
CLAUDE_ARGS: ${{ inputs.claude_args }}
|
CLAUDE_ARGS: ${{ inputs.claude_args }}
|
||||||
ALL_INPUTS: ${{ toJson(inputs) }}
|
ALL_INPUTS: ${{ toJson(inputs) }}
|
||||||
@@ -198,7 +203,7 @@ runs:
|
|||||||
|
|
||||||
# Install Claude Code if no custom executable is provided
|
# Install Claude Code if no custom executable is provided
|
||||||
if [ -z "$PATH_TO_CLAUDE_CODE_EXECUTABLE" ]; then
|
if [ -z "$PATH_TO_CLAUDE_CODE_EXECUTABLE" ]; then
|
||||||
CLAUDE_CODE_VERSION="2.0.74"
|
CLAUDE_CODE_VERSION="2.0.76"
|
||||||
echo "Installing Claude Code v${CLAUDE_CODE_VERSION}..."
|
echo "Installing Claude Code v${CLAUDE_CODE_VERSION}..."
|
||||||
for attempt in 1 2 3; do
|
for attempt in 1 2 3; do
|
||||||
echo "Installation attempt $attempt..."
|
echo "Installation attempt $attempt..."
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ runs:
|
|||||||
PATH_TO_CLAUDE_CODE_EXECUTABLE: ${{ inputs.path_to_claude_code_executable }}
|
PATH_TO_CLAUDE_CODE_EXECUTABLE: ${{ inputs.path_to_claude_code_executable }}
|
||||||
run: |
|
run: |
|
||||||
if [ -z "$PATH_TO_CLAUDE_CODE_EXECUTABLE" ]; then
|
if [ -z "$PATH_TO_CLAUDE_CODE_EXECUTABLE" ]; then
|
||||||
CLAUDE_CODE_VERSION="2.0.74"
|
CLAUDE_CODE_VERSION="2.0.76"
|
||||||
echo "Installing Claude Code v${CLAUDE_CODE_VERSION}..."
|
echo "Installing Claude Code v${CLAUDE_CODE_VERSION}..."
|
||||||
for attempt in 1 2 3; do
|
for attempt in 1 2 3; do
|
||||||
echo "Installation attempt $attempt..."
|
echo "Installation attempt $attempt..."
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"name": "@anthropic-ai/claude-code-base-action",
|
"name": "@anthropic-ai/claude-code-base-action",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@anthropic-ai/claude-agent-sdk": "^0.1.74",
|
"@anthropic-ai/claude-agent-sdk": "^0.1.76",
|
||||||
"shell-quote": "^1.8.3",
|
"shell-quote": "^1.8.3",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
|
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.1.74", "", { "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.33.5", "@img/sharp-darwin-x64": "^0.33.5", "@img/sharp-linux-arm": "^0.33.5", "@img/sharp-linux-arm64": "^0.33.5", "@img/sharp-linux-x64": "^0.33.5", "@img/sharp-linuxmusl-arm64": "^0.33.5", "@img/sharp-linuxmusl-x64": "^0.33.5", "@img/sharp-win32-x64": "^0.33.5" }, "peerDependencies": { "zod": "^3.24.1 || ^4.0.0" } }, "sha512-d6H3Oo625WAG3BrBFKJsuSshi4f0amc0kTJTm83LRPPFxn9kfq58FX4Oxxt+RUD9N3QumW9sQSEDnri20/F4qQ=="],
|
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.1.76", "", { "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.33.5", "@img/sharp-darwin-x64": "^0.33.5", "@img/sharp-linux-arm": "^0.33.5", "@img/sharp-linux-arm64": "^0.33.5", "@img/sharp-linux-x64": "^0.33.5", "@img/sharp-linuxmusl-arm64": "^0.33.5", "@img/sharp-linuxmusl-x64": "^0.33.5", "@img/sharp-win32-x64": "^0.33.5" }, "peerDependencies": { "zod": "^3.24.1 || ^4.0.0" } }, "sha512-s7RvpXoFaLXLG7A1cJBAPD8ilwOhhc/12fb5mJXRuD561o4FmPtQ+WRfuy9akMmrFRfLsKv8Ornw3ClGAPL2fw=="],
|
||||||
|
|
||||||
"@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="],
|
"@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="],
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@anthropic-ai/claude-agent-sdk": "^0.1.74",
|
"@anthropic-ai/claude-agent-sdk": "^0.1.76",
|
||||||
"shell-quote": "^1.8.3"
|
"shell-quote": "^1.8.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
4
bun.lock
4
bun.lock
@@ -7,7 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@actions/github": "^6.0.1",
|
"@actions/github": "^6.0.1",
|
||||||
"@anthropic-ai/claude-agent-sdk": "^0.1.74",
|
"@anthropic-ai/claude-agent-sdk": "^0.1.76",
|
||||||
"@modelcontextprotocol/sdk": "^1.11.0",
|
"@modelcontextprotocol/sdk": "^1.11.0",
|
||||||
"@octokit/graphql": "^8.2.2",
|
"@octokit/graphql": "^8.2.2",
|
||||||
"@octokit/rest": "^21.1.1",
|
"@octokit/rest": "^21.1.1",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
|
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.1.74", "", { "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.33.5", "@img/sharp-darwin-x64": "^0.33.5", "@img/sharp-linux-arm": "^0.33.5", "@img/sharp-linux-arm64": "^0.33.5", "@img/sharp-linux-x64": "^0.33.5", "@img/sharp-linuxmusl-arm64": "^0.33.5", "@img/sharp-linuxmusl-x64": "^0.33.5", "@img/sharp-win32-x64": "^0.33.5" }, "peerDependencies": { "zod": "^3.24.1 || ^4.0.0" } }, "sha512-d6H3Oo625WAG3BrBFKJsuSshi4f0amc0kTJTm83LRPPFxn9kfq58FX4Oxxt+RUD9N3QumW9sQSEDnri20/F4qQ=="],
|
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.1.76", "", { "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.33.5", "@img/sharp-darwin-x64": "^0.33.5", "@img/sharp-linux-arm": "^0.33.5", "@img/sharp-linux-arm64": "^0.33.5", "@img/sharp-linux-x64": "^0.33.5", "@img/sharp-linuxmusl-arm64": "^0.33.5", "@img/sharp-linuxmusl-x64": "^0.33.5", "@img/sharp-win32-x64": "^0.33.5" }, "peerDependencies": { "zod": "^3.24.1 || ^4.0.0" } }, "sha512-s7RvpXoFaLXLG7A1cJBAPD8ilwOhhc/12fb5mJXRuD561o4FmPtQ+WRfuy9akMmrFRfLsKv8Ornw3ClGAPL2fw=="],
|
||||||
|
|
||||||
"@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="],
|
"@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="],
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ You can authenticate with Claude using any of these four methods:
|
|||||||
3. Google Vertex AI with OIDC authentication
|
3. Google Vertex AI with OIDC authentication
|
||||||
4. Microsoft Foundry with OIDC authentication
|
4. Microsoft Foundry with OIDC authentication
|
||||||
|
|
||||||
For detailed setup instructions for AWS Bedrock and Google Vertex AI, see the [official documentation](https://docs.anthropic.com/en/docs/claude-code/github-actions#using-with-aws-bedrock-%26-google-vertex-ai).
|
For detailed setup instructions for AWS Bedrock and Google Vertex AI, see the [official documentation](https://code.claude.com/docs/en/github-actions#for-aws-bedrock:).
|
||||||
|
|
||||||
**Note**:
|
**Note**:
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ This action supports the following GitHub events ([learn more GitHub event trigg
|
|||||||
- `issues` - When issues are opened or assigned
|
- `issues` - When issues are opened or assigned
|
||||||
- `pull_request_review` - When PR reviews are submitted
|
- `pull_request_review` - When PR reviews are submitted
|
||||||
- `pull_request_review_comment` - When comments are made on PR reviews
|
- `pull_request_review_comment` - When comments are made on PR reviews
|
||||||
|
- `push` - When commits are pushed to a branch
|
||||||
- `repository_dispatch` - Custom events triggered via API
|
- `repository_dispatch` - Custom events triggered via API
|
||||||
- `workflow_dispatch` - Manual workflow triggers (coming soon)
|
- `workflow_dispatch` - Manual workflow triggers (coming soon)
|
||||||
|
|
||||||
@@ -120,3 +121,42 @@ For more control over Claude's behavior, use the `claude_args` input to pass CLI
|
|||||||
```
|
```
|
||||||
|
|
||||||
This provides full access to Claude Code CLI capabilities while maintaining the simplified action interface.
|
This provides full access to Claude Code CLI capabilities while maintaining the simplified action interface.
|
||||||
|
|
||||||
|
## Auto-Rebase PRs on Push
|
||||||
|
|
||||||
|
Automatically keep PRs up to date when the main branch is updated:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Auto-Rebase PRs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
rebase-prs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: anthropics/claude-code-action@v1
|
||||||
|
with:
|
||||||
|
prompt: |
|
||||||
|
Find all open PRs that are behind main and merge main into them.
|
||||||
|
For each PR:
|
||||||
|
1. Check out the PR branch
|
||||||
|
2. Merge main into the branch
|
||||||
|
3. Push the updated branch
|
||||||
|
|
||||||
|
Skip any PRs with merge conflicts - just report them.
|
||||||
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
|
```
|
||||||
|
|
||||||
|
This workflow triggers whenever commits are pushed to main and uses Claude to automatically merge main into any stale PR branches, keeping them up to date.
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ jobs:
|
|||||||
| `claude_code_oauth_token` | Claude Code OAuth token (alternative to anthropic_api_key) | No\* | - |
|
| `claude_code_oauth_token` | Claude Code OAuth token (alternative to anthropic_api_key) | No\* | - |
|
||||||
| `prompt` | Instructions for Claude. Can be a direct prompt or custom template for automation workflows | No | - |
|
| `prompt` | Instructions for Claude. Can be a direct prompt or custom template for automation workflows | No | - |
|
||||||
| `track_progress` | Force tag mode with tracking comments. Only works with specific PR/issue events. Preserves GitHub context | No | `false` |
|
| `track_progress` | Force tag mode with tracking comments. Only works with specific PR/issue events. Preserves GitHub context | No | `false` |
|
||||||
|
| `include_fix_links` | Include 'Fix this' links in PR code review feedback that open Claude Code with context to fix the identified issue | No | `true` |
|
||||||
| `claude_args` | Additional [arguments to pass directly to Claude CLI](https://docs.claude.com/en/docs/claude-code/cli-reference#cli-flags) (e.g., `--max-turns 10 --model claude-4-0-sonnet-20250805`) | No | "" |
|
| `claude_args` | Additional [arguments to pass directly to Claude CLI](https://docs.claude.com/en/docs/claude-code/cli-reference#cli-flags) (e.g., `--max-turns 10 --model claude-4-0-sonnet-20250805`) | No | "" |
|
||||||
| `base_branch` | The base branch to use for creating new branches (e.g., 'main', 'develop') | No | - |
|
| `base_branch` | The base branch to use for creating new branches (e.g., 'main', 'develop') | No | - |
|
||||||
| `use_sticky_comment` | Use just one comment to deliver PR comments (only applies for pull_request event workflows) | No | `false` |
|
| `use_sticky_comment` | Use just one comment to deliver PR comments (only applies for pull_request event workflows) | No | `false` |
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@actions/github": "^6.0.1",
|
"@actions/github": "^6.0.1",
|
||||||
"@anthropic-ai/claude-agent-sdk": "^0.1.74",
|
"@anthropic-ai/claude-agent-sdk": "^0.1.76",
|
||||||
"@modelcontextprotocol/sdk": "^1.11.0",
|
"@modelcontextprotocol/sdk": "^1.11.0",
|
||||||
"@octokit/graphql": "^8.2.2",
|
"@octokit/graphql": "^8.2.2",
|
||||||
"@octokit/rest": "^21.1.1",
|
"@octokit/rest": "^21.1.1",
|
||||||
|
|||||||
@@ -734,7 +734,13 @@ ${eventData.eventName === "issue_comment" || eventData.eventName === "pull_reque
|
|||||||
- Reference specific code sections with file paths and line numbers${eventData.isPR ? `\n - AFTER reading files and analyzing code, you MUST call mcp__github_comment__update_claude_comment to post your review` : ""}
|
- Reference specific code sections with file paths and line numbers${eventData.isPR ? `\n - AFTER reading files and analyzing code, you MUST call mcp__github_comment__update_claude_comment to post your review` : ""}
|
||||||
- Formulate a concise, technical, and helpful response based on the context.
|
- Formulate a concise, technical, and helpful response based on the context.
|
||||||
- Reference specific code with inline formatting or code blocks.
|
- Reference specific code with inline formatting or code blocks.
|
||||||
- Include relevant file paths and line numbers when applicable.
|
- Include relevant file paths and line numbers when applicable.${
|
||||||
|
eventData.isPR && context.githubContext?.inputs.includeFixLinks
|
||||||
|
? `
|
||||||
|
- When identifying issues that could be fixed, include an inline link: [Fix this →](https://claude.ai/code?q=<URI_ENCODED_INSTRUCTIONS>&repo=${context.repository})
|
||||||
|
The query should be URI-encoded and include enough context for Claude Code to understand and fix the issue (file path, line numbers, branch name, what needs to change).`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
- ${eventData.isPR ? `IMPORTANT: Submit your review feedback by updating the Claude comment using mcp__github_comment__update_claude_comment. This will be displayed as your PR review.` : `Remember that this feedback must be posted to the GitHub comment using mcp__github_comment__update_claude_comment.`}
|
- ${eventData.isPR ? `IMPORTANT: Submit your review feedback by updating the Claude comment using mcp__github_comment__update_claude_comment. This will be displayed as your PR review.` : `Remember that this feedback must be posted to the GitHub comment using mcp__github_comment__update_claude_comment.`}
|
||||||
|
|
||||||
B. For Straightforward Changes:
|
B. For Straightforward Changes:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type {
|
|||||||
PullRequestEvent,
|
PullRequestEvent,
|
||||||
PullRequestReviewEvent,
|
PullRequestReviewEvent,
|
||||||
PullRequestReviewCommentEvent,
|
PullRequestReviewCommentEvent,
|
||||||
|
PushEvent,
|
||||||
WorkflowRunEvent,
|
WorkflowRunEvent,
|
||||||
} from "@octokit/webhooks-types";
|
} from "@octokit/webhooks-types";
|
||||||
import { CLAUDE_APP_BOT_ID, CLAUDE_BOT_LOGIN } from "./constants";
|
import { CLAUDE_APP_BOT_ID, CLAUDE_BOT_LOGIN } from "./constants";
|
||||||
@@ -65,6 +66,7 @@ const AUTOMATION_EVENT_NAMES = [
|
|||||||
"repository_dispatch",
|
"repository_dispatch",
|
||||||
"schedule",
|
"schedule",
|
||||||
"workflow_run",
|
"workflow_run",
|
||||||
|
"push",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
// Derive types from constants for better maintainability
|
// Derive types from constants for better maintainability
|
||||||
@@ -95,6 +97,7 @@ type BaseContext = {
|
|||||||
allowedBots: string;
|
allowedBots: string;
|
||||||
allowedNonWriteUsers: string;
|
allowedNonWriteUsers: string;
|
||||||
trackProgress: boolean;
|
trackProgress: boolean;
|
||||||
|
includeFixLinks: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,14 +114,15 @@ export type ParsedGitHubContext = BaseContext & {
|
|||||||
isPR: boolean;
|
isPR: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Context for automation events (workflow_dispatch, repository_dispatch, schedule, workflow_run)
|
// Context for automation events (workflow_dispatch, repository_dispatch, schedule, workflow_run, push)
|
||||||
export type AutomationContext = BaseContext & {
|
export type AutomationContext = BaseContext & {
|
||||||
eventName: AutomationEventName;
|
eventName: AutomationEventName;
|
||||||
payload:
|
payload:
|
||||||
| WorkflowDispatchEvent
|
| WorkflowDispatchEvent
|
||||||
| RepositoryDispatchEvent
|
| RepositoryDispatchEvent
|
||||||
| ScheduleEvent
|
| ScheduleEvent
|
||||||
| WorkflowRunEvent;
|
| WorkflowRunEvent
|
||||||
|
| PushEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Union type for all contexts
|
// Union type for all contexts
|
||||||
@@ -150,6 +154,7 @@ export function parseGitHubContext(): GitHubContext {
|
|||||||
allowedBots: process.env.ALLOWED_BOTS ?? "",
|
allowedBots: process.env.ALLOWED_BOTS ?? "",
|
||||||
allowedNonWriteUsers: process.env.ALLOWED_NON_WRITE_USERS ?? "",
|
allowedNonWriteUsers: process.env.ALLOWED_NON_WRITE_USERS ?? "",
|
||||||
trackProgress: process.env.TRACK_PROGRESS === "true",
|
trackProgress: process.env.TRACK_PROGRESS === "true",
|
||||||
|
includeFixLinks: process.env.INCLUDE_FIX_LINKS === "true",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -233,6 +238,13 @@ export function parseGitHubContext(): GitHubContext {
|
|||||||
payload: context.payload as unknown as WorkflowRunEvent,
|
payload: context.payload as unknown as WorkflowRunEvent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case "push": {
|
||||||
|
return {
|
||||||
|
...commonFields,
|
||||||
|
eventName: "push",
|
||||||
|
payload: context.payload as unknown as PushEvent,
|
||||||
|
};
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported event type: ${context.eventName}`);
|
throw new Error(`Unsupported event type: ${context.eventName}`);
|
||||||
}
|
}
|
||||||
@@ -274,6 +286,12 @@ export function isIssuesAssignedEvent(
|
|||||||
return isIssuesEvent(context) && context.eventAction === "assigned";
|
return isIssuesEvent(context) && context.eventAction === "assigned";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isPushEvent(
|
||||||
|
context: GitHubContext,
|
||||||
|
): context is AutomationContext & { payload: PushEvent } {
|
||||||
|
return context.eventName === "push";
|
||||||
|
}
|
||||||
|
|
||||||
// Type guard to check if context is an entity context (has entityNumber and isPR)
|
// Type guard to check if context is an entity context (has entityNumber and isPR)
|
||||||
export function isEntityContext(
|
export function isEntityContext(
|
||||||
context: GitHubContext,
|
context: GitHubContext,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ describe("prepareMcpConfig", () => {
|
|||||||
allowedBots: "",
|
allowedBots: "",
|
||||||
allowedNonWriteUsers: "",
|
allowedNonWriteUsers: "",
|
||||||
trackProgress: false,
|
trackProgress: false,
|
||||||
|
includeFixLinks: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const defaultInputs = {
|
|||||||
allowedBots: "",
|
allowedBots: "",
|
||||||
allowedNonWriteUsers: "",
|
allowedNonWriteUsers: "",
|
||||||
trackProgress: false,
|
trackProgress: false,
|
||||||
|
includeFixLinks: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultRepository = {
|
const defaultRepository = {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import { detectMode } from "../../src/modes/detector";
|
import { detectMode } from "../../src/modes/detector";
|
||||||
import type { GitHubContext } from "../../src/github/context";
|
import type { GitHubContext } from "../../src/github/context";
|
||||||
|
import { isPushEvent } from "../../src/github/context";
|
||||||
|
|
||||||
describe("detectMode with enhanced routing", () => {
|
describe("detectMode with enhanced routing", () => {
|
||||||
const baseContext = {
|
const baseContext = {
|
||||||
@@ -25,6 +26,7 @@ describe("detectMode with enhanced routing", () => {
|
|||||||
allowedBots: "",
|
allowedBots: "",
|
||||||
allowedNonWriteUsers: "",
|
allowedNonWriteUsers: "",
|
||||||
trackProgress: false,
|
trackProgress: false,
|
||||||
|
includeFixLinks: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -256,4 +258,65 @@ describe("detectMode with enhanced routing", () => {
|
|||||||
expect(detectMode(context)).toBe("tag");
|
expect(detectMode(context)).toBe("tag");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Push Events", () => {
|
||||||
|
it("should use agent mode for push events", () => {
|
||||||
|
const context: GitHubContext = {
|
||||||
|
...baseContext,
|
||||||
|
eventName: "push",
|
||||||
|
payload: {} as any,
|
||||||
|
inputs: { ...baseContext.inputs, prompt: "Merge main into stale PRs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(detectMode(context)).toBe("agent");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw error when track_progress is used with push event", () => {
|
||||||
|
const context: GitHubContext = {
|
||||||
|
...baseContext,
|
||||||
|
eventName: "push",
|
||||||
|
payload: {} as any,
|
||||||
|
inputs: { ...baseContext.inputs, trackProgress: true },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(() => detectMode(context)).toThrow(
|
||||||
|
/track_progress is only supported /,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("isPushEvent type guard", () => {
|
||||||
|
it("should return true for push events", () => {
|
||||||
|
const context: GitHubContext = {
|
||||||
|
...baseContext,
|
||||||
|
eventName: "push",
|
||||||
|
payload: {} as any,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(isPushEvent(context)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false for non-push events", () => {
|
||||||
|
const issueContext: GitHubContext = {
|
||||||
|
...baseContext,
|
||||||
|
eventName: "issues",
|
||||||
|
eventAction: "opened",
|
||||||
|
payload: { issue: { number: 1, body: "Test" } } as any,
|
||||||
|
entityNumber: 1,
|
||||||
|
isPR: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(isPushEvent(issueContext)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false for workflow_dispatch events", () => {
|
||||||
|
const context: GitHubContext = {
|
||||||
|
...baseContext,
|
||||||
|
eventName: "workflow_dispatch",
|
||||||
|
payload: {} as any,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(isPushEvent(context)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -60,6 +60,15 @@ describe("Mode Registry", () => {
|
|||||||
expect(mode.name).toBe("agent");
|
expect(mode.name).toBe("agent");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("getMode auto-detects agent for push event", () => {
|
||||||
|
const pushContext = createMockAutomationContext({
|
||||||
|
eventName: "push",
|
||||||
|
});
|
||||||
|
const mode = getMode(pushContext);
|
||||||
|
expect(mode).toBe(agentMode);
|
||||||
|
expect(mode.name).toBe("agent");
|
||||||
|
});
|
||||||
|
|
||||||
test("getMode auto-detects agent for repository_dispatch with client_payload", () => {
|
test("getMode auto-detects agent for repository_dispatch with client_payload", () => {
|
||||||
const contextWithPayload = createMockAutomationContext({
|
const contextWithPayload = createMockAutomationContext({
|
||||||
eventName: "repository_dispatch",
|
eventName: "repository_dispatch",
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ describe("checkWritePermissions", () => {
|
|||||||
allowedBots: "",
|
allowedBots: "",
|
||||||
allowedNonWriteUsers: "",
|
allowedNonWriteUsers: "",
|
||||||
trackProgress: false,
|
trackProgress: false,
|
||||||
|
includeFixLinks: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user