29 lines · 1.2 KB
import { all, first } from "../db";
import { CAPS } from "../limits";
import { deleteRunnerRow, summarizeRunner } from "./runner-registration";
import type { RunnerRow, RunnerSummary } from "./runner-registration";

/** Owner-wide runners of an account (they serve every repository it owns). */
export async function listOwnerRunners(ownerId: string): Promise<RunnerSummary[]> {
  const rows = await all<RunnerRow>(
    "SELECT * FROM runners WHERE owner_id = ? ORDER BY name LIMIT ?",
    ownerId,
    CAPS.runnersPerScope,
  );
  const busy = await all<{ runner_id: string; count: number }>(
    `SELECT j.runner_id, COUNT(*) AS count FROM workflow_jobs j JOIN runners r ON r.id = j.runner_id
     WHERE j.status = 'in_progress' AND r.owner_id = ? GROUP BY j.runner_id`,
    ownerId,
  );
  const counts = new Map(busy.map((row) => [row.runner_id, row.count]));
  return rows.map((row) => summarizeRunner(row, counts.get(row.id) ?? 0));
}

/** Callers must have checked owner admin. */
export async function removeOwnerRunner(ownerId: string, runnerId: string): Promise<boolean> {
  const row = await first<{ id: string }>("SELECT id FROM runners WHERE id = ? AND owner_id = ?", runnerId, ownerId);
  if (!row) return false;
  await deleteRunnerRow(runnerId);
  return true;
}