mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 15:04:13 +08:00
* feat: add agent mode for automation scenarios - Add agent mode that always triggers without checking for mentions - Implement Mode interface with support for mode-specific tool configuration - Add getAllowedTools() and getDisallowedTools() methods to Mode interface - Simplify tests by combining related test cases - Update documentation and examples to include agent mode - Fix TypeScript imports to prevent circular dependencies Agent mode is designed for automation and workflow_dispatch scenarios where Claude should always run without requiring trigger phrases. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Minor update to readme (from @main to @beta) * Since workflow_dispatch isn't in the base action, update the examples accordingly * minor formatting issue * Update to say beta instead of main * Fix missed tracking comment to be false --------- Co-authored-by: km-anthropic <km-anthropic@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
125 lines
4.2 KiB
TypeScript
125 lines
4.2 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
/**
|
|
* Prepare the Claude action by checking trigger conditions, verifying human actor,
|
|
* and creating the initial tracking comment
|
|
*/
|
|
|
|
import * as core from "@actions/core";
|
|
import { setupGitHubToken } from "../github/token";
|
|
import { checkHumanActor } from "../github/validation/actor";
|
|
import { checkWritePermissions } from "../github/validation/permissions";
|
|
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 { createOctokit } from "../github/api/client";
|
|
import { fetchGitHubData } from "../github/data/fetcher";
|
|
import { parseGitHubContext } from "../github/context";
|
|
import { getMode } from "../modes/registry";
|
|
import { createPrompt } from "../create-prompt";
|
|
|
|
async function run() {
|
|
try {
|
|
// Step 1: Setup GitHub token
|
|
const githubToken = await setupGitHubToken();
|
|
const octokit = createOctokit(githubToken);
|
|
|
|
// Step 2: Parse GitHub context (once for all operations)
|
|
const context = parseGitHubContext();
|
|
|
|
// Step 3: Check write permissions
|
|
const hasWritePermissions = await checkWritePermissions(
|
|
octokit.rest,
|
|
context,
|
|
);
|
|
if (!hasWritePermissions) {
|
|
throw new Error(
|
|
"Actor does not have write permissions to the repository",
|
|
);
|
|
}
|
|
|
|
// Step 4: Get mode and check trigger conditions
|
|
const mode = getMode(context.inputs.mode);
|
|
const containsTrigger = mode.shouldTrigger(context);
|
|
|
|
// Set output for action.yml to check
|
|
core.setOutput("contains_trigger", containsTrigger.toString());
|
|
|
|
if (!containsTrigger) {
|
|
console.log("No trigger found, skipping remaining steps");
|
|
return;
|
|
}
|
|
|
|
// Step 5: Check if actor is human
|
|
await checkHumanActor(octokit.rest, context);
|
|
|
|
// Step 6: Create initial tracking comment (mode-aware)
|
|
// Some modes (e.g., agent mode) may not need tracking comments
|
|
let commentId: number | undefined;
|
|
let commentData:
|
|
| Awaited<ReturnType<typeof createInitialComment>>
|
|
| undefined;
|
|
if (mode.shouldCreateTrackingComment()) {
|
|
commentData = await createInitialComment(octokit.rest, context);
|
|
commentId = commentData.id;
|
|
}
|
|
|
|
// Step 7: Fetch GitHub data (once for both branch setup and prompt creation)
|
|
const githubData = await fetchGitHubData({
|
|
octokits: octokit,
|
|
repository: `${context.repository.owner}/${context.repository.repo}`,
|
|
prNumber: context.entityNumber.toString(),
|
|
isPR: context.isPR,
|
|
triggerUsername: context.actor,
|
|
});
|
|
|
|
// Step 8: Setup branch
|
|
const branchInfo = await setupBranch(octokit, githubData, context);
|
|
|
|
// Step 9: 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;
|
|
}
|
|
}
|
|
|
|
// Step 10: Create prompt file
|
|
const modeContext = mode.prepareContext(context, {
|
|
commentId,
|
|
baseBranch: branchInfo.baseBranch,
|
|
claudeBranch: branchInfo.claudeBranch,
|
|
});
|
|
|
|
await createPrompt(mode, modeContext, githubData, context);
|
|
|
|
// Step 11: 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);
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
core.setFailed(`Prepare step failed with error: ${errorMessage}`);
|
|
// Also output the clean error message for the action to capture
|
|
core.setOutput("prepare_error", errorMessage);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
run();
|
|
}
|