feat(prd-1): implement M6 - MCP server platform routing
- Add platform detection to prepareMcpConfig() via detectPlatform() - Skip GitHub public MCP server (ghcr.io/github/github-mcp-server) on Forgejo - Skip checkActionsReadPermission on Forgejo (workflow token has full access) - Reuse existing github-actions-server.ts for both platforms (no duplication) - Add 6 Forgejo-specific tests to install-mcp-server.test.ts - Updated PRD checkboxes for M6 Progress: 67% complete (6/9 milestones) - M7 now unblocked Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
0802ac18eb
commit
ce1459fe7f
3 files changed
+208
-17
No files matched your search
@@ -313,4 +313,178 @@ describe("prepareMcpConfig", () => {
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers.github_ci).not.toBeDefined();
|
||||
});
|
||||
|
||||
describe("Forgejo platform routing", () => {
|
||||
let savedPlatform: string | undefined;
|
||||
let savedForgejo: string | undefined;
|
||||
let savedServerUrl: string | undefined;
|
||||
|
||||
beforeEach(() => {
|
||||
savedPlatform = process.env.PLATFORM;
|
||||
savedForgejo = process.env.FORGEJO;
|
||||
savedServerUrl = process.env.GITHUB_SERVER_URL;
|
||||
// Set platform to forgejo for all tests in this block
|
||||
process.env.PLATFORM = "forgejo";
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (savedPlatform !== undefined) {
|
||||
process.env.PLATFORM = savedPlatform;
|
||||
} else {
|
||||
delete process.env.PLATFORM;
|
||||
}
|
||||
if (savedForgejo !== undefined) {
|
||||
process.env.FORGEJO = savedForgejo;
|
||||
} else {
|
||||
delete process.env.FORGEJO;
|
||||
}
|
||||
if (savedServerUrl !== undefined) {
|
||||
process.env.GITHUB_SERVER_URL = savedServerUrl;
|
||||
} else {
|
||||
delete process.env.GITHUB_SERVER_URL;
|
||||
}
|
||||
});
|
||||
|
||||
test("should skip GitHub public MCP server on Forgejo", async () => {
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
baseBranch: "main",
|
||||
allowedTools: [
|
||||
"mcp__github__create_issue",
|
||||
"mcp__github__create_pr",
|
||||
],
|
||||
mode: "tag",
|
||||
context: mockContext,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
// The Docker-based GitHub MCP server should NOT be included on Forgejo
|
||||
expect(parsed.mcpServers.github).not.toBeDefined();
|
||||
});
|
||||
|
||||
test("should include CI server on Forgejo without permission check", async () => {
|
||||
process.env.DEFAULT_WORKFLOW_TOKEN = "forgejo-workflow-token";
|
||||
// Simulate a 403 from the permission check — on Forgejo this should be
|
||||
// skipped entirely, so the CI server is still included.
|
||||
fetchSpy.mockResolvedValue(
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
message: "Resource not accessible by integration",
|
||||
}),
|
||||
{ status: 403 },
|
||||
),
|
||||
);
|
||||
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
baseBranch: "main",
|
||||
allowedTools: [],
|
||||
mode: "tag",
|
||||
context: mockPRContext,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
// CI server should be included on Forgejo even though the permission
|
||||
// check would fail — the check is skipped entirely.
|
||||
expect(parsed.mcpServers.github_ci).toBeDefined();
|
||||
expect(parsed.mcpServers.github_ci.env.GITHUB_TOKEN).toBe(
|
||||
"forgejo-workflow-token",
|
||||
);
|
||||
|
||||
delete process.env.DEFAULT_WORKFLOW_TOKEN;
|
||||
});
|
||||
|
||||
test("should not call checkActionsReadPermission on Forgejo", async () => {
|
||||
process.env.DEFAULT_WORKFLOW_TOKEN = "forgejo-workflow-token";
|
||||
fetchSpy.mockClear();
|
||||
|
||||
await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
baseBranch: "main",
|
||||
allowedTools: [],
|
||||
mode: "tag",
|
||||
context: mockPRContext,
|
||||
});
|
||||
|
||||
// fetch should not have been called — the permission check is skipped
|
||||
expect(fetchSpy).not.toHaveBeenCalled();
|
||||
|
||||
delete process.env.DEFAULT_WORKFLOW_TOKEN;
|
||||
});
|
||||
|
||||
test("should keep server names as github_* on Forgejo", async () => {
|
||||
process.env.DEFAULT_WORKFLOW_TOKEN = "forgejo-workflow-token";
|
||||
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
baseBranch: "main",
|
||||
allowedTools: [],
|
||||
mode: "tag",
|
||||
context: {
|
||||
...mockPRContext,
|
||||
inputs: { ...mockPRContext.inputs, useCommitSigning: true },
|
||||
},
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
// Server names must stay as github_* to match hardcoded tool names
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
expect(parsed.mcpServers.github_file_ops).toBeDefined();
|
||||
expect(parsed.mcpServers.github_ci).toBeDefined();
|
||||
|
||||
delete process.env.DEFAULT_WORKFLOW_TOKEN;
|
||||
});
|
||||
|
||||
test("should include comment server on Forgejo in tag mode", async () => {
|
||||
const result = await prepareMcpConfig({
|
||||
githubToken: "test-token",
|
||||
owner: "test-owner",
|
||||
repo: "test-repo",
|
||||
branch: "test-branch",
|
||||
baseBranch: "main",
|
||||
allowedTools: [],
|
||||
mode: "tag",
|
||||
context: mockContext,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers.github_comment).toBeDefined();
|
||||
expect(parsed.mcpServers.github_comment.env.GITHUB_TOKEN).toBe(
|
||||
"test-token",
|
||||
);
|
||||
});
|
||||
|
||||
test("should include inline comment server on Forgejo for PRs", 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: "tag",
|
||||
context: mockPRContext,
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(result);
|
||||
expect(parsed.mcpServers.github_inline_comment).toBeDefined();
|
||||
expect(
|
||||
parsed.mcpServers.github_inline_comment.env.GITHUB_TOKEN,
|
||||
).toBe("test-token");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user