refactor: complete v1.0 simplification by removing all legacy inputs

- Remove all backward compatibility for v1.0 simplification
- Remove 10 legacy inputs from base-action/action.yml
- Remove 9 legacy inputs from main action.yml
- Simplify ClaudeOptions type to just timeoutMinutes and claudeArgs
- Remove all legacy option handling from prepareRunConfig
- Update tests to remove references to deleted fields
- Remove obsolete test file github/context.test.ts
- Clean up types to remove customInstructions, allowedTools, disallowedTools

Users now use claudeArgs exclusively for CLI control.
This commit is contained in:
km-anthropic
2025-08-08 00:32:57 -07:00
parent f2775d66df
commit f59258677e
23 changed files with 47 additions and 715 deletions

View File

@@ -14,47 +14,10 @@ inputs:
description: "Path to a file containing the prompt to send to Claude Code (mutually exclusive with prompt)"
required: false
default: ""
allowed_tools:
description: "Comma-separated list of allowed tools for Claude Code to use"
required: false
default: ""
disallowed_tools:
description: "Comma-separated list of disallowed tools that Claude Code cannot use"
required: false
default: ""
max_turns:
description: "Maximum number of conversation turns (default: no limit)"
required: false
default: ""
mcp_config:
description: "MCP configuration as JSON string or path to MCP configuration JSON file"
required: false
default: ""
settings:
description: "Claude Code settings as JSON string or path to settings JSON file"
required: false
default: ""
system_prompt:
description: "Override system prompt"
required: false
default: ""
append_system_prompt:
description: "Append to system prompt"
required: false
default: ""
model:
description: "Model to use (provider-specific format required for Bedrock/Vertex)"
required: false
anthropic_model:
description: "DEPRECATED: Use 'model' instead. Model to use (provider-specific format required for Bedrock/Vertex)"
required: false
fallback_model:
description: "Enable automatic fallback to specified model when default model is unavailable"
required: false
claude_env:
description: "Custom environment variables to pass to Claude Code execution (YAML multiline format)"
required: false
default: ""
# Action settings
timeout_minutes:
@@ -137,19 +100,11 @@ runs:
env:
# Model configuration
CLAUDE_CODE_ACTION: "1"
ANTHROPIC_MODEL: ${{ inputs.model || inputs.anthropic_model }}
INPUT_PROMPT: ${{ inputs.prompt }}
INPUT_PROMPT_FILE: ${{ inputs.prompt_file }}
INPUT_ALLOWED_TOOLS: ${{ inputs.allowed_tools }}
INPUT_DISALLOWED_TOOLS: ${{ inputs.disallowed_tools }}
INPUT_MAX_TURNS: ${{ inputs.max_turns }}
INPUT_MCP_CONFIG: ${{ inputs.mcp_config }}
INPUT_SETTINGS: ${{ inputs.settings }}
INPUT_SYSTEM_PROMPT: ${{ inputs.system_prompt }}
INPUT_APPEND_SYSTEM_PROMPT: ${{ inputs.append_system_prompt }}
INPUT_TIMEOUT_MINUTES: ${{ inputs.timeout_minutes }}
INPUT_CLAUDE_ENV: ${{ inputs.claude_env }}
INPUT_FALLBACK_MODEL: ${{ inputs.fallback_model }}
INPUT_CLAUDE_ARGS: ${{ inputs.claude_args }}
INPUT_EXPERIMENTAL_SLASH_COMMANDS_DIR: ${{ inputs.experimental_slash_commands_dir }}
# Provider configuration

View File

