mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 06:54:13 +08:00
resolve merge conflict in create-prompt.test.ts
This commit is contained in:
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-7aced2b"
|
"ghcr.io/github/github-mcp-server:sha-6d69797"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
|
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|||||||
@@ -50,20 +50,6 @@ Thank you for your interest in contributing to Claude Code Action! This document
|
|||||||
bun test
|
bun test
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Integration Tests** (using GitHub Actions locally):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./test-local.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
This script:
|
|
||||||
|
|
||||||
- Installs `act` if not present (requires Homebrew on macOS)
|
|
||||||
- Runs the GitHub Action workflow locally using Docker
|
|
||||||
- Requires your `ANTHROPIC_API_KEY` to be set
|
|
||||||
|
|
||||||
On Apple Silicon Macs, the script automatically adds the `--container-architecture linux/amd64` flag to avoid compatibility issues.
|
|
||||||
|
|
||||||
## Pull Request Process
|
## Pull Request Process
|
||||||
|
|
||||||
1. Create a new branch from `main`:
|
1. Create a new branch from `main`:
|
||||||
@@ -103,13 +89,7 @@ Thank you for your interest in contributing to Claude Code Action! This document
|
|||||||
|
|
||||||
When modifying the action:
|
When modifying the action:
|
||||||
|
|
||||||
1. Test locally with the test script:
|
1. Test in a real GitHub Actions workflow by:
|
||||||
|
|
||||||
```bash
|
|
||||||
./test-local.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Test in a real GitHub Actions workflow by:
|
|
||||||
- Creating a test repository
|
- Creating a test repository
|
||||||
- Using your branch as the action source:
|
- Using your branch as the action source:
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
@@ -114,7 +114,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@f481f924b73a7085d9efea0e50a3ba171ed1d74b # v0.0.20
|
uses: anthropics/claude-code-base-action@ce5cfd683932f58cb459e749f20b06d2fb30c265 # v0.0.25
|
||||||
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 }}
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ export function prepareContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (eventAction === "assigned") {
|
if (eventAction === "assigned") {
|
||||||
if (!assigneeTrigger) {
|
if (!assigneeTrigger && !directPrompt) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"ASSIGNEE_TRIGGER is required for issue assigned event",
|
"ASSIGNEE_TRIGGER is required for issue assigned event",
|
||||||
);
|
);
|
||||||
@@ -255,7 +255,7 @@ export function prepareContext(
|
|||||||
issueNumber,
|
issueNumber,
|
||||||
baseBranch,
|
baseBranch,
|
||||||
claudeBranch,
|
claudeBranch,
|
||||||
assigneeTrigger,
|
...(assigneeTrigger && { assigneeTrigger }),
|
||||||
};
|
};
|
||||||
} else if (eventAction === "labeled") {
|
} else if (eventAction === "labeled") {
|
||||||
if (!labelTrigger) {
|
if (!labelTrigger) {
|
||||||
@@ -350,7 +350,9 @@ export function getEventTypeAndContext(envVars: PreparedContext): {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
eventType: "ISSUE_ASSIGNED",
|
eventType: "ISSUE_ASSIGNED",
|
||||||
triggerContext: `issue assigned to '${eventData.assigneeTrigger}'`,
|
triggerContext: eventData.assigneeTrigger
|
||||||
|
? `issue assigned to '${eventData.assigneeTrigger}'`
|
||||||
|
: `issue assigned event`,
|
||||||
};
|
};
|
||||||
|
|
||||||
case "pull_request":
|
case "pull_request":
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ type IssueAssignedEvent = {
|
|||||||
issueNumber: string;
|
issueNumber: string;
|
||||||
baseBranch: string;
|
baseBranch: string;
|
||||||
claudeBranch: string;
|
claudeBranch: string;
|
||||||
assigneeTrigger: string;
|
assigneeTrigger?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IssueLabeledEvent = {
|
type IssueLabeledEvent = {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
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,
|
||||||
@@ -149,3 +150,9 @@ 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";
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import {
|
import {
|
||||||
isIssuesEvent,
|
isIssuesEvent,
|
||||||
|
isIssuesAssignedEvent,
|
||||||
isIssueCommentEvent,
|
isIssueCommentEvent,
|
||||||
isPullRequestEvent,
|
isPullRequestEvent,
|
||||||
isPullRequestReviewEvent,
|
isPullRequestReviewEvent,
|
||||||
@@ -22,10 +23,10 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for assignee trigger
|
// Check for assignee trigger
|
||||||
if (isIssuesEvent(context) && context.eventAction === "assigned") {
|
if (isIssuesAssignedEvent(context)) {
|
||||||
// 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.issue.assignee?.login || "";
|
const assigneeUsername = context.payload.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-e9f748f", // https://github.com/github/github-mcp-server/releases/tag/v0.4.0
|
"ghcr.io/github/github-mcp-server:sha-6d69797", // https://github.com/github/github-mcp-server/releases/tag/v0.5.0
|
||||||
],
|
],
|
||||||
env: {
|
env: {
|
||||||
GITHUB_PERSONAL_ACCESS_TOKEN: githubToken,
|
GITHUB_PERSONAL_ACCESS_TOKEN: githubToken,
|
||||||
|
|||||||
@@ -663,6 +663,29 @@ describe("getEventTypeAndContext", () => {
|
|||||||
expect(result.eventType).toBe("ISSUE_LABELED");
|
expect(result.eventType).toBe("ISSUE_LABELED");
|
||||||
expect(result.triggerContext).toBe("issue labeled with 'claude-task'");
|
expect(result.triggerContext).toBe("issue labeled with 'claude-task'");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should return correct type and context for issue assigned without assigneeTrigger", () => {
|
||||||
|
const envVars: PreparedContext = {
|
||||||
|
repository: "owner/repo",
|
||||||
|
claudeCommentId: "12345",
|
||||||
|
triggerPhrase: "@claude",
|
||||||
|
directPrompt: "Please assess this issue",
|
||||||
|
eventData: {
|
||||||
|
eventName: "issues",
|
||||||
|
eventAction: "assigned",
|
||||||
|
isPR: false,
|
||||||
|
issueNumber: "999",
|
||||||
|
baseBranch: "main",
|
||||||
|
claudeBranch: "claude/issue-999-20240101_120000",
|
||||||
|
// No assigneeTrigger when using directPrompt
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = getEventTypeAndContext(envVars);
|
||||||
|
|
||||||
|
expect(result.eventType).toBe("ISSUE_ASSIGNED");
|
||||||
|
expect(result.triggerContext).toBe("issue assigned event");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("buildAllowedToolsString", () => {
|
describe("buildAllowedToolsString", () => {
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ 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",
|
||||||
|
|||||||
@@ -219,6 +219,55 @@ describe("parseEnvVarsWithContext", () => {
|
|||||||
),
|
),
|
||||||
).toThrow("BASE_BRANCH is required for issues event");
|
).toThrow("BASE_BRANCH is required for issues event");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should allow issue assigned event with direct_prompt and no assigneeTrigger", () => {
|
||||||
|
const contextWithDirectPrompt = createMockContext({
|
||||||
|
...mockIssueAssignedContext,
|
||||||
|
inputs: {
|
||||||
|
...mockIssueAssignedContext.inputs,
|
||||||
|
assigneeTrigger: "", // No assignee trigger
|
||||||
|
directPrompt: "Please assess this issue", // But direct prompt is provided
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = prepareContext(
|
||||||
|
contextWithDirectPrompt,
|
||||||
|
"12345",
|
||||||
|
"main",
|
||||||
|
"claude/issue-123-20240101_120000",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.eventData.eventName).toBe("issues");
|
||||||
|
expect(result.eventData.isPR).toBe(false);
|
||||||
|
expect(result.directPrompt).toBe("Please assess this issue");
|
||||||
|
if (
|
||||||
|
result.eventData.eventName === "issues" &&
|
||||||
|
result.eventData.eventAction === "assigned"
|
||||||
|
) {
|
||||||
|
expect(result.eventData.issueNumber).toBe("123");
|
||||||
|
expect(result.eventData.assigneeTrigger).toBeUndefined();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should throw error when neither assigneeTrigger nor directPrompt provided for issue assigned event", () => {
|
||||||
|
const contextWithoutTriggers = createMockContext({
|
||||||
|
...mockIssueAssignedContext,
|
||||||
|
inputs: {
|
||||||
|
...mockIssueAssignedContext.inputs,
|
||||||
|
assigneeTrigger: "", // No assignee trigger
|
||||||
|
directPrompt: "", // No direct prompt
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() =>
|
||||||
|
prepareContext(
|
||||||
|
contextWithoutTriggers,
|
||||||
|
"12345",
|
||||||
|
"main",
|
||||||
|
"claude/issue-123-20240101_120000",
|
||||||
|
),
|
||||||
|
).toThrow("ASSIGNEE_TRIGGER is required for issue assigned event");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("optional fields", () => {
|
describe("optional fields", () => {
|
||||||
|
|||||||
@@ -90,6 +90,11 @@ 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