Add PR progress comment and increase Cursor review timeout.
Post a temporary in-progress comment while reviewing, remove it when done, default timeout to 10 minutes, and skip retries on timeout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+126
-84
@@ -4,6 +4,7 @@ import { runCursorReview } from "../cursor/review-agent.js";
|
||||
import { DedupeStore } from "../domain/dedupe-store.js";
|
||||
import { shouldProcessEvent } from "../domain/should-process-event.js";
|
||||
import { GiteaClient } from "../gitea/client.js";
|
||||
import { deleteProgressComment, postProgressComment } from "../gitea/comments-api.js";
|
||||
import { deletePriorBotReviews, postReview } from "../gitea/review-api.js";
|
||||
import { removeBotFromReviewers } from "../gitea/reviewer-api.js";
|
||||
import { buildReviewPrompt } from "../prompt/build-review-prompt.js";
|
||||
@@ -113,93 +114,134 @@ async function executeReview(params: {
|
||||
return "skipped";
|
||||
}
|
||||
|
||||
const files = await retry({
|
||||
fn: () => gitea.getPullFiles(owner, repo, prNumber),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "getPullFiles",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
const maxInlineComments = repoConfig.max_inline_comments ?? input.env.MAX_INLINE_COMMENTS;
|
||||
const prompt = buildReviewPrompt({
|
||||
owner,
|
||||
repo,
|
||||
pull,
|
||||
files,
|
||||
maxInlineComments,
|
||||
repoRuleFiles: ruleFiles
|
||||
});
|
||||
const review = await retry({
|
||||
fn: () =>
|
||||
runCursorReview({
|
||||
apiKey: input.env.CURSOR_API_KEY,
|
||||
prompt,
|
||||
timeoutMs: input.env.REVIEW_TIMEOUT_MS,
|
||||
model: repoConfig.model,
|
||||
correlationId: input.correlationId
|
||||
}),
|
||||
retries: 2,
|
||||
initialDelayMs: 500,
|
||||
operationName: "runCursorReview",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
let progressCommentId: number | undefined;
|
||||
try {
|
||||
try {
|
||||
progressCommentId = await postProgressComment({ gitea, owner, repo, prNumber });
|
||||
log("info", "Posted progress comment on PR", {
|
||||
correlation_id: input.correlationId,
|
||||
pr_number: prNumber,
|
||||
comment_id: progressCommentId
|
||||
});
|
||||
} catch (error) {
|
||||
log("warn", "Failed to post progress comment on PR", {
|
||||
correlation_id: input.correlationId,
|
||||
pr_number: prNumber,
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
});
|
||||
}
|
||||
|
||||
await retry({
|
||||
fn: () =>
|
||||
deletePriorBotReviews({
|
||||
gitea,
|
||||
owner,
|
||||
repo,
|
||||
prNumber,
|
||||
botLogin: input.env.GITEA_BOT_LOGIN
|
||||
}),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "deletePriorBotReviews",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
const files = await retry({
|
||||
fn: () => gitea.getPullFiles(owner, repo, prNumber),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "getPullFiles",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
const maxInlineComments = repoConfig.max_inline_comments ?? input.env.MAX_INLINE_COMMENTS;
|
||||
const prompt = buildReviewPrompt({
|
||||
owner,
|
||||
repo,
|
||||
pull,
|
||||
files,
|
||||
maxInlineComments,
|
||||
repoRuleFiles: ruleFiles
|
||||
});
|
||||
const review = await retry({
|
||||
fn: () =>
|
||||
runCursorReview({
|
||||
apiKey: input.env.CURSOR_API_KEY,
|
||||
prompt,
|
||||
timeoutMs: input.env.REVIEW_TIMEOUT_MS,
|
||||
model: repoConfig.model,
|
||||
correlationId: input.correlationId
|
||||
}),
|
||||
retries: 1,
|
||||
initialDelayMs: 500,
|
||||
operationName: "runCursorReview",
|
||||
correlationId: input.correlationId,
|
||||
shouldRetry: (error) => !isTimeoutError(error)
|
||||
});
|
||||
|
||||
await retry({
|
||||
fn: () =>
|
||||
postReview({
|
||||
gitea,
|
||||
owner,
|
||||
repo,
|
||||
prNumber,
|
||||
files,
|
||||
review,
|
||||
maxInlineComments
|
||||
}),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "postReview",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
await retry({
|
||||
fn: () =>
|
||||
deletePriorBotReviews({
|
||||
gitea,
|
||||
owner,
|
||||
repo,
|
||||
prNumber,
|
||||
botLogin: input.env.GITEA_BOT_LOGIN
|
||||
}),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "deletePriorBotReviews",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
|
||||
await retry({
|
||||
fn: () =>
|
||||
removeBotFromReviewers({
|
||||
gitea,
|
||||
owner,
|
||||
repo,
|
||||
prNumber,
|
||||
botLogin: input.env.GITEA_BOT_LOGIN
|
||||
}),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "removeBotFromReviewers",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
await retry({
|
||||
fn: () =>
|
||||
postReview({
|
||||
gitea,
|
||||
owner,
|
||||
repo,
|
||||
prNumber,
|
||||
files,
|
||||
review,
|
||||
maxInlineComments
|
||||
}),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "postReview",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
|
||||
input.dedupe.complete(dedupeKey);
|
||||
await retry({
|
||||
fn: () =>
|
||||
removeBotFromReviewers({
|
||||
gitea,
|
||||
owner,
|
||||
repo,
|
||||
prNumber,
|
||||
botLogin: input.env.GITEA_BOT_LOGIN
|
||||
}),
|
||||
retries: 2,
|
||||
initialDelayMs: 300,
|
||||
operationName: "removeBotFromReviewers",
|
||||
correlationId: input.correlationId
|
||||
});
|
||||
|
||||
log("info", "Review completed", {
|
||||
correlation_id: input.correlationId,
|
||||
owner,
|
||||
repo,
|
||||
pr_number: prNumber,
|
||||
head_sha: headSha,
|
||||
outcome: "success"
|
||||
});
|
||||
return "success";
|
||||
input.dedupe.complete(dedupeKey);
|
||||
|
||||
log("info", "Review completed", {
|
||||
correlation_id: input.correlationId,
|
||||
owner,
|
||||
repo,
|
||||
pr_number: prNumber,
|
||||
head_sha: headSha,
|
||||
outcome: "success"
|
||||
});
|
||||
return "success";
|
||||
} finally {
|
||||
if (progressCommentId !== undefined) {
|
||||
try {
|
||||
await deleteProgressComment({ gitea, owner, repo, commentId: progressCommentId });
|
||||
log("info", "Removed progress comment from PR", {
|
||||
correlation_id: input.correlationId,
|
||||
pr_number: prNumber,
|
||||
comment_id: progressCommentId
|
||||
});
|
||||
} 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)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isTimeoutError(error: unknown): boolean {
|
||||
return error instanceof Error && error.message.toLowerCase().includes("timed out");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user