#17 fix: handle pull_request_review_comment payload differences in Gitea (#19)

This commit is contained in:
leoarry
2026-06-08 09:13:54 +01:00
committed by GitHub
parent dfdfdd91fe
commit b744372179
6 changed files with 83 additions and 54 deletions

View File

@@ -10,6 +10,20 @@ import type {
import type { ModeName } from "../modes/types";
import { DEFAULT_MODE, isValidMode } from "../modes/registry";
// Gitea review payloads use `review.content` instead of `review.body`, and
// `sender` instead of nested user objects. These types extend the GitHub base
// types to make both fields available without `as any` casts.
export type GiteaPullRequestReviewEvent = PullRequestReviewEvent & {
review?: { content?: string };
sender?: { login: string };
};
export type GiteaPullRequestReviewCommentEvent =
PullRequestReviewCommentEvent & {
review?: { type: string; content: string };
sender?: { login: string };
};
export type ParsedGitHubContext = {
runId: string;
eventName: string;
@@ -24,8 +38,8 @@ export type ParsedGitHubContext = {
| IssuesEvent
| IssueCommentEvent
| PullRequestEvent
| PullRequestReviewEvent
| PullRequestReviewCommentEvent;
| GiteaPullRequestReviewEvent
| GiteaPullRequestReviewCommentEvent;
entityNumber: number;
isPR: boolean;
inputs: {
@@ -181,13 +195,15 @@ export function isPullRequestEvent(
export function isPullRequestReviewEvent(
context: ParsedGitHubContext,
): context is ParsedGitHubContext & { payload: PullRequestReviewEvent } {
): context is ParsedGitHubContext & { payload: GiteaPullRequestReviewEvent } {
return context.eventName === "pull_request_review";
}
export function isPullRequestReviewCommentEvent(
context: ParsedGitHubContext,
): context is ParsedGitHubContext & { payload: PullRequestReviewCommentEvent } {
): context is ParsedGitHubContext & {
payload: GiteaPullRequestReviewCommentEvent;
} {
return context.eventName === "pull_request_review_comment";
}

View File

@@ -1,5 +1,3 @@
import { GITEA_SERVER_URL } from "../api/config";
export type ExecutionDetails = {
cost_usd?: number;
duration_ms?: number;
@@ -166,7 +164,11 @@ export function updateCommentBody(input: CommentUpdateInput): string {
.filter((segment) => segment);
const [owner, repo] = segments;
if (owner && repo) {
branchUrl = `${GITEA_SERVER_URL}/${owner}/${repo}/src/branch/${finalBranchName}`;
const serverUrl =
process.env.GITEA_SERVER_URL ||
process.env.GITHUB_SERVER_URL ||
"https://github.com";
branchUrl = `${serverUrl}/${owner}/${repo}/src/branch/${finalBranchName}`;
}
} catch (error) {
console.warn(`Failed to derive branch URL from job URL: ${error}`);

View File

@@ -31,7 +31,10 @@ export async function createInitialComment(
console.log(`Repository: ${owner}/${repo}`);
// Only use createReplyForReviewComment if it's a PR review comment AND we have a comment_id
if (isPullRequestReviewCommentEvent(context)) {
if (
isPullRequestReviewCommentEvent(context) &&
context.payload.comment?.id
) {
console.log(`Creating PR review comment reply`);
response = await api.customRequest(
"POST",

View File

@@ -45,8 +45,9 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
// Check for issue label trigger
if (isIssuesEvent(context) && context.eventAction === "labeled") {
const triggerLabel = context.inputs.labelTrigger?.trim();
const appliedLabel = (context.payload as IssuesLabeledEvent).label?.name
?.trim();
const appliedLabel = (
context.payload as IssuesLabeledEvent
).label?.name?.trim();
console.log(
`Checking label trigger: expected='${triggerLabel}', applied='${appliedLabel}'`,
@@ -55,7 +56,9 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
if (
triggerLabel &&
appliedLabel &&
triggerLabel.localeCompare(appliedLabel, undefined, { sensitivity: "accent" }) === 0
triggerLabel.localeCompare(appliedLabel, undefined, {
sensitivity: "accent",
}) === 0
) {
console.log(`Issue labeled with trigger label '${triggerLabel}'`);
return true;
@@ -115,9 +118,10 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
// Check if trigger user is in requested reviewers (treat same as mention in text)
const triggerUser = triggerPhrase.replace(/^@/, "");
const requestedReviewers = context.payload.pull_request.requested_reviewers || [];
const isReviewerRequested = requestedReviewers.some(reviewer =>
'login' in reviewer && reviewer.login === triggerUser
const requestedReviewers =
context.payload.pull_request.requested_reviewers || [];
const isReviewerRequested = requestedReviewers.some(
(reviewer) => "login" in reviewer && reviewer.login === triggerUser,
);
if (isReviewerRequested) {
@@ -131,9 +135,12 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
// Check for pull request review body trigger
if (
isPullRequestReviewEvent(context) &&
(context.eventAction === "submitted" || context.eventAction === "edited")
(context.eventAction === "submitted" ||
context.eventAction === "edited" ||
context.eventAction === "reviewed")
) {
const reviewBody = context.payload.review.body || "";
const reviewBody =
context.payload.review?.body ?? context.payload.review?.content ?? "";
// Check for exact match with word boundaries or punctuation
const regex = new RegExp(
`(^|\\s)${escapeRegExp(triggerPhrase)}([\\s.,!?;:]|$)`,
@@ -153,7 +160,7 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
) {
const commentBody = isIssueCommentEvent(context)
? context.payload.comment.body
: context.payload.comment.body;
: (context.payload.comment?.body ?? context.payload.review?.content);
// Check for exact match with word boundaries or punctuation
const regex = new RegExp(
`(^|\\s)${escapeRegExp(triggerPhrase)}([\\s.,!?;:]|$)`,