mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 06:54:13 +08:00
feat: add repository_dispatch event support (#546)
* feat: add repository_dispatch event support Add support for repository_dispatch events in GitHub context parsing system. This enables the action to handle custom API-triggered events properly. Changes: - Add RepositoryDispatchEvent type definition - Include repository_dispatch in automation event names - Update context parsing to handle repository_dispatch events - Update documentation to reflect repository_dispatch availability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * style: format code with prettier 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * test: add comprehensive repository_dispatch event test coverage - Add mockRepositoryDispatchContext with realistic payload structure - Add repository_dispatch mode detection tests in registry.test.ts - Add repository_dispatch trigger tests in agent.test.ts - Ensure repository_dispatch events are properly handled as automation events - Verify agent mode trigger behavior with and without prompts - All 394 tests passing with new coverage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * style: format test files with prettier 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +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
|
||||||
- `repository_dispatch` - Custom events triggered via API (coming soon)
|
- `repository_dispatch` - Custom events triggered via API
|
||||||
- `workflow_dispatch` - Manual workflow triggers (coming soon)
|
- `workflow_dispatch` - Manual workflow triggers (coming soon)
|
||||||
|
|
||||||
## Automated Documentation Updates
|
## Automated Documentation Updates
|
||||||
|
|||||||
@@ -26,6 +26,20 @@ export type WorkflowDispatchEvent = {
|
|||||||
workflow: string;
|
workflow: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type RepositoryDispatchEvent = {
|
||||||
|
action: string;
|
||||||
|
client_payload?: Record<string, any>;
|
||||||
|
repository: {
|
||||||
|
name: string;
|
||||||
|
owner: {
|
||||||
|
login: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
sender: {
|
||||||
|
login: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type ScheduleEvent = {
|
export type ScheduleEvent = {
|
||||||
action?: never;
|
action?: never;
|
||||||
schedule?: string;
|
schedule?: string;
|
||||||
@@ -48,6 +62,7 @@ const ENTITY_EVENT_NAMES = [
|
|||||||
|
|
||||||
const AUTOMATION_EVENT_NAMES = [
|
const AUTOMATION_EVENT_NAMES = [
|
||||||
"workflow_dispatch",
|
"workflow_dispatch",
|
||||||
|
"repository_dispatch",
|
||||||
"schedule",
|
"schedule",
|
||||||
"workflow_run",
|
"workflow_run",
|
||||||
] as const;
|
] as const;
|
||||||
@@ -95,10 +110,14 @@ export type ParsedGitHubContext = BaseContext & {
|
|||||||
isPR: boolean;
|
isPR: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Context for automation events (workflow_dispatch, schedule, workflow_run)
|
// Context for automation events (workflow_dispatch, repository_dispatch, schedule, workflow_run)
|
||||||
export type AutomationContext = BaseContext & {
|
export type AutomationContext = BaseContext & {
|
||||||
eventName: AutomationEventName;
|
eventName: AutomationEventName;
|
||||||
payload: WorkflowDispatchEvent | ScheduleEvent | WorkflowRunEvent;
|
payload:
|
||||||
|
| WorkflowDispatchEvent
|
||||||
|
| RepositoryDispatchEvent
|
||||||
|
| ScheduleEvent
|
||||||
|
| WorkflowRunEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Union type for all contexts
|
// Union type for all contexts
|
||||||
@@ -190,6 +209,13 @@ export function parseGitHubContext(): GitHubContext {
|
|||||||
payload: context.payload as unknown as WorkflowDispatchEvent,
|
payload: context.payload as unknown as WorkflowDispatchEvent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case "repository_dispatch": {
|
||||||
|
return {
|
||||||
|
...commonFields,
|
||||||
|
eventName: "repository_dispatch",
|
||||||
|
payload: context.payload as unknown as RepositoryDispatchEvent,
|
||||||
|
};
|
||||||
|
}
|
||||||
case "schedule": {
|
case "schedule": {
|
||||||
return {
|
return {
|
||||||
...commonFields,
|
...commonFields,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type {
|
import type {
|
||||||
ParsedGitHubContext,
|
ParsedGitHubContext,
|
||||||
AutomationContext,
|
AutomationContext,
|
||||||
|
RepositoryDispatchEvent,
|
||||||
} from "../src/github/context";
|
} from "../src/github/context";
|
||||||
import type {
|
import type {
|
||||||
IssuesEvent,
|
IssuesEvent,
|
||||||
@@ -81,6 +82,33 @@ export const createMockAutomationContext = (
|
|||||||
return { ...baseContext, ...overrides, inputs: mergedInputs };
|
return { ...baseContext, ...overrides, inputs: mergedInputs };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mockRepositoryDispatchContext: AutomationContext = {
|
||||||
|
runId: "1234567890",
|
||||||
|
eventName: "repository_dispatch",
|
||||||
|
eventAction: undefined,
|
||||||
|
repository: defaultRepository,
|
||||||
|
actor: "automation-user",
|
||||||
|
payload: {
|
||||||
|
action: "trigger-analysis",
|
||||||
|
client_payload: {
|
||||||
|
source: "issue-detective",
|
||||||
|
issue_number: 42,
|
||||||
|
repository_name: "test-owner/test-repo",
|
||||||
|
analysis_type: "bug-report",
|
||||||
|
},
|
||||||
|
repository: {
|
||||||
|
name: "test-repo",
|
||||||
|
owner: {
|
||||||
|
login: "test-owner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sender: {
|
||||||
|
login: "automation-user",
|
||||||
|
},
|
||||||
|
} as RepositoryDispatchEvent,
|
||||||
|
inputs: defaultInputs,
|
||||||
|
};
|
||||||
|
|
||||||
export const mockIssueOpenedContext: ParsedGitHubContext = {
|
export const mockIssueOpenedContext: ParsedGitHubContext = {
|
||||||
runId: "1234567890",
|
runId: "1234567890",
|
||||||
eventName: "issues",
|
eventName: "issues",
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ describe("Agent Mode", () => {
|
|||||||
});
|
});
|
||||||
expect(agentMode.shouldTrigger(scheduleContext)).toBe(false);
|
expect(agentMode.shouldTrigger(scheduleContext)).toBe(false);
|
||||||
|
|
||||||
|
const repositoryDispatchContext = createMockAutomationContext({
|
||||||
|
eventName: "repository_dispatch",
|
||||||
|
});
|
||||||
|
expect(agentMode.shouldTrigger(repositoryDispatchContext)).toBe(false);
|
||||||
|
|
||||||
// Should NOT trigger for entity events without prompt
|
// Should NOT trigger for entity events without prompt
|
||||||
const entityEvents = [
|
const entityEvents = [
|
||||||
"issue_comment",
|
"issue_comment",
|
||||||
@@ -92,6 +97,7 @@ describe("Agent Mode", () => {
|
|||||||
// Should trigger for ANY event when prompt is provided
|
// Should trigger for ANY event when prompt is provided
|
||||||
const allEvents = [
|
const allEvents = [
|
||||||
"workflow_dispatch",
|
"workflow_dispatch",
|
||||||
|
"repository_dispatch",
|
||||||
"schedule",
|
"schedule",
|
||||||
"issue_comment",
|
"issue_comment",
|
||||||
"pull_request",
|
"pull_request",
|
||||||
@@ -101,7 +107,9 @@ describe("Agent Mode", () => {
|
|||||||
|
|
||||||
allEvents.forEach((eventName) => {
|
allEvents.forEach((eventName) => {
|
||||||
const contextWithPrompt =
|
const contextWithPrompt =
|
||||||
eventName === "workflow_dispatch" || eventName === "schedule"
|
eventName === "workflow_dispatch" ||
|
||||||
|
eventName === "repository_dispatch" ||
|
||||||
|
eventName === "schedule"
|
||||||
? createMockAutomationContext({
|
? createMockAutomationContext({
|
||||||
eventName,
|
eventName,
|
||||||
inputs: { prompt: "Do something" },
|
inputs: { prompt: "Do something" },
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import { describe, test, expect } from "bun:test";
|
|||||||
import { getMode, isValidMode } from "../../src/modes/registry";
|
import { getMode, isValidMode } from "../../src/modes/registry";
|
||||||
import { agentMode } from "../../src/modes/agent";
|
import { agentMode } from "../../src/modes/agent";
|
||||||
import { tagMode } from "../../src/modes/tag";
|
import { tagMode } from "../../src/modes/tag";
|
||||||
import { createMockContext, createMockAutomationContext } from "../mockContext";
|
import {
|
||||||
|
createMockContext,
|
||||||
|
createMockAutomationContext,
|
||||||
|
mockRepositoryDispatchContext,
|
||||||
|
} from "../mockContext";
|
||||||
|
|
||||||
describe("Mode Registry", () => {
|
describe("Mode Registry", () => {
|
||||||
const mockContext = createMockContext({
|
const mockContext = createMockContext({
|
||||||
@@ -50,6 +54,34 @@ describe("Mode Registry", () => {
|
|||||||
expect(mode.name).toBe("agent");
|
expect(mode.name).toBe("agent");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("getMode auto-detects agent for repository_dispatch event", () => {
|
||||||
|
const mode = getMode(mockRepositoryDispatchContext);
|
||||||
|
expect(mode).toBe(agentMode);
|
||||||
|
expect(mode.name).toBe("agent");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getMode auto-detects agent for repository_dispatch with client_payload", () => {
|
||||||
|
const contextWithPayload = createMockAutomationContext({
|
||||||
|
eventName: "repository_dispatch",
|
||||||
|
payload: {
|
||||||
|
action: "trigger-analysis",
|
||||||
|
client_payload: {
|
||||||
|
source: "external-system",
|
||||||
|
metadata: { priority: "high" },
|
||||||
|
},
|
||||||
|
repository: {
|
||||||
|
name: "test-repo",
|
||||||
|
owner: { login: "test-owner" },
|
||||||
|
},
|
||||||
|
sender: { login: "automation-user" },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mode = getMode(contextWithPayload);
|
||||||
|
expect(mode).toBe(agentMode);
|
||||||
|
expect(mode.name).toBe("agent");
|
||||||
|
});
|
||||||
|
|
||||||
// Removed test - legacy mode names no longer supported in v1.0
|
// Removed test - legacy mode names no longer supported in v1.0
|
||||||
|
|
||||||
test("getMode auto-detects agent mode for PR opened", () => {
|
test("getMode auto-detects agent mode for PR opened", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user