g1t/packages/contracts/src/runners.ts

112 lines3,789 bytesCodeBlame
1import type { User } from "./identity";
2import type { RepoPath } from "./repos";
3import type { Result } from "./result";
4
5/**
6 * Self-hosted runners: a workspace's or a repository's own machines, which
7 * run its workflow jobs (and, when it says so, its agents' work) instead of
8 * g1t's sandboxes, at $0. Mirrors `crates/contracts/src/runners.rs`.
9 */
10
11export type RunnerStatus = "online" | "busy" | "offline";
12
13/** What a runner is doing now. */
14export type RunnerWork = {
15 kind: "workflow" | "agent";
16 id: string;
17 name: string;
18 repo: string | null;
19 runId: string | null;
20 startedAt: string | null;
21};
22
23export type Runner = {
24 id: string;
25 name: string;
26 workspace: string;
27 /** `owner/name` for a repository's own runner; null for the workspace's. */
28 repo: string | null;
29 group: string | null;
30 labels: string[];
31 os: "linux" | "macos" | "windows";
32 arch: "x64" | "arm64";
33 version: string;
34 ephemeral: boolean;
35 status: RunnerStatus;
36 work: RunnerWork | null;
37 lastSeenAt: string | null;
38 createdAt: string;
39 createdBy: string | null;
40};
41
42export type RunnerGroup = {
43 id: string;
44 name: string;
45 default: boolean;
46 /** Repository names; empty is every repository in the workspace. */
47 repositories: string[];
48 runners: number;
49 updatedAt: string;
50};
51
52/** Shown once. */
53export type RegistrationToken = {
54 token: string;
55 expiresAt: string;
56 workspace: string;
57 repo: string | null;
58 group: string | null;
59 url: string;
60};
61
62export type RunnerSettings = {
63 agentsOnSelfHosted: boolean;
64 agentLabels: string[];
65 forkPullRequests: boolean;
66 /** For a repository: these are its workspace's. */
67 inherited: boolean;
68};
69
70export type RunnersOwner = { repo: RepoPath } | { workspace: string };
71
72export type RunnerSettingsChange = {
73 agents_on_self_hosted?: boolean;
74 agent_labels?: string[];
75 fork_pull_requests?: boolean;
76 inherit?: boolean;
77};
78
79/** A job that has waited ten minutes or more with no matching runner online. */
80export type StuckJob = { id: string; name: string; runId: string; repo: string; labels: string; queuedAt: string };
81
82export interface RunnersApi {
83 /** The viewer's workspaces' jobs stuck waiting for a self-hosted runner, for Mission control. */
84 stuck(viewer: User): Promise<StuckJob[]>;
85 list(actor: User, owner: RunnersOwner): Promise<Result<Runner[]>>;
86 createToken(actor: User, owner: RunnersOwner, group?: string): Promise<Result<RegistrationToken>>;
87 remove(actor: User, owner: RunnersOwner, id: string): Promise<Result<boolean>>;
88 groups(actor: User, workspace: string): Promise<Result<RunnerGroup[]>>;
89 /** Without `id`, a new group. */
90 setGroup(actor: User, workspace: string, group: { id?: string; name?: string; repositories?: string[] }): Promise<Result<RunnerGroup>>;
91 deleteGroup(actor: User, workspace: string, id: string): Promise<Result<boolean>>;
92 settings(actor: User, owner: RunnersOwner): Promise<Result<RunnerSettings>>;
93 setSettings(actor: User, owner: RunnersOwner, change: RunnerSettingsChange): Promise<Result<RunnerSettings>>;
94}
95
96/**
97 * The runner's container image: `g1t-runner` and the Docker CLI, for
98 * running it in Docker or Kubernetes. Published with each release.
99 */
100export const RUNNER_IMAGE = "g1t.sh/flagon-io/g1t-runner";
101
102/** Where the runner binary is published: `g1t.sh/downloads/runner/<version>/<file>`. */
103export const RUNNER_DOWNLOADS = "https://g1t.sh/downloads/runner";
104
105/** The file for each platform, as published. */
106export const RUNNER_FILES: Record<"linux-x64" | "linux-arm64" | "macos-arm64" | "macos-x64" | "windows-x64", string> = {
107 "linux-x64": "g1t-runner-linux-x64",
108 "linux-arm64": "g1t-runner-linux-arm64",
109 "macos-arm64": "g1t-runner-macos-arm64",
110 "macos-x64": "g1t-runner-macos-x64",
111 "windows-x64": "g1t-runner-windows-x64.exe",
112};