mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 15:04:13 +08:00
Compare commits
1 Commits
v0.0.22
...
ashwin/mul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9e73dc5d4 |
2
.github/workflows/issue-triage.yml
vendored
2
.github/workflows/issue-triage.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
"--rm",
|
"--rm",
|
||||||
"-e",
|
"-e",
|
||||||
"GITHUB_PERSONAL_ACCESS_TOKEN",
|
"GITHUB_PERSONAL_ACCESS_TOKEN",
|
||||||
"ghcr.io/github/github-mcp-server:sha-6d69797"
|
"ghcr.io/github/github-mcp-server:sha-7aced2b"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
|
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|||||||
138
.github/workflows/release.yml
vendored
138
.github/workflows/release.yml
vendored
@@ -1,138 +0,0 @@
|
|||||||
name: Create Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
dry_run:
|
|
||||||
description: "Dry run (only show what would be created)"
|
|
||||||
required: false
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
create-release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
outputs:
|
|
||||||
next_version: ${{ steps.next_version.outputs.next_version }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Get latest tag
|
|
||||||
id: get_latest_tag
|
|
||||||
run: |
|
|
||||||
# Get only version tags (v + number pattern)
|
|
||||||
latest_tag=$(git tag -l 'v[0-9]*' | sort -V | tail -1 || echo "v0.0.0")
|
|
||||||
if [ -z "$latest_tag" ]; then
|
|
||||||
latest_tag="v0.0.0"
|
|
||||||
fi
|
|
||||||
echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT
|
|
||||||
echo "Latest tag: $latest_tag"
|
|
||||||
|
|
||||||
- name: Calculate next version
|
|
||||||
id: next_version
|
|
||||||
run: |
|
|
||||||
latest_tag="${{ steps.get_latest_tag.outputs.latest_tag }}"
|
|
||||||
# Remove 'v' prefix and split by dots
|
|
||||||
version=${latest_tag#v}
|
|
||||||
IFS='.' read -ra VERSION_PARTS <<< "$version"
|
|
||||||
|
|
||||||
# Increment patch version
|
|
||||||
major=${VERSION_PARTS[0]:-0}
|
|
||||||
minor=${VERSION_PARTS[1]:-0}
|
|
||||||
patch=${VERSION_PARTS[2]:-0}
|
|
||||||
patch=$((patch + 1))
|
|
||||||
|
|
||||||
next_version="v${major}.${minor}.${patch}"
|
|
||||||
echo "next_version=$next_version" >> $GITHUB_OUTPUT
|
|
||||||
echo "Next version: $next_version"
|
|
||||||
|
|
||||||
- name: Display dry run info
|
|
||||||
if: ${{ inputs.dry_run }}
|
|
||||||
run: |
|
|
||||||
echo "🔍 DRY RUN MODE"
|
|
||||||
echo "Would create tag: ${{ steps.next_version.outputs.next_version }}"
|
|
||||||
echo "From commit: ${{ github.sha }}"
|
|
||||||
echo "Previous tag: ${{ steps.get_latest_tag.outputs.latest_tag }}"
|
|
||||||
|
|
||||||
- name: Create and push tag
|
|
||||||
if: ${{ !inputs.dry_run }}
|
|
||||||
run: |
|
|
||||||
next_version="${{ steps.next_version.outputs.next_version }}"
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
git tag -a "$next_version" -m "Release $next_version"
|
|
||||||
git push origin "$next_version"
|
|
||||||
|
|
||||||
- name: Create Release
|
|
||||||
if: ${{ !inputs.dry_run }}
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
run: |
|
|
||||||
next_version="${{ steps.next_version.outputs.next_version }}"
|
|
||||||
|
|
||||||
gh release create "$next_version" \
|
|
||||||
--title "$next_version" \
|
|
||||||
--generate-notes \
|
|
||||||
--latest=false # We want to keep beta as the latest
|
|
||||||
|
|
||||||
update-beta-tag:
|
|
||||||
needs: create-release
|
|
||||||
if: ${{ !inputs.dry_run }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Update beta tag
|
|
||||||
run: |
|
|
||||||
# Get the latest version tag
|
|
||||||
VERSION=$(git tag -l 'v[0-9]*' | sort -V | tail -1)
|
|
||||||
|
|
||||||
# Update the beta tag to point to this release
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git tag -fa beta -m "Update beta tag to ${VERSION}"
|
|
||||||
git push origin beta --force
|
|
||||||
|
|
||||||
- name: Update beta release to be latest
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
run: |
|
|
||||||
# Update beta release to be marked as latest
|
|
||||||
gh release edit beta --latest
|
|
||||||
|
|
||||||
update-major-tag:
|
|
||||||
needs: create-release
|
|
||||||
if: ${{ !inputs.dry_run }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Update major version tag
|
|
||||||
run: |
|
|
||||||
next_version="${{ needs.create-release.outputs.next_version }}"
|
|
||||||
# Extract major version (e.g., v0 from v0.0.20)
|
|
||||||
major_version=$(echo "$next_version" | cut -d. -f1)
|
|
||||||
|
|
||||||
# Update the major version tag to point to this release
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git tag -fa "$major_version" -m "Update $major_version tag to $next_version"
|
|
||||||
git push origin "$major_version" --force
|
|
||||||
|
|
||||||
echo "Updated $major_version tag to point to $next_version"
|
|
||||||
34
README.md
34
README.md
@@ -149,40 +149,6 @@ For MCP servers that require sensitive information like API keys or tokens, use
|
|||||||
# ... other inputs
|
# ... other inputs
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Using Python MCP Servers with uv
|
|
||||||
|
|
||||||
For Python-based MCP servers managed with `uv`, you need to specify the directory containing your server:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- uses: anthropics/claude-code-action@beta
|
|
||||||
with:
|
|
||||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
||||||
mcp_config: |
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"my-python-server": {
|
|
||||||
"type": "stdio",
|
|
||||||
"command": "uv",
|
|
||||||
"args": [
|
|
||||||
"--directory",
|
|
||||||
"${{ github.workspace }}/path/to/server/",
|
|
||||||
"run",
|
|
||||||
"server_file.py"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allowed_tools: "my-python-server__<tool_name>" # Replace <tool_name> with your server's tool names
|
|
||||||
# ... other inputs
|
|
||||||
```
|
|
||||||
|
|
||||||
For example, if your Python MCP server is at `mcp_servers/weather.py`, you would use:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
"args":
|
|
||||||
["--directory", "${{ github.workspace }}/mcp_servers/", "run", "weather.py"]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important**:
|
**Important**:
|
||||||
|
|
||||||
- Always use GitHub Secrets (`${{ secrets.SECRET_NAME }}`) for sensitive values like API keys, tokens, or passwords. Never hardcode secrets directly in the workflow file.
|
- Always use GitHub Secrets (`${{ secrets.SECRET_NAME }}`) for sensitive values like API keys, tokens, or passwords. Never hardcode secrets directly in the workflow file.
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ runs:
|
|||||||
- name: Run Claude Code
|
- name: Run Claude Code
|
||||||
id: claude-code
|
id: claude-code
|
||||||
if: steps.prepare.outputs.contains_trigger == 'true'
|
if: steps.prepare.outputs.contains_trigger == 'true'
|
||||||
uses: anthropics/claude-code-base-action@bb2ef1d9768b9e94083d377778120f8f27958a72 # v0.0.22
|
uses: anthropics/claude-code-base-action@ebd8558e902b3db132e89863de49565fcb9aec46 # v0.0.19
|
||||||
with:
|
with:
|
||||||
prompt_file: ${{ runner.temp }}/claude-prompts/claude-prompt.txt
|
prompt_file: ${{ runner.temp }}/claude-prompts/claude-prompt.txt
|
||||||
allowed_tools: ${{ env.ALLOWED_TOOLS }}
|
allowed_tools: ${{ env.ALLOWED_TOOLS }}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import * as github from "@actions/github";
|
import * as github from "@actions/github";
|
||||||
import type {
|
import type {
|
||||||
IssuesEvent,
|
IssuesEvent,
|
||||||
IssuesAssignedEvent,
|
|
||||||
IssueCommentEvent,
|
IssueCommentEvent,
|
||||||
PullRequestEvent,
|
PullRequestEvent,
|
||||||
PullRequestReviewEvent,
|
PullRequestReviewEvent,
|
||||||
@@ -148,9 +147,3 @@ export function isPullRequestReviewCommentEvent(
|
|||||||
): context is ParsedGitHubContext & { payload: PullRequestReviewCommentEvent } {
|
): context is ParsedGitHubContext & { payload: PullRequestReviewCommentEvent } {
|
||||||
return context.eventName === "pull_request_review_comment";
|
return context.eventName === "pull_request_review_comment";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isIssuesAssignedEvent(
|
|
||||||
context: ParsedGitHubContext,
|
|
||||||
): context is ParsedGitHubContext & { payload: IssuesAssignedEvent } {
|
|
||||||
return isIssuesEvent(context) && context.eventAction === "assigned";
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -45,16 +45,9 @@ export async function setupBranch(
|
|||||||
|
|
||||||
const branchName = prData.headRefName;
|
const branchName = prData.headRefName;
|
||||||
|
|
||||||
// Determine optimal fetch depth based on PR commit count, with a minimum of 20
|
// Execute git commands to checkout PR branch (shallow fetch for performance)
|
||||||
const commitCount = prData.commits.totalCount;
|
// Fetch the branch with a depth of 20 to avoid fetching too much history, while still allowing for some context
|
||||||
const fetchDepth = Math.max(commitCount, 20);
|
await $`git fetch origin --depth=20 ${branchName}`;
|
||||||
|
|
||||||
console.log(
|
|
||||||
`PR #${entityNumber}: ${commitCount} commits, using fetch depth ${fetchDepth}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Execute git commands to checkout PR branch (dynamic depth based on PR size)
|
|
||||||
await $`git fetch origin --depth=${fetchDepth} ${branchName}`;
|
|
||||||
await $`git checkout ${branchName}`;
|
await $`git checkout ${branchName}`;
|
||||||
|
|
||||||
console.log(`Successfully checked out PR branch for PR #${entityNumber}`);
|
console.log(`Successfully checked out PR branch for PR #${entityNumber}`);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import {
|
import {
|
||||||
isIssuesEvent,
|
isIssuesEvent,
|
||||||
isIssuesAssignedEvent,
|
|
||||||
isIssueCommentEvent,
|
isIssueCommentEvent,
|
||||||
isPullRequestEvent,
|
isPullRequestEvent,
|
||||||
isPullRequestReviewEvent,
|
isPullRequestReviewEvent,
|
||||||
@@ -23,10 +22,10 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for assignee trigger
|
// Check for assignee trigger
|
||||||
if (isIssuesAssignedEvent(context)) {
|
if (isIssuesEvent(context) && context.eventAction === "assigned") {
|
||||||
// Remove @ symbol from assignee_trigger if present
|
// Remove @ symbol from assignee_trigger if present
|
||||||
let triggerUser = assigneeTrigger.replace(/^@/, "");
|
let triggerUser = assigneeTrigger.replace(/^@/, "");
|
||||||
const assigneeUsername = context.payload.assignee?.login || "";
|
const assigneeUsername = context.payload.issue.assignee?.login || "";
|
||||||
|
|
||||||
if (triggerUser && assigneeUsername === triggerUser) {
|
if (triggerUser && assigneeUsername === triggerUser) {
|
||||||
console.log(`Issue assigned to trigger user '${triggerUser}'`);
|
console.log(`Issue assigned to trigger user '${triggerUser}'`);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export async function prepareMcpConfig(
|
|||||||
"--rm",
|
"--rm",
|
||||||
"-e",
|
"-e",
|
||||||
"GITHUB_PERSONAL_ACCESS_TOKEN",
|
"GITHUB_PERSONAL_ACCESS_TOKEN",
|
||||||
"ghcr.io/github/github-mcp-server:sha-6d69797", // https://github.com/github/github-mcp-server/releases/tag/v0.5.0
|
"ghcr.io/github/github-mcp-server:sha-e9f748f", // https://github.com/github/github-mcp-server/releases/tag/v0.4.0
|
||||||
],
|
],
|
||||||
env: {
|
env: {
|
||||||
GITHUB_PERSONAL_ACCESS_TOKEN: githubToken,
|
GITHUB_PERSONAL_ACCESS_TOKEN: githubToken,
|
||||||
|
|||||||
@@ -91,12 +91,6 @@ export const mockIssueAssignedContext: ParsedGitHubContext = {
|
|||||||
actor: "admin-user",
|
actor: "admin-user",
|
||||||
payload: {
|
payload: {
|
||||||
action: "assigned",
|
action: "assigned",
|
||||||
assignee: {
|
|
||||||
login: "claude-bot",
|
|
||||||
id: 11111,
|
|
||||||
avatar_url: "https://avatars.githubusercontent.com/u/11111",
|
|
||||||
html_url: "https://github.com/claude-bot",
|
|
||||||
},
|
|
||||||
issue: {
|
issue: {
|
||||||
number: 123,
|
number: 123,
|
||||||
title: "Feature: Add dark mode support",
|
title: "Feature: Add dark mode support",
|
||||||
|
|||||||
@@ -87,11 +87,6 @@ describe("checkContainsTrigger", () => {
|
|||||||
...mockIssueAssignedContext,
|
...mockIssueAssignedContext,
|
||||||
payload: {
|
payload: {
|
||||||
...mockIssueAssignedContext.payload,
|
...mockIssueAssignedContext.payload,
|
||||||
assignee: {
|
|
||||||
...(mockIssueAssignedContext.payload as IssuesAssignedEvent)
|
|
||||||
.assignee,
|
|
||||||
login: "otherUser",
|
|
||||||
},
|
|
||||||
issue: {
|
issue: {
|
||||||
...(mockIssueAssignedContext.payload as IssuesAssignedEvent).issue,
|
...(mockIssueAssignedContext.payload as IssuesAssignedEvent).issue,
|
||||||
assignee: {
|
assignee: {
|
||||||
|
|||||||
Reference in New Issue
Block a user