mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 06:54:13 +08:00
Merge branch 'main' into v1-dev
Resolved conflict by keeping deletion of src/modes/review/index.ts as review mode is removed in v1.0
This commit is contained in:
2
.github/workflows/claude.yml
vendored
2
.github/workflows/claude.yml
vendored
@@ -36,4 +36,4 @@ jobs:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
allowed_tools: "Bash(bun install),Bash(bun test:*),Bash(bun run format),Bash(bun typecheck)"
|
||||
custom_instructions: "You have also been granted tools for editing files and running bun commands (install, run, test, typecheck) for testing your changes: bun install, bun test, bun run format, bun typecheck."
|
||||
model: "claude-opus-4-20250514"
|
||||
model: "claude-opus-4-1-20250805"
|
||||
|
||||
@@ -160,7 +160,7 @@ runs:
|
||||
echo "Base-action dependencies installed"
|
||||
cd -
|
||||
# Install Claude Code globally
|
||||
bun install -g @anthropic-ai/claude-code@1.0.69
|
||||
bun install -g @anthropic-ai/claude-code@1.0.70
|
||||
|
||||
- name: Setup Network Restrictions
|
||||
if: steps.prepare.outputs.contains_trigger == 'true' && inputs.experimental_allowed_domains != ''
|
||||
|
||||
@@ -69,7 +69,7 @@ Add the following to your workflow file:
|
||||
uses: anthropics/claude-code-base-action@beta
|
||||
with:
|
||||
prompt: "Review and fix TypeScript errors"
|
||||
model: "claude-opus-4-20250514"
|
||||
model: "claude-opus-4-1-20250805"
|
||||
fallback_model: "claude-sonnet-4-20250514"
|
||||
allowed_tools: "Bash(git:*),View,GlobTool,GrepTool,BatchTool"
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
@@ -217,7 +217,7 @@ Provide the settings configuration directly as a JSON string:
|
||||
prompt: "Your prompt here"
|
||||
settings: |
|
||||
{
|
||||
"model": "claude-opus-4-20250514",
|
||||
"model": "claude-opus-4-1-20250805",
|
||||
"env": {
|
||||
"DEBUG": "true",
|
||||
"API_URL": "https://api.example.com"
|
||||
|
||||
@@ -118,7 +118,7 @@ runs:
|
||||
|
||||
- name: Install Claude Code
|
||||
shell: bash
|
||||
run: bun install -g @anthropic-ai/claude-code@1.0.69
|
||||
run: bun install -g @anthropic-ai/claude-code@1.0.70
|
||||
|
||||
- name: Run Claude Code Action
|
||||
shell: bash
|
||||
|
||||
@@ -134,7 +134,7 @@ describe("setupClaudeCodeSettings", () => {
|
||||
// Then, add new settings
|
||||
const newSettings = JSON.stringify({
|
||||
newKey: "newValue",
|
||||
model: "claude-opus-4-20250514",
|
||||
model: "claude-opus-4-1-20250805",
|
||||
});
|
||||
|
||||
await setupClaudeCodeSettings(newSettings, testHomeDir);
|
||||
@@ -145,7 +145,7 @@ describe("setupClaudeCodeSettings", () => {
|
||||
expect(settings.enableAllProjectMcpServers).toBe(true);
|
||||
expect(settings.existingKey).toBe("existingValue");
|
||||
expect(settings.newKey).toBe("newValue");
|
||||
expect(settings.model).toBe("claude-opus-4-20250514");
|
||||
expect(settings.model).toBe("claude-opus-4-1-20250805");
|
||||
});
|
||||
|
||||
test("should copy slash commands to .claude directory when path provided", async () => {
|
||||
|
||||
@@ -252,7 +252,7 @@ You can provide Claude Code settings to customize behavior such as model selecti
|
||||
with:
|
||||
settings: |
|
||||
{
|
||||
"model": "claude-opus-4-20250514",
|
||||
"model": "claude-opus-4-1-20250805",
|
||||
"env": {
|
||||
"DEBUG": "true",
|
||||
"API_URL": "https://api.example.com"
|
||||
|
||||
178
src/mcp/github-inline-comment-server.ts
Normal file
178
src/mcp/github-inline-comment-server.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env node
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { z } from "zod";
|
||||
import { createOctokit } from "../github/api/client";
|
||||
|
||||
// Get repository and PR information from environment variables
|
||||
const REPO_OWNER = process.env.REPO_OWNER;
|
||||
const REPO_NAME = process.env.REPO_NAME;
|
||||
const PR_NUMBER = process.env.PR_NUMBER;
|
||||
|
||||
if (!REPO_OWNER || !REPO_NAME || !PR_NUMBER) {
|
||||
console.error(
|
||||
"Error: REPO_OWNER, REPO_NAME, and PR_NUMBER environment variables are required",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// GitHub Inline Comment MCP Server - Provides inline PR comment functionality
|
||||
// Provides an inline comment tool without exposing full PR review capabilities, so that
|
||||
// Claude can't accidentally approve a PR
|
||||
const server = new McpServer({
|
||||
name: "GitHub Inline Comment Server",
|
||||
version: "0.0.1",
|
||||
});
|
||||
|
||||
server.tool(
|
||||
"create_inline_comment",
|
||||
"Create an inline comment on a specific line or lines in a PR file",
|
||||
{
|
||||
path: z
|
||||
.string()
|
||||
.describe("The file path to comment on (e.g., 'src/index.js')"),
|
||||
body: z
|
||||
.string()
|
||||
.describe(
|
||||
"The comment text (supports markdown and GitHub code suggestion blocks). " +
|
||||
"For code suggestions, use: ```suggestion\\nreplacement code\\n```. " +
|
||||
"IMPORTANT: The suggestion block will REPLACE the ENTIRE line range (single line or startLine to line). " +
|
||||
"Ensure the replacement is syntactically complete and valid - it must work as a drop-in replacement for the selected lines.",
|
||||
),
|
||||
line: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe(
|
||||
"Line number for single-line comments (required if startLine is not provided)",
|
||||
),
|
||||
startLine: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe(
|
||||
"Start line for multi-line comments (use with line parameter for the end line)",
|
||||
),
|
||||
side: z
|
||||
.enum(["LEFT", "RIGHT"])
|
||||
.optional()
|
||||
.default("RIGHT")
|
||||
.describe(
|
||||
"Side of the diff to comment on: LEFT (old code) or RIGHT (new code)",
|
||||
),
|
||||
commit_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Specific commit SHA to comment on (defaults to latest commit)",
|
||||
),
|
||||
},
|
||||
async ({ path, body, line, startLine, side, commit_id }) => {
|
||||
try {
|
||||
const githubToken = process.env.GITHUB_TOKEN;
|
||||
|
||||
if (!githubToken) {
|
||||
throw new Error("GITHUB_TOKEN environment variable is required");
|
||||
}
|
||||
|
||||
const owner = REPO_OWNER;
|
||||
const repo = REPO_NAME;
|
||||
const pull_number = parseInt(PR_NUMBER, 10);
|
||||
|
||||
const octokit = createOctokit(githubToken).rest;
|
||||
|
||||
// Validate that either line or both startLine and line are provided
|
||||
if (!line && !startLine) {
|
||||
throw new Error(
|
||||
"Either 'line' for single-line comments or both 'startLine' and 'line' for multi-line comments must be provided",
|
||||
);
|
||||
}
|
||||
|
||||
// If only line is provided, it's a single-line comment
|
||||
// If both startLine and line are provided, it's a multi-line comment
|
||||
const isSingleLine = !startLine;
|
||||
|
||||
const pr = await octokit.pulls.get({
|
||||
owner,
|
||||
repo,
|
||||
pull_number,
|
||||
});
|
||||
|
||||
const params: Parameters<
|
||||
typeof octokit.rest.pulls.createReviewComment
|
||||
>[0] = {
|
||||
owner,
|
||||
repo,
|
||||
pull_number,
|
||||
body,
|
||||
path,
|
||||
side: side || "RIGHT",
|
||||
commit_id: commit_id || pr.data.head.sha,
|
||||
};
|
||||
|
||||
if (isSingleLine) {
|
||||
// Single-line comment
|
||||
params.line = line;
|
||||
} else {
|
||||
// Multi-line comment
|
||||
params.start_line = startLine;
|
||||
params.start_side = side || "RIGHT";
|
||||
params.line = line;
|
||||
}
|
||||
|
||||
const result = await octokit.rest.pulls.createReviewComment(params);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(
|
||||
{
|
||||
success: true,
|
||||
comment_id: result.data.id,
|
||||
html_url: result.data.html_url,
|
||||
path: result.data.path,
|
||||
line: result.data.line || result.data.original_line,
|
||||
message: `Inline comment created successfully on ${path}${isSingleLine ? ` at line ${line}` : ` from line ${startLine} to ${line}`}`,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
|
||||
// Provide more helpful error messages for common issues
|
||||
let helpMessage = "";
|
||||
if (errorMessage.includes("Validation Failed")) {
|
||||
helpMessage =
|
||||
"\n\nThis usually means the line number doesn't exist in the diff or the file path is incorrect. Make sure you're commenting on lines that are part of the PR's changes.";
|
||||
} else if (errorMessage.includes("Not Found")) {
|
||||
helpMessage =
|
||||
"\n\nThis usually means the PR number, repository, or file path is incorrect.";
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error creating inline comment: ${errorMessage}${helpMessage}`,
|
||||
},
|
||||
],
|
||||
error: errorMessage,
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
async function runServer() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
process.on("exit", () => {
|
||||
server.close();
|
||||
});
|
||||
}
|
||||
|
||||
runServer().catch(console.error);
|
||||
@@ -111,6 +111,24 @@ export async function prepareMcpConfig(
|
||||
};
|
||||
}
|
||||
|
||||
// Include inline comment server for experimental review mode
|
||||
if (context.inputs.mode === "experimental-review" && context.isPR) {
|
||||
baseMcpConfig.mcpServers.github_inline_comment = {
|
||||
command: "bun",
|
||||
args: [
|
||||
"run",
|
||||
`${process.env.GITHUB_ACTION_PATH}/src/mcp/github-inline-comment-server.ts`,
|
||||
],
|
||||
env: {
|
||||
GITHUB_TOKEN: githubToken,
|
||||
REPO_OWNER: owner,
|
||||
REPO_NAME: repo,
|
||||
PR_NUMBER: context.entityNumber?.toString() || "",
|
||||
GITHUB_API_URL: GITHUB_API_URL,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Only add CI server if we have actions:read permission and we're in a PR context
|
||||
const hasActionsReadPermission =
|
||||
context.inputs.additionalPermissions.get("actions") === "read";
|
||||
|
||||
Reference in New Issue
Block a user