Skip to content

Commit f08181a

Browse files
committed
Merge remote-tracking branch 'upstream/main'
# Conflicts: # action.yml
2 parents 3e89611 + ebbd9e9 commit f08181a

File tree

10 files changed

+216
-26
lines changed

10 files changed

+216
-26
lines changed

.github/workflows/issue-triage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
"--rm",
3333
"-e",
3434
"GITHUB_PERSONAL_ACCESS_TOKEN",
35-
"ghcr.io/github/github-mcp-server:sha-7aced2b"
35+
"ghcr.io/github/github-mcp-server:sha-6d69797"
3636
],
3737
"env": {
3838
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"

CONTRIBUTING.md

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,6 @@ Thank you for your interest in contributing to Claude Code Action! This document
5050
bun test
5151
```
5252

53-
2. **Integration Tests** (using GitHub Actions locally):
54-
55-
```bash
56-
./test-local.sh
57-
```
58-
59-
This script:
60-
61-
- Installs `act` if not present (requires Homebrew on macOS)
62-
- Runs the GitHub Action workflow locally using Docker
63-
- Requires your `ANTHROPIC_API_KEY` to be set
64-
65-
On Apple Silicon Macs, the script automatically adds the `--container-architecture linux/amd64` flag to avoid compatibility issues.
66-
6753
## Pull Request Process
6854

6955
1. Create a new branch from `main`:
@@ -103,13 +89,7 @@ Thank you for your interest in contributing to Claude Code Action! This document
10389

10490
When modifying the action:
10591

106-
1. Test locally with the test script:
107-
108-
```bash
109-
./test-local.sh
110-
```
111-
112-
2. Test in a real GitHub Actions workflow by:
92+
1. Test in a real GitHub Actions workflow by:
11393
- Creating a test repository
11494
- Using your branch as the action source:
11595
```yaml

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ runs:
126126
- name: Run Claude Code
127127
id: claude-code
128128
if: steps.prepare.outputs.contains_trigger == 'true'
129-
uses: grll/claude-code-base-action@30f4e17267bd0172ae76f7a3a10593c44811b230 # Latest commit from fork
129+
uses: grll/claude-code-base-action@27eda5e9c4eff1ef4919086595947a5b3547d9e5 # Latest commit from fork
130130
with:
131131
prompt_file: ${{ runner.temp }}/claude-prompts/claude-prompt.txt
132132
allowed_tools: ${{ env.ALLOWED_TOOLS }}

example-dispatch-workflow.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Claude Task Executor
2+
3+
on:
4+
repository_dispatch:
5+
types: [claude-task]
6+
7+
permissions:
8+
contents: write
9+
pull-requests: write
10+
issues: write
11+
id-token: write # Required for OIDC authentication
12+
13+
jobs:
14+
execute-claude-task:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v4
19+
20+
- name: Execute Claude Task
21+
uses: anthropics/claude-code-action@main
22+
with:
23+
github_token: ${{ secrets.GITHUB_TOKEN }}
24+
# Base branch for creating task branches
25+
base_branch: main
26+
# Optional: Custom instructions for Claude
27+
custom_instructions: |
28+
Follow the CLAUDE.md guidelines strictly.
29+
Commit changes with descriptive messages.
30+
# Optional: Tool restrictions
31+
allowed_tools: |
32+
file_editor
33+
bash_command
34+
github_comment
35+
mcp__github__create_or_update_file
36+
# Optional: Anthropic API configuration
37+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
38+
# Or use AWS Bedrock
39+
# aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
40+
# aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
41+
# aws_region: us-east-1
42+
# Or use Google Vertex AI
43+
# google_credentials: ${{ secrets.GOOGLE_CREDENTIALS }}
44+
# vertex_project: my-project
45+
# vertex_location: us-central1
46+
# Example: Triggering this workflow from another service
47+
#
48+
# curl -X POST \
49+
# https://api.github.com/repos/owner/repo/dispatches \
50+
# -H "Authorization: token $GITHUB_TOKEN" \
51+
# -H "Accept: application/vnd.github.v3+json" \
52+
# -d '{
53+
# "event_type": "claude-task",
54+
# "client_payload": {
55+
# "description": "Analyze the codebase and create a comprehensive test suite for the authentication module",
56+
# "progress_endpoint": "https://api.example.com/claude/progress",
57+
# "correlation_id": "task-auth-tests-2024-01-17"
58+
# }
59+
# }'
60+
#
61+
# The progress_endpoint will receive POST requests with:
62+
# {
63+
# "repository": "owner/repo",
64+
# "run_id": "123456789",
65+
# "correlation_id": "task-auth-tests-2024-01-17",
66+
# "status": "in_progress" | "completed" | "failed",
67+
# "message": "Current progress description",
68+
# "completed_tasks": ["task1", "task2"],
69+
# "current_task": "Working on task3",
70+
# "timestamp": "2024-01-17T12:00:00Z"
71+
# }
72+
#
73+
# Authentication: Progress updates include a GitHub OIDC token in the Authorization header

pr-summary.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
## Summary
2+
3+
Adds support for `repository_dispatch` events, enabling backend services to programmatically trigger Claude to perform tasks and receive progress updates via API.
4+
5+
## Architecture
6+
7+
```mermaid
8+
sequenceDiagram
9+
participant Backend as Backend Service
10+
participant GH as GitHub
11+
participant Action as Claude Action
12+
participant Claude as Claude
13+
participant MCP as Progress MCP Server
14+
participant API as Progress API
15+
16+
Backend->>GH: POST /repos/{owner}/{repo}/dispatches
17+
Note over Backend,GH: Payload includes:<br/>- description (task)<br/>- progress_endpoint<br/>- correlation_id
18+
19+
GH->>Action: Trigger workflow<br/>(repository_dispatch)
20+
21+
Action->>Action: Parse dispatch payload
22+
Note over Action: Extract task description,<br/>endpoint, correlation_id
23+
24+
Action->>MCP: Install Progress Server
25+
Note over MCP: Configure with:<br/>- PROGRESS_ENDPOINT<br/>- CORRELATION_ID<br/>- GITHUB_RUN_ID
26+
27+
Action->>Claude: Execute task with<br/>MCP tools available
28+
29+
loop Task Execution
30+
Claude->>MCP: update_claude_progress()
31+
MCP->>MCP: Get OIDC token
32+
MCP->>API: POST progress update
33+
Note over API: Payload includes:<br/>- correlation_id<br/>- status<br/>- message<br/>- completed_tasks
34+
API->>Backend: Forward update
35+
end
36+
37+
Claude->>Action: Task complete
38+
Action->>GH: Commit changes
39+
```
40+
41+
## Key Features
42+
43+
### 1. Repository Dispatch Support
44+
45+
- New event handler for `repository_dispatch` events
46+
- Extracts task description, progress endpoint, and correlation ID from `client_payload`
47+
- Bypasses GitHub UI interaction for fully programmatic operation
48+
49+
### 2. Progress Reporting MCP Server
50+
51+
- New MCP server (`progress-server.ts`) for sending progress updates
52+
- OIDC authentication for secure API communication
53+
- Includes correlation ID in all updates for request tracking
54+
55+
### 3. Simplified Dispatch Prompts
56+
57+
- Focused instructions for dispatch events (no PR/issue context)
58+
- Clear directives: answer questions or implement changes
59+
- Automatic progress updates at start and completion
60+
61+
## Implementation Details
62+
63+
### Triggering a Dispatch
64+
65+
```bash
66+
curl -X POST \
67+
https://api.github.com/repos/{owner}/{repo}/dispatches \
68+
-H "Authorization: token $GITHUB_TOKEN" \
69+
-H "Accept: application/vnd.github.v3+json" \
70+
-d '{
71+
"event_type": "claude-task",
72+
"client_payload": {
73+
"description": "Implement a new feature that...",
74+
"progress_endpoint": "https://api.example.com/progress",
75+
"correlation_id": "req-123-abc"
76+
}
77+
}'
78+
```
79+
80+
### Progress Update Payload
81+
82+
```json
83+
{
84+
"repository": "owner/repo",
85+
"run_id": "123456789",
86+
"correlation_id": "req-123-abc",
87+
"status": "in_progress",
88+
"message": "Implementing feature...",
89+
"completed_tasks": ["Setup environment", "Created base structure"],
90+
"current_task": "Writing tests",
91+
"timestamp": "2024-01-17T12:00:00Z"
92+
}
93+
```
94+
95+
## Security
96+
97+
- **OIDC Authentication**: All progress updates use GitHub OIDC tokens
98+
- **Correlation IDs**: Included in request body (not URL) for security
99+
- **Endpoint Validation**: Progress endpoint must be explicitly provided
100+
- **No Credential Storage**: Tokens are generated per-request
101+
102+
## Testing
103+
104+
To test the repository_dispatch flow:
105+
106+
1. Configure workflow with `repository_dispatch` trigger
107+
2. Send dispatch event with required payload
108+
3. Monitor GitHub Actions logs for execution
109+
4. Verify progress updates at configured endpoint
110+
111+
## Changes
112+
113+
- Added `repository_dispatch` event handling in `context.ts`
114+
- Created new `progress-server.ts` MCP server
115+
- Updated `isDispatch` flag across all event types
116+
- Modified prompt generation for dispatch events
117+
- Made `githubData` optional for dispatch workflows
118+
- Added correlation ID support throughout the pipeline

src/github/context.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as github from "@actions/github";
22
import type {
33
IssuesEvent,
4+
IssuesAssignedEvent,
45
IssueCommentEvent,
56
PullRequestEvent,
67
PullRequestReviewEvent,
@@ -147,3 +148,9 @@ export function isPullRequestReviewCommentEvent(
147148
): context is ParsedGitHubContext & { payload: PullRequestReviewCommentEvent } {
148149
return context.eventName === "pull_request_review_comment";
149150
}
151+
152+
export function isIssuesAssignedEvent(
153+
context: ParsedGitHubContext,
154+
): context is ParsedGitHubContext & { payload: IssuesAssignedEvent } {
155+
return isIssuesEvent(context) && context.eventAction === "assigned";
156+
}

src/github/validation/trigger.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import * as core from "@actions/core";
44
import {
55
isIssuesEvent,
6+
isIssuesAssignedEvent,
67
isIssueCommentEvent,
78
isPullRequestEvent,
89
isPullRequestReviewEvent,
@@ -22,10 +23,10 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
2223
}
2324

2425
// Check for assignee trigger
25-
if (isIssuesEvent(context) && context.eventAction === "assigned") {
26+
if (isIssuesAssignedEvent(context)) {
2627
// Remove @ symbol from assignee_trigger if present
2728
let triggerUser = assigneeTrigger.replace(/^@/, "");
28-
const assigneeUsername = context.payload.issue.assignee?.login || "";
29+
const assigneeUsername = context.payload.assignee?.login || "";
2930

3031
if (triggerUser && assigneeUsername === triggerUser) {
3132
console.log(`Issue assigned to trigger user '${triggerUser}'`);

src/mcp/install-mcp-server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export async function prepareMcpConfig(
6262
"--rm",
6363
"-e",
6464
"GITHUB_PERSONAL_ACCESS_TOKEN",
65-
"ghcr.io/github/github-mcp-server:sha-e9f748f", // https://github.com/github/github-mcp-server/releases/tag/v0.4.0
65+
"ghcr.io/github/github-mcp-server:sha-6d69797", // https://github.com/github/github-mcp-server/releases/tag/v0.5.0
6666
],
6767
env: {
6868
GITHUB_PERSONAL_ACCESS_TOKEN: githubToken,

test/mockContext.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ export const mockIssueAssignedContext: ParsedGitHubContext = {
9191
actor: "admin-user",
9292
payload: {
9393
action: "assigned",
94+
assignee: {
95+
login: "claude-bot",
96+
id: 11111,
97+
avatar_url: "https://avatars.githubusercontent.com/u/11111",
98+
html_url: "https://github.com/claude-bot",
99+
},
94100
issue: {
95101
number: 123,
96102
title: "Feature: Add dark mode support",

test/trigger-validation.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ describe("checkContainsTrigger", () => {
8787
...mockIssueAssignedContext,
8888
payload: {
8989
...mockIssueAssignedContext.payload,
90+
assignee: {
91+
...(mockIssueAssignedContext.payload as IssuesAssignedEvent)
92+
.assignee,
93+
login: "otherUser",
94+
},
9095
issue: {
9196
...(mockIssueAssignedContext.payload as IssuesAssignedEvent).issue,
9297
assignee: {

0 commit comments

Comments
 (0)