@@ -22,15 +22,7 @@ async function run() {
});
await runClaude(promptConfig.path, {
allowedTools: process.env.INPUT_ALLOWED_TOOLS,
disallowedTools: process.env.INPUT_DISALLOWED_TOOLS,
maxTurns: process.env.INPUT_MAX_TURNS,
mcpConfig: process.env.INPUT_MCP_CONFIG,
systemPrompt: process.env.INPUT_SYSTEM_PROMPT,
appendSystemPrompt: process.env.INPUT_APPEND_SYSTEM_PROMPT,
claudeEnv: process.env.INPUT_CLAUDE_ENV,
fallbackModel: process.env.INPUT_FALLBACK_MODEL,
model: process.env.ANTHROPIC_MODEL,
timeoutMinutes: process.env.INPUT_TIMEOUT_MINUTES,
claudeArgs: process.env.INPUT_CLAUDE_ARGS,
});
} catch (error) {

View File

@@ -10,20 +10,10 @@ const execAsync = promisify(exec);
const PIPE_PATH = `${process.env.RUNNER_TEMP}/claude_prompt_pipe`;
const EXECUTION_FILE = `${process.env.RUNNER_TEMP}/claude-execution-output.json`;
// These base args are always appended at the end
const BASE_ARGS = ["--verbose", "--output-format", "stream-json"];
export type ClaudeOptions = {
allowedTools?: string;
disallowedTools?: string;
maxTurns?: string;
mcpConfig?: string;
systemPrompt?: string;
appendSystemPrompt?: string;
claudeEnv?: string;
fallbackModel?: string;
timeoutMinutes?: string;
model?: string;
claudeArgs?: string;
};
@@ -33,48 +23,19 @@ type PreparedConfig = {
env: Record<string, string>;
};
function parseCustomEnvVars(claudeEnv?: string): Record<string, string> {
if (!claudeEnv || claudeEnv.trim() === "") {
return {};
}
const customEnv: Record<string, string> = {};
// Split by lines and parse each line as KEY: VALUE
const lines = claudeEnv.split("\n");
for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine === "" || trimmedLine.startsWith("#")) {
continue; // Skip empty lines and comments
}
const colonIndex = trimmedLine.indexOf(":");
if (colonIndex === -1) {
continue; // Skip lines without colons
}
const key = trimmedLine.substring(0, colonIndex).trim();
const value = trimmedLine.substring(colonIndex + 1).trim();
if (key) {
customEnv[key] = value;
}
}
return customEnv;
}
export function prepareRunConfig(
promptPath: string,
options: ClaudeOptions,
): PreparedConfig {
// Build arguments in correct order:
// 1. -p flag for prompt via pipe
// Build Claude CLI arguments:
// 1. Prompt flag (always first)
// 2. User's claudeArgs (full control)
// 3. BASE_ARGS (always last, cannot be overridden)
const claudeArgs = ["-p"];
// 2. User's custom arguments (can override defaults)
if (options.claudeArgs && options.claudeArgs.trim() !== "") {
// Parse and add user's custom Claude arguments
if (options.claudeArgs?.trim()) {
const parsed = parseShellArgs(options.claudeArgs);
const customArgs = parsed.filter(
(arg): arg is string => typeof arg === "string",
@@ -82,34 +43,7 @@ export function prepareRunConfig(
claudeArgs.push(...customArgs);
}
// 3. Legacy specific options for backward compatibility
// These will eventually be removed in favor of claudeArgs
if (options.allowedTools) {
claudeArgs.push("--allowedTools", options.allowedTools);
}
if (options.disallowedTools) {
claudeArgs.push("--disallowedTools", options.disallowedTools);
}
if (options.maxTurns) {
claudeArgs.push("--max-turns", options.maxTurns);
}
if (options.mcpConfig) {
claudeArgs.push("--mcp-config", options.mcpConfig);
}
if (options.systemPrompt) {
claudeArgs.push("--system-prompt", options.systemPrompt);
}
if (options.appendSystemPrompt) {
claudeArgs.push("--append-system-prompt", options.appendSystemPrompt);
}
if (options.fallbackModel) {
claudeArgs.push("--fallback-model", options.fallbackModel);
}
if (options.model) {
claudeArgs.push("--model", options.model);
}
// 4. Base args always at the end
// BASE_ARGS are always appended last (cannot be overridden)
claudeArgs.push(...BASE_ARGS);
// Validate timeout if provided (affects process wrapper, not Claude)
@@ -122,13 +56,10 @@ export function prepareRunConfig(
}
}
// Parse custom environment variables
const customEnv = parseCustomEnvVars(options.claudeEnv);
return {
claudeArgs,
promptPath,
env: customEnv,
env: {},
};
}

View File

@@ -23,79 +23,6 @@ describe("prepareRunConfig", () => {
expect(prepared.promptPath).toBe("/tmp/test-prompt.txt");
});
test("should include allowed tools in command arguments", () => {
const options: ClaudeOptions = {
allowedTools: "Bash,Read",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--allowedTools");
expect(prepared.claudeArgs).toContain("Bash,Read");
});
test("should include disallowed tools in command arguments", () => {
const options: ClaudeOptions = {
disallowedTools: "Bash,Read",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--disallowedTools");
expect(prepared.claudeArgs).toContain("Bash,Read");
});
test("should include max turns in command arguments", () => {
const options: ClaudeOptions = {
maxTurns: "5",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--max-turns");
expect(prepared.claudeArgs).toContain("5");
});
test("should include mcp config in command arguments", () => {
const options: ClaudeOptions = {
mcpConfig: "/path/to/mcp-config.json",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--mcp-config");
expect(prepared.claudeArgs).toContain("/path/to/mcp-config.json");
});
test("should include system prompt in command arguments", () => {
const options: ClaudeOptions = {
systemPrompt: "You are a senior backend engineer.",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--system-prompt");
expect(prepared.claudeArgs).toContain("You are a senior backend engineer.");
});
test("should include append system prompt in command arguments", () => {
const options: ClaudeOptions = {
appendSystemPrompt:
"After writing code, be sure to code review yourself.",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--append-system-prompt");
expect(prepared.claudeArgs).toContain(
"After writing code, be sure to code review yourself.",
);
});
test("should include fallback model in command arguments", () => {
const options: ClaudeOptions = {
fallbackModel: "claude-sonnet-4-20250514",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--fallback-model");
expect(prepared.claudeArgs).toContain("claude-sonnet-4-20250514");
});
test("should use provided prompt path", () => {
const options: ClaudeOptions = {};
const prepared = prepareRunConfig("/custom/prompt/path.txt", options);
@@ -103,105 +30,6 @@ describe("prepareRunConfig", () => {
expect(prepared.promptPath).toBe("/custom/prompt/path.txt");
});
test("should not include optional arguments when not set", () => {
const options: ClaudeOptions = {};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).not.toContain("--allowedTools");
expect(prepared.claudeArgs).not.toContain("--disallowedTools");
expect(prepared.claudeArgs).not.toContain("--max-turns");
expect(prepared.claudeArgs).not.toContain("--mcp-config");
expect(prepared.claudeArgs).not.toContain("--system-prompt");
expect(prepared.claudeArgs).not.toContain("--append-system-prompt");
expect(prepared.claudeArgs).not.toContain("--fallback-model");
});
test("should preserve order of claude arguments", () => {
const options: ClaudeOptions = {
allowedTools: "Bash,Read",
maxTurns: "3",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toEqual([
"-p",
"--allowedTools",
"Bash,Read",
"--max-turns",
"3",
"--verbose",
"--output-format",
"stream-json",
]);
});
test("should preserve order with all options including fallback model", () => {
const options: ClaudeOptions = {
allowedTools: "Bash,Read",
disallowedTools: "Write",
maxTurns: "3",
mcpConfig: "/path/to/config.json",
systemPrompt: "You are a helpful assistant",
appendSystemPrompt: "Be concise",
fallbackModel: "claude-sonnet-4-20250514",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toEqual([
"-p",
"--allowedTools",
"Bash,Read",
"--disallowedTools",
"Write",
"--max-turns",
"3",
"--mcp-config",
"/path/to/config.json",
"--system-prompt",
"You are a helpful assistant",
"--append-system-prompt",
"Be concise",
"--fallback-model",
"claude-sonnet-4-20250514",
"--verbose",
"--output-format",
"stream-json",
]);
});
describe("maxTurns handling", () => {
test("should accept valid maxTurns value", () => {
const options: ClaudeOptions = { maxTurns: "5" };
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toContain("--max-turns");
expect(prepared.claudeArgs).toContain("5");
});
test("should pass through non-numeric maxTurns without validation (v1.0)", () => {
const options: ClaudeOptions = { maxTurns: "abc" };
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
// v1.0: No validation - let Claude handle it
expect(prepared.claudeArgs).toContain("--max-turns");
expect(prepared.claudeArgs).toContain("abc");
});
test("should pass through negative maxTurns without validation (v1.0)", () => {
const options: ClaudeOptions = { maxTurns: "-1" };
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
// v1.0: No validation - let Claude handle it
expect(prepared.claudeArgs).toContain("--max-turns");
expect(prepared.claudeArgs).toContain("-1");
});
test("should pass through zero maxTurns without validation (v1.0)", () => {
const options: ClaudeOptions = { maxTurns: "0" };
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
// v1.0: No validation - let Claude handle it
expect(prepared.claudeArgs).toContain("--max-turns");
expect(prepared.claudeArgs).toContain("0");
});
});
describe("timeoutMinutes validation", () => {
test("should accept valid timeoutMinutes value", () => {
const options: ClaudeOptions = { timeoutMinutes: "15" };
@@ -251,25 +79,6 @@ describe("prepareRunConfig", () => {
]);
});
test("should handle claudeArgs with legacy options", () => {
const options: ClaudeOptions = {
claudeArgs: "--max-turns 10",
allowedTools: "Bash,Read",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.claudeArgs).toEqual([
"-p",
"--max-turns",
"10",
"--allowedTools",
"Bash,Read",
"--verbose",
"--output-format",
"stream-json",
]);
});
test("should handle empty claudeArgs", () => {
const options: ClaudeOptions = {
claudeArgs: "",
@@ -300,70 +109,4 @@ describe("prepareRunConfig", () => {
]);
});
});
describe("custom environment variables", () => {
test("should parse empty claudeEnv correctly", () => {
const options: ClaudeOptions = { claudeEnv: "" };
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.env).toEqual({});
});
test("should parse single environment variable", () => {
const options: ClaudeOptions = { claudeEnv: "API_KEY: secret123" };
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.env).toEqual({ API_KEY: "secret123" });
});
test("should parse multiple environment variables", () => {
const options: ClaudeOptions = {
claudeEnv: "API_KEY: secret123\nDEBUG: true\nUSER: testuser",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.env).toEqual({
API_KEY: "secret123",
DEBUG: "true",
USER: "testuser",
});
});
test("should handle environment variables with spaces around values", () => {
const options: ClaudeOptions = {
claudeEnv: "API_KEY: secret123 \n DEBUG : true ",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.env).toEqual({
API_KEY: "secret123",
DEBUG: "true",
});
});
test("should skip empty lines and comments", () => {
const options: ClaudeOptions = {
claudeEnv:
"API_KEY: secret123\n\n# This is a comment\nDEBUG: true\n# Another comment",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.env).toEqual({
API_KEY: "secret123",
DEBUG: "true",
});
});
test("should skip lines without colons", () => {
const options: ClaudeOptions = {
claudeEnv: "API_KEY: secret123\nINVALID_LINE\nDEBUG: true",
};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.env).toEqual({
API_KEY: "secret123",
DEBUG: "true",
});
});
test("should handle undefined claudeEnv", () => {
const options: ClaudeOptions = {};
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
expect(prepared.env).toEqual({});
});
});
});