diff --git a/docs/custom-automations.md b/docs/custom-automations.md index ae5ff36..47fe9d7 100644 --- a/docs/custom-automations.md +++ b/docs/custom-automations.md @@ -21,7 +21,7 @@ This action supports the following GitHub events ([learn more GitHub event trigg - `issues` - When issues are opened or assigned - `pull_request_review` - When PR reviews are submitted - `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) ## Automated Documentation Updates diff --git a/src/github/context.ts b/src/github/context.ts index 94ef4f8..de4dd08 100644 --- a/src/github/context.ts +++ b/src/github/context.ts @@ -26,6 +26,20 @@ export type WorkflowDispatchEvent = { workflow: string; }; +export type RepositoryDispatchEvent = { + action: string; + client_payload?: Record; + repository: { + name: string; + owner: { + login: string; + }; + }; + sender: { + login: string; + }; +}; + export type ScheduleEvent = { action?: never; schedule?: string; @@ -48,6 +62,7 @@ const ENTITY_EVENT_NAMES = [ const AUTOMATION_EVENT_NAMES = [ "workflow_dispatch", + "repository_dispatch", "schedule", "workflow_run", ] as const; @@ -95,10 +110,14 @@ export type ParsedGitHubContext = BaseContext & { 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 & { eventName: AutomationEventName; - payload: WorkflowDispatchEvent | ScheduleEvent | WorkflowRunEvent; + payload: + | WorkflowDispatchEvent + | RepositoryDispatchEvent + | ScheduleEvent + | WorkflowRunEvent; }; // Union type for all contexts @@ -190,6 +209,13 @@ export function parseGitHubContext(): GitHubContext { payload: context.payload as unknown as WorkflowDispatchEvent, }; } + case "repository_dispatch": { + return { + ...commonFields, + eventName: "repository_dispatch", + payload: context.payload as unknown as RepositoryDispatchEvent, + }; + } case "schedule": { return { ...commonFields, diff --git a/test/mockContext.ts b/test/mockContext.ts index 57716da..c375f18 100644 --- a/test/mockContext.ts +++ b/test/mockContext.ts @@ -1,6 +1,7 @@ import type { ParsedGitHubContext, AutomationContext, + RepositoryDispatchEvent, } from "../src/github/context"; import type { IssuesEvent, @@ -81,6 +82,33 @@ export const createMockAutomationContext = ( 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 = { runId: "1234567890", eventName: "issues", diff --git a/test/modes/agent.test.ts b/test/modes/agent.test.ts index 9a67e1c..9811707 100644 --- a/test/modes/agent.test.ts +++ b/test/modes/agent.test.ts @@ -76,6 +76,11 @@ describe("Agent Mode", () => { }); 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 const entityEvents = [ "issue_comment", @@ -92,6 +97,7 @@ describe("Agent Mode", () => { // Should trigger for ANY event when prompt is provided const allEvents = [ "workflow_dispatch", + "repository_dispatch", "schedule", "issue_comment", "pull_request", @@ -101,7 +107,9 @@ describe("Agent Mode", () => { allEvents.forEach((eventName) => { const contextWithPrompt = - eventName === "workflow_dispatch" || eventName === "schedule" + eventName === "workflow_dispatch" || + eventName === "repository_dispatch" || + eventName === "schedule" ? createMockAutomationContext({ eventName, inputs: { prompt: "Do something" }, diff --git a/test/modes/registry.test.ts b/test/modes/registry.test.ts index bdeac27..7c585b2 100644 --- a/test/modes/registry.test.ts +++ b/test/modes/registry.test.ts @@ -2,7 +2,11 @@ import { describe, test, expect } from "bun:test"; import { getMode, isValidMode } from "../../src/modes/registry"; import { agentMode } from "../../src/modes/agent"; import { tagMode } from "../../src/modes/tag"; -import { createMockContext, createMockAutomationContext } from "../mockContext"; +import { + createMockContext, + createMockAutomationContext, + mockRepositoryDispatchContext, +} from "../mockContext"; describe("Mode Registry", () => { const mockContext = createMockContext({ @@ -50,6 +54,34 @@ describe("Mode Registry", () => { 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 test("getMode auto-detects agent mode for PR opened", () => {