mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
feat: add use_commit_signing input with default false (#238)
* 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>
This commit is contained in:
@@ -34,6 +34,7 @@ describe("prepareMcpConfig", () => {
|
||||
branchPrefix: "",
|
||||
useStickyComment: false,
|
||||
additionalPermissions: new Map(),
|
||||
useCommitSigning: false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -44,6 +45,22 @@ describe("prepareMcpConfig", () => {
|
||||
entityNumber: 456,
|
||||
};
|
||||
|
||||
const mockContextWithSigning: ParsedGitHubContext = {
|
||||
...mockContext,
|
||||
inputs: {
|
||||
...mockContext.inputs,
|
||||
useCommitSigning: true,
|
||||
},
|
||||
};
|
||||
|
||||
const mockPRContextWithSigning: ParsedGitHubContext = {
|
||||
...mockPRContext,
|
||||
inputs: {
|
||||
...mockPRContext.inputs,
|
||||
useCommitSigning: true,
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
consoleInfoSpy = spyOn(core, "info").mockImplementation(() => {});
|
||||
consoleWarningSpy = spyOn(core, "warning").mockImplementation(() => {});
|
||||
@@ -65,7 +82,7 @@ describe("prepareMcpConfig", () => {
|
||||
processExitSpy.mockRestore();
|
||||
});
|
||||
|
||||
test("should return base config when no additional config is provided and no allowed_tools", async () => {
|
||||
test("should return comment server when commit signing is disabled", async () => {
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
@@ -78,6 +95,37 @@ describe("prepareMcpConfig", () => {
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers).toBeDefined();
|
||||
expect(parsed.mcpServers.github).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment.env.GITHUB_TOKEN).toBe(
|
||||
"test-token",
|
||||
);
|
||||
expect(parsed.mcpServers.github_comment.env.REPO_OWNER).toBe("test-owner");
|
||||
expect(parsed.mcpServers.github_comment.env.REPO_NAME).toBe("test-repo");
|
||||
});
|
||||
|
||||
test("should return file ops server when commit signing is enabled", async () => {
|
||||
const contextWithSigning = {
|
||||
...mockContext,
|
||||
inputs: {
|
||||
...mockContext.inputs,
|
||||
useCommitSigning: true,
|
||||
},
|
||||
};
|
||||
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
allowedTools: [],
|
||||
context: contextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers).toBeDefined();
|
||||
expect(parsed.mcpServers.github).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops.env.GITHUB_TOKEN).toBe(
|
||||
"test-token",
|
||||
@@ -105,13 +153,22 @@ describe("prepareMcpConfig", () => {
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers).toBeDefined();
|
||||
expect(parsed.mcpServers.github).toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github.env.GITHUB_PERSONAL_ACCESS_TOKEN).toBe(
|
||||
"test-token",
|
||||
);
|
||||
});
|
||||
|
||||
test("should not include github MCP server when only file_ops tools are allowed", async () => {
|
||||
const contextWithSigning = {
|
||||
...mockContext,
|
||||
inputs: {
|
||||
...mockContext.inputs,
|
||||
useCommitSigning: true,
|
||||
},
|
||||
};
|
||||
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
@@ -121,7 +178,7 @@ describe("prepareMcpConfig", () => {
|
||||
"mcp__github_file_ops__commit_files",
|
||||
"mcp__github_file_ops__update_claude_comment",
|
||||
],
|
||||
context: mockContext,
|
||||
context: contextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -130,7 +187,7 @@ describe("prepareMcpConfig", () => {
|
||||
expect(parsed.mcpServers.github_file_ops).toBeDefined();
|
||||
});
|
||||
|
||||
test("should include file_ops server even when no GitHub tools are allowed", async () => {
|
||||
test("should include comment server when no GitHub tools are allowed and signing disabled", async () => {
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
@@ -143,7 +200,8 @@ describe("prepareMcpConfig", () => {
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers).toBeDefined();
|
||||
expect(parsed.mcpServers.github).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
});
|
||||
|
||||
test("should return base config when additional config is empty string", async () => {
|
||||
@@ -160,7 +218,7 @@ describe("prepareMcpConfig", () => {
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers).toBeDefined();
|
||||
expect(parsed.mcpServers.github).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
expect(consoleWarningSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -178,7 +236,7 @@ describe("prepareMcpConfig", () => {
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers).toBeDefined();
|
||||
expect(parsed.mcpServers.github).not.toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
expect(consoleWarningSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -205,7 +263,7 @@ describe("prepareMcpConfig", () => {
|
||||
"mcp__github__create_issue",
|
||||
"mcp__github_file_ops__commit_files",
|
||||
],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -243,7 +301,7 @@ describe("prepareMcpConfig", () => {
|
||||
"mcp__github__create_issue",
|
||||
"mcp__github_file_ops__commit_files",
|
||||
],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -281,7 +339,7 @@ describe("prepareMcpConfig", () => {
|
||||
branch: "test-branch",
|
||||
additionalMcpConfig: additionalConfig,
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -301,7 +359,7 @@ describe("prepareMcpConfig", () => {
|
||||
branch: "test-branch",
|
||||
additionalMcpConfig: invalidJson,
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -322,7 +380,7 @@ describe("prepareMcpConfig", () => {
|
||||
branch: "test-branch",
|
||||
additionalMcpConfig: nonObjectJson,
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -346,7 +404,7 @@ describe("prepareMcpConfig", () => {
|
||||
branch: "test-branch",
|
||||
additionalMcpConfig: nullJson,
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -370,7 +428,7 @@ describe("prepareMcpConfig", () => {
|
||||
branch: "test-branch",
|
||||
additionalMcpConfig: arrayJson,
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -417,7 +475,7 @@ describe("prepareMcpConfig", () => {
|
||||
branch: "test-branch",
|
||||
additionalMcpConfig: additionalConfig,
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -439,7 +497,7 @@ describe("prepareMcpConfig", () => {
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -460,7 +518,7 @@ describe("prepareMcpConfig", () => {
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -478,6 +536,7 @@ describe("prepareMcpConfig", () => {
|
||||
inputs: {
|
||||
...mockPRContext.inputs,
|
||||
additionalPermissions: new Map([["actions", "read"]]),
|
||||
useCommitSigning: true,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -506,7 +565,7 @@ describe("prepareMcpConfig", () => {
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
allowedTools: [],
|
||||
context: mockContext,
|
||||
context: mockContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
@@ -524,7 +583,7 @@ describe("prepareMcpConfig", () => {
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
allowedTools: [],
|
||||
context: mockPRContext,
|
||||
context: mockPRContextWithSigning,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
|
||||
Reference in New Issue
Block a user