This commit is contained in:
Daan Schouteden
2026-06-02 11:39:41 +02:00
commit 3d0e28f427
27 changed files with 3426 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
import { Env } from "../config/env.js";
import { loadRepoConfig } from "../config/load-repo-config.js";
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 { deletePriorBotReviews, postReview } from "../gitea/review-api.js";
import { removeBotFromReviewers } from "../gitea/reviewer-api.js";
import { buildReviewPrompt } from "../prompt/build-review-prompt.js";
import { RoutedEvent } from "../types/events.js";
import { retry } from "./retry.js";
export async function runReview(input: {
env: Env;
event: RoutedEvent;
dedupe: DedupeStore;
correlationId: string;
}): Promise<"skipped" | "success"> {
const owner = input.event.payload.repository.owner.login;
const repo = input.event.payload.repository.name;
const prNumber = input.event.payload.pull_request.number;
const headSha = input.event.payload.pull_request.head.sha;
const dedupeKey = input.dedupe.createKey({
owner,
repo,
prNumber,
headSha
});
if (input.dedupe.has(dedupeKey)) {
return "skipped";
}
input.dedupe.mark(dedupeKey);
const gitea = new GiteaClient(input.env.GITEA_BASE_URL, input.env.GITEA_TOKEN, 30000);
const pull = await retry({
fn: () => gitea.getPull(owner, repo, prNumber),
retries: 2,
initialDelayMs: 300
});
const { config: repoConfig, ruleFiles } = await retry({
fn: () =>
loadRepoConfig({
gitea,
owner,
repo,
ref: pull.head.ref
}),
retries: 2,
initialDelayMs: 300
});
const should = shouldProcessEvent({
event: input.event,
repoConfig,
defaultBaseBranch: input.env.DEFAULT_BASE_BRANCH,
botLogin: input.env.GITEA_BOT_LOGIN
});
if (!should.process) {
return "skipped";
}
const files = await retry({
fn: () => gitea.getPullFiles(owner, repo, prNumber),
retries: 2,
initialDelayMs: 300
});
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
}),
retries: 2,
initialDelayMs: 500
});
await retry({
fn: () =>
deletePriorBotReviews({
gitea,
owner,
repo,
prNumber,
botLogin: input.env.GITEA_BOT_LOGIN
}),
retries: 2,
initialDelayMs: 300
});
await retry({
fn: () =>
postReview({
gitea,
owner,
repo,
prNumber,
files,
review,
maxInlineComments
}),
retries: 2,
initialDelayMs: 300
});
await retry({
fn: () =>
removeBotFromReviewers({
gitea,
owner,
repo,
prNumber,
botLogin: input.env.GITEA_BOT_LOGIN
}),
retries: 2,
initialDelayMs: 300
});
console.log(
JSON.stringify({
correlation_id: input.correlationId,
owner,
repo,
pr_number: prNumber,
head_sha: headSha,
outcome: "success"
})
);
return "success";
}