mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 06:54:13 +08:00
* feat: add use_commit_signing input with default false - Add new input 'use_commit_signing' to action.yml (defaults to false) - Separate comment update functionality into standalone github-comment-server.ts - Update MCP server configuration to conditionally load servers based on signing preference - When commit signing is disabled, use specific Bash git commands (e.g., Bash(git add:*)) - When commit signing is enabled, use github-file-ops-server for atomic commits with signing - Always include github-comment-server for comment updates regardless of signing mode - Update prompt generation to provide appropriate instructions based on signing preference - Add comprehensive test coverage for new functionality This change simplifies the default setup for users who don't need commit signing, while maintaining the option to enable it for those who require GitHub's commit signature verification. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: auto-commit uncommitted changes when commit signing is disabled - Check for uncommitted changes after Claude finishes (non-signing mode only) - Automatically commit and push any uncommitted work to preserve Claude's changes - Update tests to avoid actual git operations during test runs - Pass use_commit_signing flag to branch cleanup logic --------- Co-authored-by: Claude <noreply@anthropic.com>
188 lines
5.4 KiB
TypeScript
188 lines
5.4 KiB
TypeScript
import * as github from "@actions/github";
|
|
import type {
|
|
IssuesEvent,
|
|
IssuesAssignedEvent,
|
|
IssueCommentEvent,
|
|
PullRequestEvent,
|
|
PullRequestReviewEvent,
|
|
PullRequestReviewCommentEvent,
|
|
} from "@octokit/webhooks-types";
|
|
|
|
export type ParsedGitHubContext = {
|
|
runId: string;
|
|
eventName: string;
|
|
eventAction?: string;
|
|
repository: {
|
|
owner: string;
|
|
repo: string;
|
|
full_name: string;
|
|
};
|
|
actor: string;
|
|
payload:
|
|
| IssuesEvent
|
|
| IssueCommentEvent
|
|
| PullRequestEvent
|
|
| PullRequestReviewEvent
|
|
| PullRequestReviewCommentEvent;
|
|
entityNumber: number;
|
|
isPR: boolean;
|
|
inputs: {
|
|
triggerPhrase: string;
|
|
assigneeTrigger: string;
|
|
labelTrigger: string;
|
|
allowedTools: string[];
|
|
disallowedTools: string[];
|
|
customInstructions: string;
|
|
directPrompt: string;
|
|
baseBranch?: string;
|
|
branchPrefix: string;
|
|
useStickyComment: boolean;
|
|
additionalPermissions: Map<string, string>;
|
|
useCommitSigning: boolean;
|
|
};
|
|
};
|
|
|
|
export function parseGitHubContext(): ParsedGitHubContext {
|
|
const context = github.context;
|
|
|
|
const commonFields = {
|
|
runId: process.env.GITHUB_RUN_ID!,
|
|
eventName: context.eventName,
|
|
eventAction: context.payload.action,
|
|
repository: {
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
full_name: `${context.repo.owner}/${context.repo.repo}`,
|
|
},
|
|
actor: context.actor,
|
|
inputs: {
|
|
triggerPhrase: process.env.TRIGGER_PHRASE ?? "@claude",
|
|
assigneeTrigger: process.env.ASSIGNEE_TRIGGER ?? "",
|
|
labelTrigger: process.env.LABEL_TRIGGER ?? "",
|
|
allowedTools: parseMultilineInput(process.env.ALLOWED_TOOLS ?? ""),
|
|
disallowedTools: parseMultilineInput(process.env.DISALLOWED_TOOLS ?? ""),
|
|
customInstructions: process.env.CUSTOM_INSTRUCTIONS ?? "",
|
|
directPrompt: process.env.DIRECT_PROMPT ?? "",
|
|
baseBranch: process.env.BASE_BRANCH,
|
|
branchPrefix: process.env.BRANCH_PREFIX ?? "claude/",
|
|
useStickyComment: process.env.USE_STICKY_COMMENT === "true",
|
|
additionalPermissions: parseAdditionalPermissions(
|
|
process.env.ADDITIONAL_PERMISSIONS ?? "",
|
|
),
|
|
useCommitSigning: process.env.USE_COMMIT_SIGNING === "true",
|
|
},
|
|
};
|
|
|
|
switch (context.eventName) {
|
|
case "issues": {
|
|
return {
|
|
...commonFields,
|
|
payload: context.payload as IssuesEvent,
|
|
entityNumber: (context.payload as IssuesEvent).issue.number,
|
|
isPR: false,
|
|
};
|
|
}
|
|
case "issue_comment": {
|
|
return {
|
|
...commonFields,
|
|
payload: context.payload as IssueCommentEvent,
|
|
entityNumber: (context.payload as IssueCommentEvent).issue.number,
|
|
isPR: Boolean(
|
|
(context.payload as IssueCommentEvent).issue.pull_request,
|
|
),
|
|
};
|
|
}
|
|
case "pull_request": {
|
|
return {
|
|
...commonFields,
|
|
payload: context.payload as PullRequestEvent,
|
|
entityNumber: (context.payload as PullRequestEvent).pull_request.number,
|
|
isPR: true,
|
|
};
|
|
}
|
|
case "pull_request_review": {
|
|
return {
|
|
...commonFields,
|
|
payload: context.payload as PullRequestReviewEvent,
|
|
entityNumber: (context.payload as PullRequestReviewEvent).pull_request
|
|
.number,
|
|
isPR: true,
|
|
};
|
|
}
|
|
case "pull_request_review_comment": {
|
|
return {
|
|
...commonFields,
|
|
payload: context.payload as PullRequestReviewCommentEvent,
|
|
entityNumber: (context.payload as PullRequestReviewCommentEvent)
|
|
.pull_request.number,
|
|
isPR: true,
|
|
};
|
|
}
|
|
default:
|
|
throw new Error(`Unsupported event type: ${context.eventName}`);
|
|
}
|
|
}
|
|
|
|
export function parseMultilineInput(s: string): string[] {
|
|
return s
|
|
.split(/,|[\n\r]+/)
|
|
.map((tool) => tool.replace(/#.+$/, ""))
|
|
.map((tool) => tool.trim())
|
|
.filter((tool) => tool.length > 0);
|
|
}
|
|
|
|
export function parseAdditionalPermissions(s: string): Map<string, string> {
|
|
const permissions = new Map<string, string>();
|
|
if (!s || !s.trim()) {
|
|
return permissions;
|
|
}
|
|
|
|
const lines = s.trim().split("\n");
|
|
for (const line of lines) {
|
|
const trimmedLine = line.trim();
|
|
if (trimmedLine) {
|
|
const [key, value] = trimmedLine.split(":").map((part) => part.trim());
|
|
if (key && value) {
|
|
permissions.set(key, value);
|
|
}
|
|
}
|
|
}
|
|
return permissions;
|
|
}
|
|
|
|
export function isIssuesEvent(
|
|
context: ParsedGitHubContext,
|
|
): context is ParsedGitHubContext & { payload: IssuesEvent } {
|
|
return context.eventName === "issues";
|
|
}
|
|
|
|
export function isIssueCommentEvent(
|
|
context: ParsedGitHubContext,
|
|
): context is ParsedGitHubContext & { payload: IssueCommentEvent } {
|
|
return context.eventName === "issue_comment";
|
|
}
|
|
|
|
export function isPullRequestEvent(
|
|
context: ParsedGitHubContext,
|
|
): context is ParsedGitHubContext & { payload: PullRequestEvent } {
|
|
return context.eventName === "pull_request";
|
|
}
|
|
|
|
export function isPullRequestReviewEvent(
|
|
context: ParsedGitHubContext,
|
|
): context is ParsedGitHubContext & { payload: PullRequestReviewEvent } {
|
|
return context.eventName === "pull_request_review";
|
|
}
|
|
|
|
export function isPullRequestReviewCommentEvent(
|
|
context: ParsedGitHubContext,
|
|
): context is ParsedGitHubContext & { payload: PullRequestReviewCommentEvent } {
|
|
return context.eventName === "pull_request_review_comment";
|
|
}
|
|
|
|
export function isIssuesAssignedEvent(
|
|
context: ParsedGitHubContext,
|
|
): context is ParsedGitHubContext & { payload: IssuesAssignedEvent } {
|
|
return isIssuesEvent(context) && context.eventAction === "assigned";
|
|
}
|