import { waitUntil } from "cloudflare:workers";
import { hasPermission, loadRepoById, repoPermission } from "./repos";
import { loadUserById, toViewer } from "./auth";
import type { RepoRow } from "~/lib/types";
import { checkMergeability, loadPullByIssueId } from "./pulls";
import { scheduleWorkflows } from "./ci/scheduler";
import { requestCodeOwnerReviews } from "./review-requests";
import { emitWebhook, publicUrl } from "./events/emit";
import type { Viewer } from "~/lib/types";
/**
* Pull requests from forks run untrusted code on our containers, so (like GitHub) runs from actors
* without write access to the base repository wait for a maintainer to approve them.
*/
export async function forkRunNeedsApproval(
baseRepo: RepoRow,
headRepo: RepoRow,
actorId: string | null,
): Promise<boolean> {
if (baseRepo.id === headRepo.id) return false;
const actor = actorId ? await loadUserById(actorId) : null;
return !hasPermission(await repoPermission(baseRepo, actor ? toViewer(actor) : null), "write");
}
/** Kicks off CI and mergeability checks for a pull request lifecycle event without blocking the request. */
export function afterPullChange(
issueId: string,
action: "opened" | "reopened" | "synchronize" | "ready_for_review",
actor: Viewer,
): void {
waitUntil(
(async () => {
const pull = await loadPullByIssueId(issueId);
if (!pull) return;
const [baseRepo, headRepo] = await Promise.all([loadRepoById(pull.repo_id), loadRepoById(pull.head_repo_id)]);
if (!baseRepo || !headRepo) return;
await emitWebhook(baseRepo.id, "pull_request", {
action,
number: pull.number,
pull_request: {