feat: enable GitHub inline comment server for code-review plugin

Add support for automatically including the GitHub inline comment server when
the code-review@claude-code-plugins plugin is specified in the plugins input.
This enables the code-review plugin to post inline comments on PRs even in
agent mode.

Changes:
- Parse plugins input as string[] in parseGitHubContext
- Update inline comment server logic to check for code-review plugin
- Add comprehensive test coverage for inline comment server detection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ashwin Bhat
2025-10-25 21:40:13 -07:00
parent d4c09790f5
commit 3ffb87fe89
7 changed files with 124 additions and 1 deletions

View File

@@ -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'

View File

@@ -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),
},
};

View File

@@ -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",

View File

@@ -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();
});
});

View File

@@ -25,6 +25,7 @@ const defaultInputs = {
allowedBots: "",
allowedNonWriteUsers: "",
trackProgress: false,
plugins: [],
};
const defaultRepository = {

View File

@@ -25,6 +25,7 @@ describe("detectMode with enhanced routing", () => {
allowedBots: "",
allowedNonWriteUsers: "",
trackProgress: false,
plugins: [],
},
};

View File

@@ -73,6 +73,7 @@ describe("checkWritePermissions", () => {
allowedBots: "",
allowedNonWriteUsers: "",
trackProgress: false,
plugins: [],
},
});