mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-27 01:52:24 +08:00
* feat: add ssh_signing_key input for SSH commit signing Add a new ssh_signing_key input that allows passing an SSH signing key for commit signing, as an alternative to the existing use_commit_signing (which uses GitHub API-based commits). When ssh_signing_key is provided: - Git is configured to use SSH signing (gpg.format=ssh, commit.gpgsign=true) - The key is written to ~/.ssh/claude_signing_key with 0600 permissions - Git CLI commands are used (not MCP file ops) - The key is cleaned up in a post step for security Behavior matrix: | ssh_signing_key | use_commit_signing | Result | |-----------------|-------------------|--------| | not set | false | Regular git, no signing | | not set | true | GitHub API (MCP), verified commits | | set | false | Git CLI with SSH signing | | set | true | Git CLI with SSH signing (ssh_signing_key takes precedence) * docs: add SSH signing key documentation - Update security.md with detailed setup instructions for both signing options - Explain that ssh_signing_key enables full git CLI operations (rebasing, etc.) - Add ssh_signing_key to inputs table in usage.md - Update bot_id/bot_name descriptions to note they're needed for verified commits * fix: address security review feedback for SSH signing - Write SSH key atomically with mode 0o600 (fixes TOCTOU race condition) - Create .ssh directory with mode 0o700 (SSH best practices) - Add input validation for SSH key format - Remove unused chmod import - Add tests for validation logic
59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
import * as core from "@actions/core";
|
|
|
|
export function collectActionInputsPresence(): void {
|
|
const inputDefaults: Record<string, string> = {
|
|
trigger_phrase: "@claude",
|
|
assignee_trigger: "",
|
|
label_trigger: "claude",
|
|
base_branch: "",
|
|
branch_prefix: "claude/",
|
|
allowed_bots: "",
|
|
mode: "tag",
|
|
model: "",
|
|
anthropic_model: "",
|
|
fallback_model: "",
|
|
allowed_tools: "",
|
|
disallowed_tools: "",
|
|
custom_instructions: "",
|
|
direct_prompt: "",
|
|
override_prompt: "",
|
|
additional_permissions: "",
|
|
claude_env: "",
|
|
settings: "",
|
|
anthropic_api_key: "",
|
|
claude_code_oauth_token: "",
|
|
github_token: "",
|
|
max_turns: "",
|
|
use_sticky_comment: "false",
|
|
use_commit_signing: "false",
|
|
ssh_signing_key: "",
|
|
};
|
|
|
|
const allInputsJson = process.env.ALL_INPUTS;
|
|
if (!allInputsJson) {
|
|
console.log("ALL_INPUTS environment variable not found");
|
|
core.setOutput("action_inputs_present", JSON.stringify({}));
|
|
return;
|
|
}
|
|
|
|
let allInputs: Record<string, string>;
|
|
try {
|
|
allInputs = JSON.parse(allInputsJson);
|
|
} catch (e) {
|
|
console.error("Failed to parse ALL_INPUTS JSON:", e);
|
|
core.setOutput("action_inputs_present", JSON.stringify({}));
|
|
return;
|
|
}
|
|
|
|
const presentInputs: Record<string, boolean> = {};
|
|
|
|
for (const [name, defaultValue] of Object.entries(inputDefaults)) {
|
|
const actualValue = allInputs[name] || "";
|
|
|
|
const isSet = actualValue !== defaultValue;
|
|
presentInputs[name] = isSet;
|
|
}
|
|
|
|
core.setOutput("action_inputs_present", JSON.stringify(presentInputs));
|
|
}
|