refactor: simplify prepare logic with mode-specific implementations

This commit is contained in:
km-anthropic
2025-07-29 08:56:26 -07:00
parent 11d4e4c175
commit 96970dfa2d
7 changed files with 226 additions and 173 deletions

View File

@@ -1,4 +1,8 @@
import type { Mode } from "../types";
import * as core from "@actions/core";
import { mkdir, writeFile } from "fs/promises";
import type { Mode, ModeOptions, ModeResult } from "../types";
import { prepareMcpConfig } from "../../mcp/install-mcp-server";
import { exportToolEnvironmentVariables } from "../../tools/export";
/**
* Agent mode implementation.
@@ -39,4 +43,54 @@ export const agentMode: Mode = {
shouldCreateTrackingComment() {
return false;
},
async prepare({ context, githubToken }: ModeOptions): Promise<ModeResult> {
// Agent mode is designed for automation events (workflow_dispatch, schedule)
// and potentially other events where we want full automation without tracking
// Create prompt directory
await mkdir(`${process.env.RUNNER_TEMP}/claude-prompts`, {
recursive: true,
});
// Write the prompt - either override_prompt, direct_prompt, or a minimal default
const promptContent =
context.inputs.overridePrompt ||
context.inputs.directPrompt ||
`Repository: ${context.repository.owner}/${context.repository.repo}`;
await writeFile(
`${process.env.RUNNER_TEMP}/claude-prompts/claude-prompt.txt`,
promptContent,
);
// Export tool environment variables
exportToolEnvironmentVariables(agentMode, context);
// Get MCP configuration
const additionalMcpConfig = process.env.MCP_CONFIG || "";
const mcpConfig = await prepareMcpConfig({
githubToken,
owner: context.repository.owner,
repo: context.repository.repo,
branch: "", // No specific branch for agent mode
baseBranch: "", // No base branch needed
additionalMcpConfig,
claudeCommentId: "",
allowedTools: context.inputs.allowedTools,
context,
});
core.setOutput("mcp_config", mcpConfig);
return {
commentId: undefined,
branchInfo: {
baseBranch: "",
currentBranch: "",
claudeBranch: undefined,
},
mcpConfig,
};
},
};

View File

@@ -1,5 +1,13 @@
import type { Mode } from "../types";
import * as core from "@actions/core";
import type { Mode, ModeOptions, ModeResult } from "../types";
import { checkContainsTrigger } from "../../github/validation/trigger";
import { checkHumanActor } from "../../github/validation/actor";
import { createInitialComment } from "../../github/operations/comments/create-initial";
import { setupBranch } from "../../github/operations/branch";
import { configureGitAuth } from "../../github/operations/git-config";
import { prepareMcpConfig } from "../../mcp/install-mcp-server";
import { fetchGitHubData } from "../../github/data/fetcher";
import { createPrompt } from "../../create-prompt";
/**
* Tag mode implementation.
@@ -37,4 +45,82 @@ export const tagMode: Mode = {
shouldCreateTrackingComment() {
return true;
},
async prepare({
context,
octokit,
githubToken,
}: ModeOptions): Promise<ModeResult> {
// Tag mode handles entity-based events (issues, PRs, comments)
// Check if actor is human
await checkHumanActor(octokit.rest, context);
// Create initial tracking comment
let commentId: number | undefined;
let commentData:
| Awaited<ReturnType<typeof createInitialComment>>
| undefined;
if (this.shouldCreateTrackingComment()) {
commentData = await createInitialComment(octokit.rest, context);
commentId = commentData.id;
}
// Fetch GitHub data - entity events always have entityNumber and isPR
if (!context.entityNumber || context.isPR === undefined) {
throw new Error("Entity events must have entityNumber and isPR defined");
}
const githubData = await fetchGitHubData({
octokits: octokit,
repository: `${context.repository.owner}/${context.repository.repo}`,
prNumber: context.entityNumber.toString(),
isPR: context.isPR,
triggerUsername: context.actor,
});
// Setup branch
const branchInfo = await setupBranch(octokit, githubData, context);
// Configure git authentication if not using commit signing
if (!context.inputs.useCommitSigning) {
try {
await configureGitAuth(githubToken, context, commentData?.user || null);
} catch (error) {
console.error("Failed to configure git authentication:", error);
throw error;
}
}
// Create prompt file
const modeContext = this.prepareContext(context, {
commentId,
baseBranch: branchInfo.baseBranch,
claudeBranch: branchInfo.claudeBranch,
});
await createPrompt(tagMode, modeContext, githubData, context);
// Get MCP configuration
const additionalMcpConfig = process.env.MCP_CONFIG || "";
const mcpConfig = await prepareMcpConfig({
githubToken,
owner: context.repository.owner,
repo: context.repository.repo,
branch: branchInfo.claudeBranch || branchInfo.currentBranch,
baseBranch: branchInfo.baseBranch,
additionalMcpConfig,
claudeCommentId: commentId?.toString() || "",
allowedTools: context.inputs.allowedTools,
context,
});
core.setOutput("mcp_config", mcpConfig);
return {
commentId,
branchInfo,
mcpConfig,
};
},
};

View File

@@ -53,4 +53,28 @@ export type Mode = {
* Determines if this mode should create a tracking comment
*/
shouldCreateTrackingComment(): boolean;
/**
* Prepares the GitHub environment for this mode.
* Each mode decides how to handle different event types.
* @returns PrepareResult with commentId, branchInfo, and mcpConfig
*/
prepare(options: ModeOptions): Promise<ModeResult>;
};
// Define types for mode prepare method to avoid circular dependencies
export type ModeOptions = {
context: ParsedGitHubContext;
octokit: any; // We'll use any to avoid circular dependency with Octokits
githubToken: string;
};
export type ModeResult = {
commentId?: number;
branchInfo: {
baseBranch: string;
claudeBranch?: string;
currentBranch: string;
};
mcpConfig: string;
};