import { repoDb } from "../scoped-db";
import { notFoundError } from "../errors";
import { assertBelowCap, CAPS } from "../limits";
import { cancelActiveJob, completeJob } from "./jobs";
import type { WorkflowJobRow, WorkflowRunRow } from "./jobs";
import { startRun } from "./scheduler";
export async function loadRunByNumber(repoId: string, number: number): Promise<WorkflowRunRow> {
const row = await repoDb(repoId).first<WorkflowRunRow>(
"SELECT * FROM workflow_runs WHERE repo_id = ? AND run_number = ?",
repoId,
number,
);
if (!row) throw notFoundError("Run not found");
return row;
}
/** Cancels every unfinished job of a run; running jobs are stopped through their runner. */
export async function cancelRunRow(runRow: WorkflowRunRow): Promise<void> {
const db = repoDb(runRow.repo_id);
const jobs = await db.all<WorkflowJobRow>(
"SELECT * FROM workflow_jobs WHERE run_id = ? AND status != 'completed'",
runRow.id,
);
for (const job of jobs) {
if (job.status === "in_progress") await cancelActiveJob(job, "cancelled by user");
else await completeJob(job.id, "cancelled");
}
if (runRow.approval_required === 1 && runRow.status === "queued") {
await db.run(
"UPDATE workflow_runs SET status = 'completed', conclusion = 'cancelled', completed_at = ? WHERE id = ?",
Date.now(),
runRow.id,
);
}
}
/** Approves a fork run awaiting a maintainer and starts it, within the per-repo active run cap. */
export async function approveRunRow(repoId: string, runRow: WorkflowRunRow): Promise<void> {
const db = repoDb(repoId);