flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/services/actions/migrations/0004_self_hosted_runners.sql

123 lines4,602 bytesCodeBlame
1-- Self-hosted runners: a workspace's or a repository's own machines, which
2-- run its workflow jobs (and, when it says so, its agents' work) instead
3-- of g1t's sandboxes. See `g1t_contracts::runners`.
4--
5-- Every statement can run twice: a table or index that exists is left as
6-- it is. The columns added to `jobs` are new in this file only.
7
8-- Which of a workspace's repositories may use its runners. Each workspace
9-- gets a default group (every repository) the first time it is needed.
10CREATE TABLE IF NOT EXISTS runner_groups (
11 id TEXT PRIMARY KEY,
12 -- The workspace's slug.
13 workspace TEXT NOT NULL,
14 name TEXT NOT NULL,
15 is_default INTEGER NOT NULL DEFAULT 0,
16 -- Repository names (without the workspace), as a JSON array. Empty: all.
17 repositories TEXT NOT NULL DEFAULT '[]',
18 created_at TEXT NOT NULL,
19 updated_at TEXT NOT NULL,
20 UNIQUE (workspace, name)
21);
22
23CREATE TABLE IF NOT EXISTS runners (
24 id TEXT PRIMARY KEY,
25 workspace TEXT NOT NULL,
26 -- A repository's own runner: only that repository's jobs. Null for the
27 -- workspace's, which serve the repositories its group allows.
28 repo_id TEXT,
29 repo TEXT,
30 group_id TEXT,
31 name TEXT NOT NULL,
32 -- JSON array, lowercase: self-hosted, the OS, the architecture, then
33 -- whatever it was given.
34 labels TEXT NOT NULL,
35 os TEXT NOT NULL,
36 arch TEXT NOT NULL,
37 version TEXT NOT NULL DEFAULT '',
38 ephemeral INTEGER NOT NULL DEFAULT 0,
39 -- SHA-256 of its credential. The one before a rotation stays valid
40 -- until the new one is first used.
41 credential_hash TEXT NOT NULL,
42 previous_hash TEXT,
43 rotated_at TEXT NOT NULL,
44 -- What it is running: a job's or a task's id, and which.
45 work_id TEXT,
46 work_kind TEXT,
47 -- An ephemeral runner that took its one job takes no more.
48 spent INTEGER NOT NULL DEFAULT 0,
49 last_seen_at TEXT,
50 created_at TEXT NOT NULL,
51 created_by TEXT
52);
53CREATE UNIQUE INDEX IF NOT EXISTS runners_by_name ON runners (workspace, COALESCE(repo_id, ''), name);
54CREATE INDEX IF NOT EXISTS runners_by_credential ON runners (credential_hash);
55CREATE INDEX IF NOT EXISTS runners_by_previous ON runners (previous_hash) WHERE previous_hash IS NOT NULL;
56CREATE INDEX IF NOT EXISTS runners_by_work ON runners (work_id) WHERE work_id IS NOT NULL;
57
58-- Registration tokens: an hour each, for as many runners as register with
59-- them until then. Kept as a hash.
60CREATE TABLE IF NOT EXISTS runner_registrations (
61 token_hash TEXT PRIMARY KEY,
62 workspace TEXT NOT NULL,
63 repo_id TEXT,
64 repo TEXT,
65 group_id TEXT,
66 created_by TEXT,
67 created_at TEXT NOT NULL,
68 expires_at TEXT NOT NULL,
69 used INTEGER NOT NULL DEFAULT 0
70);
71CREATE INDEX IF NOT EXISTS runner_registrations_by_workspace ON runner_registrations (workspace, created_at);
72
73-- Where g1t's own work runs, and whether forks' pull requests may use the
74-- runners: a workspace's (owner = its slug), or a repository's own
75-- (owner = its id), which overrides the workspace's.
76CREATE TABLE IF NOT EXISTS runner_settings (
77 owner TEXT PRIMARY KEY,
78 -- workspace or repository.
79 scope TEXT NOT NULL,
80 agents INTEGER NOT NULL DEFAULT 0,
81 -- JSON array of labels agent work needs.
82 agent_labels TEXT NOT NULL DEFAULT '["self-hosted"]',
83 fork_pulls INTEGER NOT NULL DEFAULT 0,
84 updated_at TEXT NOT NULL,
85 updated_by TEXT
86);
87
88-- Agent work (an agent's run, checks, a review, the merge queue) handed to
89-- a self-hosted runner by the runner service's sandbox, which is told how
90-- it ended. Its environment is sealed at rest and dropped once claimed.
91CREATE TABLE IF NOT EXISTS runner_tasks (
92 id TEXT PRIMARY KEY,
93 -- The sandbox (a Durable Object's id) waiting on it.
94 sandbox TEXT NOT NULL UNIQUE,
95 workspace TEXT NOT NULL,
96 repo_id TEXT,
97 repo TEXT NOT NULL,
98 kind TEXT NOT NULL,
99 title TEXT NOT NULL,
100 labels TEXT NOT NULL,
101 env TEXT,
102 timeout_minutes INTEGER NOT NULL,
103 -- queued, in_progress, completed.
104 status TEXT NOT NULL,
105 runner_id TEXT,
106 runner_name TEXT,
107 exit_code INTEGER,
108 reason TEXT,
109 created_at TEXT NOT NULL,
110 started_at TEXT,
111 seen_at TEXT,
112 finished_at TEXT
113);
114CREATE INDEX IF NOT EXISTS runner_tasks_by_status ON runner_tasks (status, workspace);
115
116-- A job whose runs-on names self-hosted runners: what it asks for (a JSON
117-- array; null for g1t's own sandboxes), when it started waiting, and the
118-- runner that took it.
119ALTER TABLE jobs ADD COLUMN labels TEXT;
120ALTER TABLE jobs ADD COLUMN queued_at TEXT;
121ALTER TABLE jobs ADD COLUMN runner_id TEXT;
122ALTER TABLE jobs ADD COLUMN runner_name TEXT;
123CREATE INDEX IF NOT EXISTS jobs_self_hosted ON jobs (namespace, status) WHERE labels IS NOT NULL;