Skip to content

Commit b744372

Browse files
authored
#17 fix: handle pull_request_review_comment payload differences in Gitea (#19)
1 parent dfdfdd9 commit b744372

6 files changed

Lines changed: 83 additions & 54 deletions

File tree

src/create-prompt/index.ts

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ export function buildDisallowedToolsString(
120120
// If user has explicitly allowed some hardcoded disallowed tools, remove them from disallowed list
121121
const allowedList = normalizeToolList(allowedTools);
122122
if (allowedList.length > 0) {
123-
disallowedTools = disallowedTools.filter((tool) => !allowedList.includes(tool));
123+
disallowedTools = disallowedTools.filter(
124+
(tool) => !allowedList.includes(tool),
125+
);
124126
}
125127

126128
let allDisallowedTools = disallowedTools.join(",");
@@ -164,16 +166,20 @@ export function prepareContext(
164166
let commentBody: string | undefined;
165167

166168
if (isIssueCommentEvent(context)) {
167-
commentId = context.payload.comment.id.toString();
168-
commentBody = context.payload.comment.body;
169-
triggerUsername = context.payload.comment.user.login;
169+
commentId = context.payload.comment?.id?.toString();
170+
commentBody = context.payload.comment?.body;
171+
triggerUsername = context.payload.comment?.user?.login;
170172
} else if (isPullRequestReviewEvent(context)) {
171-
commentBody = context.payload.review.body ?? "";
172-
triggerUsername = context.payload.review.user.login;
173+
commentBody =
174+
context.payload.review?.body ?? context.payload.review?.content ?? "";
175+
triggerUsername =
176+
context.payload.review?.user?.login ?? context.payload.sender?.login;
173177
} else if (isPullRequestReviewCommentEvent(context)) {
174-
commentId = context.payload.comment.id.toString();
175-
commentBody = context.payload.comment.body;
176-
triggerUsername = context.payload.comment.user.login;
178+
commentId = context.payload.comment?.id?.toString();
179+
commentBody =
180+
context.payload.comment?.body ?? context.payload.review?.content;
181+
triggerUsername =
182+
context.payload.comment?.user?.login ?? context.payload.sender?.login;
177183
} else if (isIssuesEvent(context)) {
178184
triggerUsername = context.payload.issue.user.login;
179185
}
@@ -595,18 +601,7 @@ ${sanitizeContent(context.directPrompt)}
595601
</direct_prompt>`
596602
: ""
597603
}
598-
${
599-
eventData.eventName === "pull_request_review_comment"
600-
? `<comment_tool_info>
601-
IMPORTANT: For this inline PR review comment, you have been provided with ONLY the mcp__gitea__update_pull_request_comment tool to update this specific review comment.
602-
603-
Tool usage example for mcp__gitea__update_pull_request_comment:
604-
{
605-
"body": "Your comment text here"
606-
}
607-
All four parameters (owner, repo, commentId, body) are required.
608-
</comment_tool_info>`
609-
: `<comment_tool_info>
604+
${`<comment_tool_info>
610605
IMPORTANT: For this event type, you have been provided with ONLY the mcp__gitea__update_issue_comment tool to update comments.
611606
612607
Tool usage example for mcp__gitea__update_issue_comment:
@@ -617,8 +612,7 @@ Tool usage example for mcp__gitea__update_issue_comment:
617612
"body": "Your comment text here"
618613
}
619614
All four parameters (owner, repo, commentId, body) are required.
620-
</comment_tool_info>`
621-
}
615+
</comment_tool_info>`}
622616
623617
Your task is to analyze the context, understand the request, and provide helpful responses and/or implement code changes as needed.
624618
@@ -632,7 +626,7 @@ Follow these steps:
632626
1. Create a Todo List:
633627
- Use your Gitea comment to maintain a detailed task list based on the request.
634628
- Format todos as a checklist (- [ ] for incomplete, - [x] for complete).
635-
- Update the comment using ${eventData.eventName === "pull_request_review_comment" ? "mcp__gitea__update_pull_request_comment" : "mcp__gitea__update_issue_comment"} with each task completion.
629+
- Update the comment using mcp__gitea__update_issue_comment with each task completion.
636630
637631
2. Gather Context:
638632
- Analyze the pre-fetched data provided above.
@@ -738,8 +732,8 @@ ${!eventData.isPR || !eventData.claudeBranch ? `6. Final Update:` : `5. Final Up
738732
739733
Important Notes:
740734
- All communication must happen through Gitea PR comments.
741-
- Never create new comments. Only update the existing comment using ${eventData.eventName === "pull_request_review_comment" ? "mcp__gitea__update_pull_request_comment" : "mcp__gitea__update_issue_comment"} with comment_id: ${context.claudeCommentId}.
742-
- 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__gitea__update_issue_comment. Do NOT just respond with a normal response, the user will not see it." : ""}
735+
- Never create new comments. Only update the existing comment using mcp__gitea__update_issue_comment with comment_id: ${context.claudeCommentId}.
736+
- 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__gitea__update_issue_comment. Do NOT just respond with a normal response, the user will not see it.` : ""}
743737
- You communicate exclusively by editing your single comment - not through any other means.
744738
- 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;" />
745739
${eventData.isPR && !eventData.claudeBranch ? `- Always push to the existing branch when triggered on a PR.` : eventData.claudeBranch ? `- IMPORTANT: You are already on the correct branch (${eventData.claudeBranch}). Do not create additional branches.` : `- IMPORTANT: You are currently on the base branch (${eventData.baseBranch}). First check for existing claude branches for this ${eventData.isPR ? "PR" : "issue"} and use them if found, otherwise create a new branch using mcp__local_git_ops__create_branch.`}
@@ -750,8 +744,8 @@ ${eventData.isPR && !eventData.claudeBranch ? `- Always push to the existing bra
750744
- mcp__local_git_ops__delete_files: {"files": ["path/to/old.js"], "message": "chore: remove deprecated file"}
751745
- Display the todo list as a checklist in the Gitea comment and mark things off as you go.
752746
- All communication must happen through Gitea PR comments.
753-
- Never create new comments. Only update the existing comment using ${eventData.eventName === "pull_request_review_comment" ? "mcp__gitea__update_pull_request_comment" : "mcp__gitea__update_issue_comment"}.
754-
- 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__gitea__update_issue_comment. Do NOT just respond with a normal response, the user will not see it." : ""}
747+
- Never create new comments. Only update the existing comment using mcp__gitea__update_issue_comment.
748+
- 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__gitea__update_issue_comment. Do NOT just respond with a normal response, the user will not see it.` : ""}
755749
- You communicate exclusively by editing your single comment - not through any other means.
756750
- Use this spinner HTML when work is in progress: <img src="https://github.com/user-attachments/assets/5ac382c7-e004-429b-8e35-7feb3e8f9c6f" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />
757751
${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.`}

src/entrypoints/update-comment-link.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,22 @@ async function run() {
4141
// GitHub has separate ID namespaces for review comments and issue comments
4242
// We need to use the correct API based on the event type
4343
if (isPullRequestReviewCommentEvent(context)) {
44-
// For PR review comments, use the pulls API
45-
console.log(`Fetching PR review comment ${commentId}`);
46-
const response = await client.api.customRequest(
47-
"GET",
48-
`/api/v1/repos/${owner}/${repo}/pulls/comments/${commentId}`,
49-
);
50-
comment = response.data;
51-
isPRReviewComment = true;
52-
console.log("Successfully fetched as PR review comment");
44+
// Try the PR review comment endpoint first; Gitea may have created an
45+
// issue comment instead (no comment.id in payload), so fall through on 404.
46+
try {
47+
console.log(`Fetching PR review comment ${commentId}`);
48+
const response = await client.api.customRequest(
49+
"GET",
50+
`/api/v1/repos/${owner}/${repo}/pulls/comments/${commentId}`,
51+
);
52+
comment = response.data;
53+
isPRReviewComment = true;
54+
console.log("Successfully fetched as PR review comment");
55+
} catch {
56+
console.log(
57+
"PR review comment not found, falling back to issue comment",
58+
);
59+
}
5360
}
5461

5562
// For all other event types, use the issues API

src/github/context.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@ import type {
1010
import type { ModeName } from "../modes/types";
1111
import { DEFAULT_MODE, isValidMode } from "../modes/registry";
1212

13+
// Gitea review payloads use `review.content` instead of `review.body`, and
14+
// `sender` instead of nested user objects. These types extend the GitHub base
15+
// types to make both fields available without `as any` casts.
16+
export type GiteaPullRequestReviewEvent = PullRequestReviewEvent & {
17+
review?: { content?: string };
18+
sender?: { login: string };
19+
};
20+
21+
export type GiteaPullRequestReviewCommentEvent =
22+
PullRequestReviewCommentEvent & {
23+
review?: { type: string; content: string };
24+
sender?: { login: string };
25+
};
26+
1327
export type ParsedGitHubContext = {
1428
runId: string;
1529
eventName: string;
@@ -24,8 +38,8 @@ export type ParsedGitHubContext = {
2438
| IssuesEvent
2539
| IssueCommentEvent
2640
| PullRequestEvent
27-
| PullRequestReviewEvent
28-
| PullRequestReviewCommentEvent;
41+
| GiteaPullRequestReviewEvent
42+
| GiteaPullRequestReviewCommentEvent;
2943
entityNumber: number;
3044
isPR: boolean;
3145
inputs: {
@@ -181,13 +195,15 @@ export function isPullRequestEvent(
181195

182196
export function isPullRequestReviewEvent(
183197
context: ParsedGitHubContext,
184-
): context is ParsedGitHubContext & { payload: PullRequestReviewEvent } {
198+
): context is ParsedGitHubContext & { payload: GiteaPullRequestReviewEvent } {
185199
return context.eventName === "pull_request_review";
186200
}
187201

188202
export function isPullRequestReviewCommentEvent(
189203
context: ParsedGitHubContext,
190-
): context is ParsedGitHubContext & { payload: PullRequestReviewCommentEvent } {
204+
): context is ParsedGitHubContext & {
205+
payload: GiteaPullRequestReviewCommentEvent;
206+
} {
191207
return context.eventName === "pull_request_review_comment";
192208
}
193209

src/github/operations/comment-logic.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { GITEA_SERVER_URL } from "../api/config";
2-
31
export type ExecutionDetails = {
42
cost_usd?: number;
53
duration_ms?: number;
@@ -166,7 +164,11 @@ export function updateCommentBody(input: CommentUpdateInput): string {
166164
.filter((segment) => segment);
167165
const [owner, repo] = segments;
168166
if (owner && repo) {
169-
branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/src/branch/${finalBranchName}`;
167+
const serverUrl =
168+
process.env.GITEA_SERVER_URL ||
169+
process.env.GITHUB_SERVER_URL ||
170+
"https://github.com";
171+
branchUrl = `${serverUrl}/${owner}/${repo}/src/branch/${finalBranchName}`;
170172
}
171173
} catch (error) {
172174
console.warn(`Failed to derive branch URL from job URL: ${error}`);

src/github/operations/comments/create-initial.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ export async function createInitialComment(
3131
console.log(`Repository: ${owner}/${repo}`);
3232

3333
// Only use createReplyForReviewComment if it's a PR review comment AND we have a comment_id
34-
if (isPullRequestReviewCommentEvent(context)) {
34+
if (
35+
isPullRequestReviewCommentEvent(context) &&
36+
context.payload.comment?.id
37+
) {
3538
console.log(`Creating PR review comment reply`);
3639
response = await api.customRequest(
3740
"POST",

src/github/validation/trigger.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
4545
// Check for issue label trigger
4646
if (isIssuesEvent(context) && context.eventAction === "labeled") {
4747
const triggerLabel = context.inputs.labelTrigger?.trim();
48-
const appliedLabel = (context.payload as IssuesLabeledEvent).label?.name
49-
?.trim();
48+
const appliedLabel = (
49+
context.payload as IssuesLabeledEvent
50+
).label?.name?.trim();
5051

5152
console.log(
5253
`Checking label trigger: expected='${triggerLabel}', applied='${appliedLabel}'`,
@@ -55,7 +56,9 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
5556
if (
5657
triggerLabel &&
5758
appliedLabel &&
58-
triggerLabel.localeCompare(appliedLabel, undefined, { sensitivity: "accent" }) === 0
59+
triggerLabel.localeCompare(appliedLabel, undefined, {
60+
sensitivity: "accent",
61+
}) === 0
5962
) {
6063
console.log(`Issue labeled with trigger label '${triggerLabel}'`);
6164
return true;
@@ -115,9 +118,10 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
115118

116119
// Check if trigger user is in requested reviewers (treat same as mention in text)
117120
const triggerUser = triggerPhrase.replace(/^@/, "");
118-
const requestedReviewers = context.payload.pull_request.requested_reviewers || [];
119-
const isReviewerRequested = requestedReviewers.some(reviewer =>
120-
'login' in reviewer && reviewer.login === triggerUser
121+
const requestedReviewers =
122+
context.payload.pull_request.requested_reviewers || [];
123+
const isReviewerRequested = requestedReviewers.some(
124+
(reviewer) => "login" in reviewer && reviewer.login === triggerUser,
121125
);
122126

123127
if (isReviewerRequested) {
@@ -131,9 +135,12 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
131135
// Check for pull request review body trigger
132136
if (
133137
isPullRequestReviewEvent(context) &&
134-
(context.eventAction === "submitted" || context.eventAction === "edited")
138+
(context.eventAction === "submitted" ||
139+
context.eventAction === "edited" ||
140+
context.eventAction === "reviewed")
135141
) {
136-
const reviewBody = context.payload.review.body || "";
142+
const reviewBody =
143+
context.payload.review?.body ?? context.payload.review?.content ?? "";
137144
// Check for exact match with word boundaries or punctuation
138145
const regex = new RegExp(
139146
`(^|\\s)${escapeRegExp(triggerPhrase)}([\\s.,!?;:]|$)`,
@@ -153,7 +160,7 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
153160
) {
154161
const commentBody = isIssueCommentEvent(context)
155162
? context.payload.comment.body
156-
: context.payload.comment.body;
163+
: (context.payload.comment?.body ?? context.payload.review?.content);
157164
// Check for exact match with word boundaries or punctuation
158165
const regex = new RegExp(
159166
`(^|\\s)${escapeRegExp(triggerPhrase)}([\\s.,!?;:]|$)`,

0 commit comments

Comments
 (0)