Replace the over-engineered Mode interface/registry/detector pattern with straightforward inline logic. There are only 2 modes (tag and agent) and the complexity wasn't justified. - Delete Mode interface, registry, and prepare pass-through modules - Export prepareTagMode() and prepareAgentMode() as standalone functions - Inline trigger checking and mode dispatch in run.ts/prepare.ts - Change generatePrompt/createPrompt to take modeName string instead of Mode - Remove dead code (extractGitHubContext, unused detector helpers) - Update CLAUDE.md to reflect new architecture
100 lines
3.3 KiB
TypeScript
100 lines
3.3 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 { checkWritePermissions } from "../github/validation/permissions";
|
|
import { createOctokit } from "../github/api/client";
|
|
import { parseGitHubContext, isEntityContext } from "../github/context";
|
|
import { detectMode } from "../modes/detector";
|
|
import { prepareTagMode } from "../modes/tag";
|
|
import { prepareAgentMode } from "../modes/agent";
|
|
import { checkContainsTrigger } from "../github/validation/trigger";
|
|
import { collectActionInputsPresence } from "./collect-inputs";
|
|
|
|
async function run() {
|
|
try {
|
|
collectActionInputsPresence();
|
|
|
|
// Parse GitHub context first to enable mode detection
|
|
const context = parseGitHubContext();
|
|
|
|
// Auto-detect mode based on context
|
|
const modeName = detectMode(context);
|
|
console.log(
|
|
`Auto-detected mode: ${modeName} for event: ${context.eventName}`,
|
|
);
|
|
|
|
// Setup GitHub token
|
|
const githubToken = await setupGitHubToken();
|
|
const octokit = createOctokit(githubToken);
|
|
|
|
// Step 3: Check write permissions (only for entity contexts)
|
|
if (isEntityContext(context)) {
|
|
// Check if github_token was provided as input (not from app)
|
|
const githubTokenProvided = !!process.env.OVERRIDE_GITHUB_TOKEN;
|
|
const hasWritePermissions = await checkWritePermissions(
|
|
octokit.rest,
|
|
context,
|
|
context.inputs.allowedNonWriteUsers,
|
|
githubTokenProvided,
|
|
);
|
|
if (!hasWritePermissions) {
|
|
throw new Error(
|
|
"Actor does not have write permissions to the repository",
|
|
);
|
|
}
|
|
}
|
|
|
|
// Check trigger conditions
|
|
const containsTrigger =
|
|
modeName === "tag"
|
|
? isEntityContext(context) && checkContainsTrigger(context)
|
|
: !!context.inputs?.prompt;
|
|
|
|
// Debug logging
|
|
console.log(`Mode: ${modeName}`);
|
|
console.log(`Context prompt: ${context.inputs?.prompt || "NO PROMPT"}`);
|
|
console.log(`Trigger result: ${containsTrigger}`);
|
|
|
|
// Set output for action.yml to check
|
|
core.setOutput("contains_trigger", containsTrigger.toString());
|
|
|
|
if (!containsTrigger) {
|
|
console.log("No trigger found, skipping remaining steps");
|
|
// Still set github_token output even when skipping
|
|
core.setOutput("github_token", githubToken);
|
|
return;
|
|
}
|
|
|
|
// Run prepare
|
|
console.log(
|
|
`Preparing with mode: ${modeName} for event: ${context.eventName}`,
|
|
);
|
|
if (modeName === "tag") {
|
|
await prepareTagMode({ context, octokit, githubToken });
|
|
} else {
|
|
await prepareAgentMode({ context, octokit, githubToken });
|
|
}
|
|
|
|
// MCP config is handled by individual modes (tag/agent) and included in their claude_args output
|
|
|
|
// Expose the GitHub token (Claude App token) as an output
|
|
core.setOutput("github_token", githubToken);
|
|
} 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();
|
|
}
|