diff --git a/action.yml b/action.yml index cb527ba..458f25d 100644 --- a/action.yml +++ b/action.yml @@ -167,6 +167,7 @@ runs: ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }} CLAUDE_ARGS: ${{ inputs.claude_args }} ALL_INPUTS: ${{ toJson(inputs) }} + PLUGINS: ${{ inputs.plugins }} - name: Install Base Action Dependencies if: steps.prepare.outputs.contains_trigger == 'true' diff --git a/src/github/context.ts b/src/github/context.ts index 92f272c..9789e86 100644 --- a/src/github/context.ts +++ b/src/github/context.ts @@ -95,6 +95,7 @@ type BaseContext = { allowedBots: string; allowedNonWriteUsers: string; trackProgress: boolean; + plugins: string[]; }; }; @@ -150,6 +151,10 @@ export function parseGitHubContext(): GitHubContext { allowedBots: process.env.ALLOWED_BOTS ?? "", allowedNonWriteUsers: process.env.ALLOWED_NON_WRITE_USERS ?? "", trackProgress: process.env.TRACK_PROGRESS === "true", + plugins: (process.env.PLUGINS || "") + .split(",") + .map((p) => p.trim()) + .filter((p) => p.length > 0), }, }; diff --git a/src/mcp/install-mcp-server.ts b/src/mcp/install-mcp-server.ts index 22de611..1b1673f 100644 --- a/src/mcp/install-mcp-server.ts +++ b/src/mcp/install-mcp-server.ts @@ -134,11 +134,17 @@ export async function prepareMcpConfig( }; } + // Check if code-review plugin is in the plugins list + const hasCodeReviewPlugin = context.inputs.plugins.includes( + "code-review@claude-code-plugins", + ); + // Include inline comment server for PRs when requested via allowed tools + // or when code-review plugin is specified (needs inline comment access for reviews) if ( isEntityContext(context) && context.isPR && - (hasGitHubMcpTools || hasInlineCommentTools) + (hasGitHubMcpTools || hasInlineCommentTools || hasCodeReviewPlugin) ) { baseMcpConfig.mcpServers.github_inline_comment = { command: "bun", diff --git a/test/install-mcp-server.test.ts b/test/install-mcp-server.test.ts index 9d62850..8954054 100644 --- a/test/install-mcp-server.test.ts +++ b/test/install-mcp-server.test.ts @@ -37,6 +37,7 @@ describe("prepareMcpConfig", () => { allowedBots: "", allowedNonWriteUsers: "", trackProgress: false, + plugins: [], }, }; @@ -276,4 +277,111 @@ describe("prepareMcpConfig", () => { const parsed = JSON.parse(result); expect(parsed.mcpServers.github_ci).not.toBeDefined(); }); + + test("should include inline comment server in agent mode when code-review plugin is specified", async () => { + const contextWithCodeReviewPlugin: ParsedGitHubContext = { + ...mockPRContext, + inputs: { + ...mockPRContext.inputs, + plugins: ["code-review@claude-code-plugins"], + }, + }; + + const result = await prepareMcpConfig({ + githubToken: "test-token", + owner: "test-owner", + repo: "test-repo", + branch: "test-branch", + baseBranch: "main", + allowedTools: [], + mode: "agent", + context: contextWithCodeReviewPlugin, + }); + + const parsed = JSON.parse(result); + expect(parsed.mcpServers.github_inline_comment).toBeDefined(); + expect(parsed.mcpServers.github_inline_comment.env.GITHUB_TOKEN).toBe( + "test-token", + ); + }); + + test("should not include inline comment server in agent mode when code-review plugin is not specified", async () => { + const result = await prepareMcpConfig({ + githubToken: "test-token", + owner: "test-owner", + repo: "test-repo", + branch: "test-branch", + baseBranch: "main", + allowedTools: [], + mode: "agent", + context: mockPRContext, + }); + + const parsed = JSON.parse(result); + expect(parsed.mcpServers.github_inline_comment).not.toBeDefined(); + }); + + test("should include inline comment server in agent mode when code-review plugin is in a list of plugins", async () => { + const contextWithMultiplePlugins: ParsedGitHubContext = { + ...mockPRContext, + inputs: { + ...mockPRContext.inputs, + plugins: ["plugin1", "code-review@claude-code-plugins", "plugin2"], + }, + }; + + const result = await prepareMcpConfig({ + githubToken: "test-token", + owner: "test-owner", + repo: "test-repo", + branch: "test-branch", + baseBranch: "main", + allowedTools: [], + mode: "agent", + context: contextWithMultiplePlugins, + }); + + const parsed = JSON.parse(result); + expect(parsed.mcpServers.github_inline_comment).toBeDefined(); + }); + + test("should not include inline comment server in agent mode when plugins contain similar but not exact match", async () => { + const contextWithSimilarPlugin: ParsedGitHubContext = { + ...mockPRContext, + inputs: { + ...mockPRContext.inputs, + plugins: ["code-review-other", "review@claude-code-plugins"], + }, + }; + + const result = await prepareMcpConfig({ + githubToken: "test-token", + owner: "test-owner", + repo: "test-repo", + branch: "test-branch", + baseBranch: "main", + allowedTools: [], + mode: "agent", + context: contextWithSimilarPlugin, + }); + + const parsed = JSON.parse(result); + expect(parsed.mcpServers.github_inline_comment).not.toBeDefined(); + }); + + test("should include inline comment server in agent mode when explicit inline comment tools are provided (backward compatibility)", async () => { + const result = await prepareMcpConfig({ + githubToken: "test-token", + owner: "test-owner", + repo: "test-repo", + branch: "test-branch", + baseBranch: "main", + allowedTools: ["mcp__github_inline_comment__create_inline_comment"], + mode: "agent", + context: mockPRContext, + }); + + const parsed = JSON.parse(result); + expect(parsed.mcpServers.github_inline_comment).toBeDefined(); + }); }); diff --git a/test/mockContext.ts b/test/mockContext.ts index 73255e6..9c73827 100644 --- a/test/mockContext.ts +++ b/test/mockContext.ts @@ -25,6 +25,7 @@ const defaultInputs = { allowedBots: "", allowedNonWriteUsers: "", trackProgress: false, + plugins: [], }; const defaultRepository = { diff --git a/test/modes/detector.test.ts b/test/modes/detector.test.ts index ed6a3a5..2631aea 100644 --- a/test/modes/detector.test.ts +++ b/test/modes/detector.test.ts @@ -25,6 +25,7 @@ describe("detectMode with enhanced routing", () => { allowedBots: "", allowedNonWriteUsers: "", trackProgress: false, + plugins: [], }, }; diff --git a/test/permissions.test.ts b/test/permissions.test.ts index 9aeb301..cba50a8 100644 --- a/test/permissions.test.ts +++ b/test/permissions.test.ts @@ -73,6 +73,7 @@ describe("checkWritePermissions", () => { allowedBots: "", allowedNonWriteUsers: "", trackProgress: false, + plugins: [], }, });