49 lines · 1.8 KB
/**
 * Cloud runner sizes. Each size is its own Container-backed Durable Object class because a Container's
 * instance type is fixed per class; larger sizes are charged proportionally more Container minutes.
 */
export type RunnerBinding = "RUNNER" | "RUNNER_LARGE" | "RUNNER_XLARGE";

type RunnerSize = { binding: RunnerBinding; labels: string[]; weight: number; description: string };

export const RUNNER_SIZES: RunnerSize[] = [
  {
    binding: "RUNNER",
    labels: ["cloudflare", "ubuntu-latest"],
    weight: 1,
    description: "standard-1: 1/2 vCPU, 4 GiB",
  },
  {
    binding: "RUNNER_LARGE",
    labels: ["cloudflare-large", "ubuntu-latest-4-cores"],
    weight: 2,
    description: "standard-2: 1 vCPU, 6 GiB",
  },
  {
    binding: "RUNNER_XLARGE",
    labels: ["cloudflare-xlarge", "ubuntu-latest-8-cores"],
    weight: 4,
    description: "standard-4: 4 vCPU, 12 GiB",
  },
];

export function cloudRunnerSize(runsOn: string[]): RunnerSize | null {
  if (runsOn.length !== 1) return null;
  return RUNNER_SIZES.find((size) => size.labels.includes(runsOn[0])) ?? null;
}

/** The serialized `workflow_jobs.runs_on` values that run on cloud Containers. */
export const CLOUD_RUNS_ON_VALUES = RUNNER_SIZES.flatMap((size) => size.labels.map((label) => JSON.stringify([label])));

/** SQL expression weighting a job's Container minutes by its runner size (`column` is the runs_on column). */
export function runnerWeightSql(column: string): string {
  const cases = RUNNER_SIZES.filter((size) => size.weight !== 1)