Skip to content
112 linesCodeBlameRaw
1-- Keeping runs safe: what a job's token may do, environments' protection
2-- rules, approval for pull requests from outside, a job's own concurrency
3-- group, and a cache scoped by ref. See src/protection.rs, src/plan.rs and
4-- src/cache.rs.
5
6-- A repository's choices for its workflows. A repository without a row
7-- has the defaults.
8CREATE TABLE IF NOT EXISTS repo_settings (
9 repo_id TEXT PRIMARY KEY,
10 -- What a workflow without `permissions:` gets: read (contents and
11 -- packages read, the default) or write (every permission).
12 default_permissions TEXT NOT NULL DEFAULT 'read',
13 -- Which pull requests' runs wait for someone with Write to approve them:
14 -- first_time_contributors, outside_contributors (the default) or
15 -- all_external_contributors.
16 approval_policy TEXT NOT NULL DEFAULT 'outside_contributors',
17 updated_at TEXT,
18 updated_by TEXT
19);
20
21-- An environment's protection rules. An environment without a row has
22-- none: its jobs run as soon as their needs are done.
23CREATE TABLE IF NOT EXISTS environments (
24 repo_id TEXT NOT NULL,
25 -- Lowercase, as secrets' environments are.
26 name TEXT NOT NULL,
27 -- JSON: [{"type": "user" | "team", "name": "ada" | "deployers"}], up to 6.
28 reviewers TEXT NOT NULL DEFAULT '[]',
29 -- Whoever started a run may not approve its jobs.
30 prevent_self_review INTEGER NOT NULL DEFAULT 0,
31 -- Minutes a job waits before it may start, 0 to 43200.
32 wait_minutes INTEGER NOT NULL DEFAULT 0,
33 -- all, protected (branches the rules protect) or selected (patterns).
34 branch_policy TEXT NOT NULL DEFAULT 'all',
35 -- JSON: [{"name": "release/*", "type": "branch" | "tag"}].
36 branch_patterns TEXT NOT NULL DEFAULT '[]',
37 -- Admins may approve without being a reviewer, skipping the wait.
38 admins_bypass INTEGER NOT NULL DEFAULT 1,
39 created_at TEXT NOT NULL,
40 updated_at TEXT NOT NULL,
41 updated_by TEXT,
42 PRIMARY KEY (repo_id, name)
43);
44
45-- A run's jobs held at an environment's rules: one row per run attempt and
46-- environment, however many of its jobs name it, as one review approves
47-- them all.
48CREATE TABLE IF NOT EXISTS environment_gates (
49 run_id TEXT NOT NULL,
50 attempt INTEGER NOT NULL,
51 environment TEXT NOT NULL,
52 repo_id TEXT NOT NULL,
53 -- waiting, approved or rejected.
54 state TEXT NOT NULL,
55 -- Whether a reviewer must approve it.
56 needs_review INTEGER NOT NULL DEFAULT 0,
57 -- When its wait timer lets it through; null without one.
58 wait_until TEXT,
59 reviewed_by TEXT,
60 comment TEXT,
61 reviewed_at TEXT,
62 created_at TEXT NOT NULL,
63 PRIMARY KEY (run_id, attempt, environment)
64);
65CREATE INDEX IF NOT EXISTS environment_gates_waiting ON environment_gates (state, wait_until);
66
67-- A run of a pull request from outside that waits to be approved:
68-- `approval` is required, then approved; `approved_by` a username.
69ALTER TABLE runs ADD COLUMN approval TEXT;
70ALTER TABLE runs ADD COLUMN approved_by TEXT;
71-- The run's concurrency group cancels what it replaces.
72ALTER TABLE runs ADD COLUMN cancel_in_progress INTEGER NOT NULL DEFAULT 0;
73
74-- A job's environment, read when its needs were done (an expression
75-- included), and its own concurrency group.
76ALTER TABLE jobs ADD COLUMN environment TEXT;
77ALTER TABLE jobs ADD COLUMN concurrency_group TEXT;
78ALTER TABLE jobs ADD COLUMN cancel_in_progress INTEGER NOT NULL DEFAULT 0;
79CREATE INDEX IF NOT EXISTS jobs_by_group ON jobs (repo_id, concurrency_group, status) WHERE concurrency_group IS NOT NULL;
80
81-- The cache, scoped by ref: an entry belongs to the ref whose run saved it
82-- (refs/heads/main, refs/pull/3/merge), and a run restores from its own
83-- ref, then its pull request's base branch, then the default branch. A
84-- pull request from outside the repository saves under `untrusted:<ref>`,
85-- which no other ref reads. `version` is the hash of the entry's paths and
86-- compression, so the same key saved for other paths is another entry.
87--
88-- The unique key changes, so the table is made again. Entries saved
89-- before scopes are marked expired: the next sweep deletes their objects
90-- and rows, so nothing saved without a scope is ever restored.
91CREATE TABLE cache_entries_v2 (
92 id TEXT PRIMARY KEY,
93 repo_id TEXT NOT NULL,
94 namespace TEXT NOT NULL,
95 scope TEXT NOT NULL,
96 key TEXT NOT NULL,
97 version TEXT NOT NULL DEFAULT '',
98 object TEXT NOT NULL,
99 size INTEGER NOT NULL DEFAULT 0,
100 status TEXT NOT NULL,
101 created_at TEXT NOT NULL,
102 last_used_at TEXT NOT NULL,
103 UNIQUE (repo_id, scope, key, version)
104);
105INSERT INTO cache_entries_v2 (id, repo_id, namespace, scope, key, version, object, size, status, created_at, last_used_at)
106SELECT id, repo_id, namespace, 'legacy:' || id, key, '', object, size, 'expired', created_at, last_used_at FROM cache_entries;
107DROP TABLE cache_entries;
108ALTER TABLE cache_entries_v2 RENAME TO cache_entries;
109CREATE INDEX IF NOT EXISTS cache_entries_by_use ON cache_entries (repo_id, status, last_used_at);
110CREATE INDEX IF NOT EXISTS cache_entries_by_status ON cache_entries (status, last_used_at);
111CREATE INDEX IF NOT EXISTS cache_entries_by_namespace ON cache_entries (namespace, status);
112CREATE INDEX IF NOT EXISTS cache_entries_by_scope ON cache_entries (repo_id, scope, status, created_at);