Centralize best-effort deletes: log errors and continue review flow.

All cleanup deletes now use runBestEffort so Gitea delete failures never abort posting the new review.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Daan Schouteden
2026-06-03 13:29:40 +02:00
parent 8bcd91cdb2
commit 95fa696935
4 changed files with 54 additions and 37 deletions
+8 -1
View File
@@ -1,4 +1,5 @@
import { GiteaClient } from "./client.js"; import { GiteaClient } from "./client.js";
import { runBestEffort } from "./run-best-effort.js";
export const PROGRESS_COMMENT_MARKER = "<!-- gitea-pr-review-bot-progress -->"; export const PROGRESS_COMMENT_MARKER = "<!-- gitea-pr-review-bot-progress -->";
@@ -26,8 +27,14 @@ export async function deleteProgressComment(input: {
owner: string; owner: string;
repo: string; repo: string;
commentId: number; commentId: number;
correlationId?: string;
}): Promise<void> { }): Promise<void> {
await input.gitea.deleteIssueComment(input.owner, input.repo, input.commentId); await runBestEffort({
operation: "Delete progress comment",
correlationId: input.correlationId,
context: { comment_id: input.commentId },
fn: () => input.gitea.deleteIssueComment(input.owner, input.repo, input.commentId)
});
} }
export const TIMEOUT_FAILURE_MARKER = "<!-- gitea-pr-review-bot-timeout -->"; export const TIMEOUT_FAILURE_MARKER = "<!-- gitea-pr-review-bot-timeout -->";
+12 -17
View File
@@ -1,8 +1,7 @@
import { log } from "../logging/logger.js";
import { GiteaClient, PullFile } from "./client.js"; import { GiteaClient, PullFile } from "./client.js";
import { ReviewResult } from "../cursor/review-schema.js"; import { ReviewResult } from "../cursor/review-schema.js";
import { runBestEffort } from "./run-best-effort.js";
/** Best-effort cleanup; never throws (Gitea may return 500 for some review states). */
export async function deletePriorBotReviews(input: { export async function deletePriorBotReviews(input: {
gitea: GiteaClient; gitea: GiteaClient;
owner: string; owner: string;
@@ -11,29 +10,25 @@ export async function deletePriorBotReviews(input: {
botLogin: string; botLogin: string;
correlationId?: string; correlationId?: string;
}): Promise<void> { }): Promise<void> {
try { await runBestEffort({
operation: "List prior bot reviews",
correlationId: input.correlationId,
context: { pr_number: input.prNumber },
fn: async () => {
const reviews = await input.gitea.getReviews(input.owner, input.repo, input.prNumber); const reviews = await input.gitea.getReviews(input.owner, input.repo, input.prNumber);
const botReviews = reviews.filter((review) => review.user?.login === input.botLogin); const botReviews = reviews.filter((review) => review.user?.login === input.botLogin);
for (const review of botReviews) { for (const review of botReviews) {
try { await runBestEffort({
await input.gitea.deleteReview(input.owner, input.repo, input.prNumber, review.id); operation: "Delete prior bot review",
} catch (error) { correlationId: input.correlationId,
log("warn", "Failed to delete prior bot review (continuing)", { context: { review_id: review.id, pr_number: input.prNumber },
correlation_id: input.correlationId, fn: () =>
review_id: review.id, input.gitea.deleteReview(input.owner, input.repo, input.prNumber, review.id)
pr_number: input.prNumber,
error: error instanceof Error ? error.message : String(error)
}); });
} }
} }
} catch (error) {
log("warn", "Failed to list prior bot reviews for cleanup (continuing)", {
correlation_id: input.correlationId,
pr_number: input.prNumber,
error: error instanceof Error ? error.message : String(error)
}); });
}
} }
export async function postReview(input: { export async function postReview(input: {
+23
View File
@@ -0,0 +1,23 @@
import { log } from "../logging/logger.js";
/** Run a cleanup step; log failures and continue the review flow. */
export async function runBestEffort(input: {
operation: string;
correlationId?: string;
context?: Record<string, unknown>;
fn: () => Promise<void>;
}): Promise<void> {
try {
await input.fn();
log("info", `${input.operation} succeeded`, {
correlation_id: input.correlationId,
...input.context
});
} catch (error) {
log("warn", `${input.operation} failed (continuing)`, {
correlation_id: input.correlationId,
...input.context,
error: error instanceof Error ? error.message : String(error)
});
}
}
+6 -14
View File
@@ -234,21 +234,13 @@ async function executeReview(params: {
throw error; throw error;
} finally { } finally {
if (progressCommentId !== undefined) { if (progressCommentId !== undefined) {
try { await deleteProgressComment({
await deleteProgressComment({ gitea, owner, repo, commentId: progressCommentId }); gitea,
log("info", "Removed progress comment from PR", { owner,
correlation_id: input.correlationId, repo,
pr_number: prNumber, commentId: progressCommentId,
comment_id: progressCommentId correlationId: input.correlationId
}); });
} catch (error) {
log("warn", "Failed to remove progress comment from PR", {
correlation_id: input.correlationId,
pr_number: prNumber,
comment_id: progressCommentId,
error: error instanceof Error ? error.message : String(error)
});
}
} }
} }
} }