Attempt to make this work

This commit is contained in:
Mark Wylde
2025-05-31 01:10:59 +01:00
parent e2f737a753
commit 45ee2dca55
7 changed files with 21 additions and 39 deletions

View File

@@ -1,8 +1,8 @@
![Claude Code Action responding to a comment](https://github.com/user-attachments/assets/1d60c2e9-82ed-4ee5-b749-f9e021c85f4d) # Claude Code Action (Gitea Fork)
# Claude Code Action A fork of the [Claude Code Action](https://github.com/anthropics/claude-code-action) that adds support for Gitea alongside GitHub. This action provides a general-purpose [Claude Code](https://claude.ai/code) assistant for PRs and issues that can answer questions and implement code changes. It listens for a trigger phrase in comments and activates Claude to act on the request. Supports multiple authentication methods including Anthropic direct API, Amazon Bedrock, and Google Vertex AI.
A general-purpose [Claude Code](https://claude.ai/code) action for GitHub PRs and issues that can answer questions and implement code changes. This action listens for a trigger phrase in comments and activates Claude act on the request. It supports multiple authentication methods including Anthropic direct API, Amazon Bedrock, and Google Vertex AI. > **Note**: This is an unofficial fork that extends the original action to work with Gitea installations. The core functionality remains the same, with additional support for Gitea APIs and local git operations.
## Features ## Features

View File

@@ -584,16 +584,7 @@ Important Notes:
- Never create new comments. Only update the existing comment using ${eventData.eventName === "pull_request_review_comment" ? "mcp__github__update_pull_request_comment" : "mcp__github__update_issue_comment"} with comment_id: ${context.claudeCommentId}. - Never create new comments. Only update the existing comment using ${eventData.eventName === "pull_request_review_comment" ? "mcp__github__update_pull_request_comment" : "mcp__github__update_issue_comment"} with comment_id: ${context.claudeCommentId}.
- This includes ALL responses: code reviews, answers to questions, progress updates, and final results.${eventData.isPR ? "\n- PR CRITICAL: After reading files and forming your response, you MUST post it by calling mcp__github__update_issue_comment. Do NOT just respond with a normal response, the user will not see it." : ""} - This includes ALL responses: code reviews, answers to questions, progress updates, and final results.${eventData.isPR ? "\n- PR CRITICAL: After reading files and forming your response, you MUST post it by calling mcp__github__update_issue_comment. Do NOT just respond with a normal response, the user will not see it." : ""}
- You communicate exclusively by editing your single comment - not through any other means. - You communicate exclusively by editing your single comment - not through any other means.
- Use this spinner HTML when work is in progress: ${(() => { - Use this spinner HTML when work is in progress: <img src="https://raw.githubusercontent.com/markwylde/claude-code-gitea-action/refs/heads/gitea/assets/spinner.gif" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />
try {
const spinnerPath = require("path").join(__dirname, "../assets/spinner.gif");
const spinnerBuffer = require("fs").readFileSync(spinnerPath);
const base64Data = spinnerBuffer.toString("base64");
return `<img src="data:image/gif;base64,${base64Data}" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />`;
} catch (error) {
return '<span style="margin-left: 4px;">⏳</span>';
}
})()}
${eventData.isPR && !eventData.claudeBranch ? `- Always push to the existing branch when triggered on a PR.` : `- IMPORTANT: You are already on the correct branch (${eventData.claudeBranch || "the created branch"}). Never create new branches when triggered on issues or closed/merged PRs.`} ${eventData.isPR && !eventData.claudeBranch ? `- Always push to the existing branch when triggered on a PR.` : `- IMPORTANT: You are already on the correct branch (${eventData.claudeBranch || "the created branch"}). Never create new branches when triggered on issues or closed/merged PRs.`}
- Use mcp__local_git_ops__commit_files for making commits (works for both new and existing files, single or multiple). Use mcp__local_git_ops__delete_files for deleting files (supports deleting single or multiple files atomically), or mcp__github__delete_file for deleting a single file. Edit files locally, and the tool will read the content from the same path on disk. - Use mcp__local_git_ops__commit_files for making commits (works for both new and existing files, single or multiple). Use mcp__local_git_ops__delete_files for deleting files (supports deleting single or multiple files atomically), or mcp__github__delete_file for deleting a single file. Edit files locally, and the tool will read the content from the same path on disk.
Tool usage examples: Tool usage examples:

View File

@@ -46,7 +46,7 @@ export async function checkAndDeleteEmptyBranch(
console.log( console.log(
`Branch ${claudeBranch} appears to have commits (different SHA from base)`, `Branch ${claudeBranch} appears to have commits (different SHA from base)`,
); );
const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/src/branch/${claudeBranch}`;
branchLink = `\n[View branch](${branchUrl})`; branchLink = `\n[View branch](${branchUrl})`;
} else { } else {
console.log( console.log(
@@ -63,7 +63,7 @@ export async function checkAndDeleteEmptyBranch(
console.log( console.log(
`Branch ${claudeBranch} exists but SHA comparison failed, assuming it has commits`, `Branch ${claudeBranch} exists but SHA comparison failed, assuming it has commits`,
); );
const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/src/branch/${claudeBranch}`;
branchLink = `\n[View branch](${branchUrl})`; branchLink = `\n[View branch](${branchUrl})`;
} else { } else {
console.log( console.log(
@@ -76,7 +76,7 @@ export async function checkAndDeleteEmptyBranch(
console.error("Error checking branch with git commands:", error); console.error("Error checking branch with git commands:", error);
// For errors, assume the branch has commits to be safe // For errors, assume the branch has commits to be safe
console.log("Assuming branch exists due to git command error"); console.log("Assuming branch exists due to git command error");
const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/src/branch/${claudeBranch}`;
branchLink = `\n[View branch](${branchUrl})`; branchLink = `\n[View branch](${branchUrl})`;
} }
} else { } else {
@@ -106,7 +106,7 @@ export async function checkAndDeleteEmptyBranch(
console.log( console.log(
`Branch ${claudeBranch} appears to have commits (different SHA from base)`, `Branch ${claudeBranch} appears to have commits (different SHA from base)`,
); );
const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/src/branch/${claudeBranch}`;
branchLink = `\n[View branch](${branchUrl})`; branchLink = `\n[View branch](${branchUrl})`;
} else { } else {
console.log( console.log(
@@ -127,7 +127,7 @@ export async function checkAndDeleteEmptyBranch(
} else { } else {
// For other errors, assume the branch has commits to be safe // For other errors, assume the branch has commits to be safe
console.log("Assuming branch exists due to non-404 error"); console.log("Assuming branch exists due to non-404 error");
const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; const branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/src/branch/${claudeBranch}`;
branchLink = `\n[View branch](${branchUrl})`; branchLink = `\n[View branch](${branchUrl})`;
} }
} }

View File

@@ -160,7 +160,7 @@ export function updateCommentBody(input: CommentUpdateInput): string {
// Extract owner/repo from jobUrl // Extract owner/repo from jobUrl
const repoMatch = jobUrl.match(/github\.com\/([^\/]+)\/([^\/]+)\//); const repoMatch = jobUrl.match(/github\.com\/([^\/]+)\/([^\/]+)\//);
if (repoMatch) { if (repoMatch) {
branchUrl = `${GITEA_SERVER_URL}/${repoMatch[1]}/${repoMatch[2]}/tree/${finalBranchName}`; branchUrl = `${GITEA_SERVER_URL}/${repoMatch[1]}/${repoMatch[2]}/src/branch/${finalBranchName}`;
} }
} }

View File

@@ -3,16 +3,7 @@ import { readFileSync } from "fs";
import { join } from "path"; import { join } from "path";
function getSpinnerHtml(): string { function getSpinnerHtml(): string {
try { return `<img src="https://raw.githubusercontent.com/markwylde/claude-code-gitea-action/refs/heads/gitea/assets/spinner.gif" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />`;
const spinnerPath = join(__dirname, "../../../assets/spinner.gif");
const spinnerBuffer = readFileSync(spinnerPath);
const base64Data = spinnerBuffer.toString("base64");
return `<img src="data:image/gif;base64,${base64Data}" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />`;
} catch (error) {
console.warn("Could not load spinner image, using fallback");
// Fallback to a simple text spinner
return '<span style="margin-left: 4px;">⏳</span>';
}
} }
export const SPINNER_HTML = getSpinnerHtml(); export const SPINNER_HTML = getSpinnerHtml();

View File

@@ -88,7 +88,7 @@ describe("checkAndDeleteEmptyBranch", () => {
expect(result.shouldDeleteBranch).toBe(false); expect(result.shouldDeleteBranch).toBe(false);
expect(result.branchLink).toBe( expect(result.branchLink).toBe(
`\n[View branch](${GITEA_SERVER_URL}/owner/repo/tree/claude/issue-123-20240101_123456)`, `\n[View branch](${GITEA_SERVER_URL}/owner/repo/src/branch/claude/issue-123-20240101_123456)`,
); );
expect(consoleLogSpy).not.toHaveBeenCalledWith( expect(consoleLogSpy).not.toHaveBeenCalledWith(
expect.stringContaining("has no commits"), expect.stringContaining("has no commits"),
@@ -119,7 +119,7 @@ describe("checkAndDeleteEmptyBranch", () => {
expect(result.shouldDeleteBranch).toBe(false); expect(result.shouldDeleteBranch).toBe(false);
expect(result.branchLink).toBe( expect(result.branchLink).toBe(
`\n[View branch](${GITEA_SERVER_URL}/owner/repo/tree/claude/issue-123-20240101_123456)`, `\n[View branch](${GITEA_SERVER_URL}/owner/repo/src/branch/claude/issue-123-20240101_123456)`,
); );
expect(consoleErrorSpy).toHaveBeenCalledWith( expect(consoleErrorSpy).toHaveBeenCalledWith(
"Error checking for commits on Claude branch:", "Error checking for commits on Claude branch:",

View File

@@ -105,7 +105,7 @@ describe("updateCommentBody", () => {
const result = updateCommentBody(input); const result = updateCommentBody(input);
expect(result).toContain( expect(result).toContain(
"• [`claude/issue-123-20240101_120000`](https://github.com/owner/repo/tree/claude/issue-123-20240101_120000)", "• [`claude/issue-123-20240101_120000`](https://github.com/owner/repo/src/branch/claude/issue-123-20240101_120000)",
); );
}); });
@@ -113,12 +113,12 @@ describe("updateCommentBody", () => {
const input = { const input = {
...baseInput, ...baseInput,
branchLink: branchLink:
"\n[View branch](https://github.com/owner/repo/tree/branch-name)", "\n[View branch](https://github.com/owner/repo/src/branch/branch-name)",
}; };
const result = updateCommentBody(input); const result = updateCommentBody(input);
expect(result).toContain( expect(result).toContain(
"• [`branch-name`](https://github.com/owner/repo/tree/branch-name)", "• [`branch-name`](https://github.com/owner/repo/src/branch/branch-name)",
); );
}); });
@@ -126,13 +126,13 @@ describe("updateCommentBody", () => {
const input = { const input = {
...baseInput, ...baseInput,
currentBody: currentBody:
"Some comment with [View branch](https://github.com/owner/repo/tree/branch-name)", "Some comment with [View branch](https://github.com/owner/repo/src/branch/branch-name)",
branchName: "new-branch-name", branchName: "new-branch-name",
}; };
const result = updateCommentBody(input); const result = updateCommentBody(input);
expect(result).toContain( expect(result).toContain(
"• [`new-branch-name`](https://github.com/owner/repo/tree/new-branch-name)", "• [`new-branch-name`](https://github.com/owner/repo/src/branch/new-branch-name)",
); );
expect(result).not.toContain("View branch"); expect(result).not.toContain("View branch");
}); });
@@ -333,7 +333,7 @@ describe("updateCommentBody", () => {
); );
expect(result).toContain("—— [View job]"); expect(result).toContain("—— [View job]");
expect(result).toContain( expect(result).toContain(
"• [`claude-branch-123`](https://github.com/owner/repo/tree/claude-branch-123)", "• [`claude-branch-123`](https://github.com/owner/repo/src/branch/claude-branch-123)",
); );
expect(result).toContain("• [Create PR ➔]"); expect(result).toContain("• [Create PR ➔]");
@@ -402,7 +402,7 @@ describe("updateCommentBody", () => {
currentBody: "Claude Code is working…", currentBody: "Claude Code is working…",
branchName: "claude/issue-123-20240101_120000", branchName: "claude/issue-123-20240101_120000",
branchLink: branchLink:
"\n[View branch](https://github.com/owner/repo/tree/claude/issue-123-20240101_120000)", "\n[View branch](https://github.com/owner/repo/src/branch/claude/issue-123-20240101_120000)",
prLink: prLink:
"\n[Create a PR](https://github.com/owner/repo/compare/main...claude/issue-123-20240101_120000)", "\n[Create a PR](https://github.com/owner/repo/compare/main...claude/issue-123-20240101_120000)",
}; };
@@ -411,7 +411,7 @@ describe("updateCommentBody", () => {
// Should include both links in formatted style // Should include both links in formatted style
expect(result).toContain( expect(result).toContain(
"• [`claude/issue-123-20240101_120000`](https://github.com/owner/repo/tree/claude/issue-123-20240101_120000)", "• [`claude/issue-123-20240101_120000`](https://github.com/owner/repo/src/branch/claude/issue-123-20240101_120000)",
); );
expect(result).toContain( expect(result).toContain(
"• [Create PR ➔](https://github.com/owner/repo/compare/main...claude/issue-123-20240101_120000)", "• [Create PR ➔](https://github.com/owner/repo/compare/main...claude/issue-123-20240101_120000)",