g1t/services/work/migrations/0028_rulesets.sql
Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge rulesets: branch and tag rules, agent-first, enforced on push and merge | 1 | -- Rulesets: what may happen to a repository's branches and tags, and what |
| 2 | -- a pull request needs before it merges. See crates/rules and | |
| 3 | -- src/rulesets.rs. Every timestamp is RFC 3339 UTC. | |
| 4 | ||
| 5 | -- A repository's rulesets (level 'repository', with repo_id) and a | |
| 6 | -- workspace's (level 'workspace'). `spec` is the ruleset as the API shows | |
| 7 | -- it (g1t_contracts::rules::RulesetSpec, JSON); name, enforcement and | |
| 8 | -- target are copied out of it for listing. | |
| 9 | CREATE TABLE rulesets ( | |
| 10 | id TEXT PRIMARY KEY, | |
| 11 | level TEXT NOT NULL, | |
| 12 | -- The workspace's slug; for a repository's, its workspace when saved. | |
| 13 | workspace TEXT NOT NULL, | |
| 14 | repo_id TEXT, | |
| 15 | name TEXT NOT NULL, | |
| 16 | enforcement TEXT NOT NULL, | |
| 17 | target TEXT NOT NULL, | |
| 18 | spec TEXT NOT NULL, | |
| 19 | -- 'branch_protection' for the one made from branch protection settings. | |
| 20 | source TEXT, | |
| 21 | created_by TEXT NOT NULL, | |
| 22 | created_at TEXT NOT NULL, | |
| 23 | updated_by TEXT NOT NULL, | |
| 24 | updated_at TEXT NOT NULL | |
| 25 | ); | |
| 26 | CREATE INDEX rulesets_by_repo ON rulesets (repo_id); | |
| 27 | CREATE INDEX rulesets_by_workspace ON rulesets (workspace, level); | |
| 28 | ||
| 29 | -- Every evaluation of a ruleset on a push, a merge or another change to a | |
| 30 | -- branch or tag: the audit trail, and what `evaluate` rulesets would have | |
| 31 | -- refused. `violations` is JSON (Vec<Violation>). Ids sort by time. | |
| 32 | CREATE TABLE rule_evaluations ( | |
| 33 | id TEXT PRIMARY KEY, | |
| 34 | repo_id TEXT NOT NULL, | |
| 35 | workspace TEXT NOT NULL, | |
| 36 | ruleset_id TEXT NOT NULL, | |
| 37 | ruleset_name TEXT NOT NULL, | |
| 38 | enforcement TEXT NOT NULL, | |
| 39 | -- push, merge, create_ref, delete_ref, rename_ref or commit. | |
| 40 | action TEXT NOT NULL, | |
| 41 | git_ref TEXT NOT NULL, | |
| 42 | actor TEXT NOT NULL, | |
| 43 | -- person, agent, g1t or token. | |
| 44 | actor_kind TEXT NOT NULL, | |
| 45 | -- pass, fail or bypass. | |
| 46 | verdict TEXT NOT NULL, | |
| 47 | violations TEXT NOT NULL DEFAULT '[]', | |
| 48 | number INTEGER, | |
| 49 | sha TEXT, | |
| 50 | created_at TEXT NOT NULL | |
| 51 | ); | |
| 52 | CREATE INDEX rule_evaluations_by_repo ON rule_evaluations (repo_id, id); | |
| 53 | CREATE INDEX rule_evaluations_by_workspace ON rule_evaluations (workspace, id); | |
| 54 | CREATE INDEX rule_evaluations_by_ruleset ON rule_evaluations (ruleset_id, id); | |
| 55 | ||
| 56 | -- The repos service kept whether pushes to the default branch were refused | |
| 57 | -- (its `protected` flag). The first time g1t reads a repository's rulesets | |
| 58 | -- after this, it folds that flag into its branch protection ruleset, once. | |
| 59 | CREATE TABLE ruleset_adoptions ( | |
| 60 | repo_id TEXT PRIMARY KEY, | |
| 61 | adopted_at TEXT NOT NULL | |
| 62 | ); | |
| 63 | ||
| 64 | -- Who moved a pull request's head last, and when: for approving the most | |
| 65 | -- recent push and dismissing approvals that came before it. | |
| 66 | ALTER TABLE pulls ADD COLUMN head_pushed_by TEXT; | |
| 67 | ALTER TABLE pulls ADD COLUMN head_pushed_at TEXT; | |
| 68 | ||
| 69 | -- The integration that reported a status: actions, deployments, security | |
| 70 | -- or g1t. A required check can insist on one. | |
| 71 | ALTER TABLE commit_statuses ADD COLUMN source TEXT; | |
| 72 | ||
| 73 | -- Branch protection becomes a ruleset, holding exactly what it held: the | |
| 74 | -- default branch's pull request rule (approvals, code owners), required | |
| 75 | -- status checks and merge queue. Pushes stay allowed here; repositories | |
| 76 | -- that refused them are adopted as described above. Only for repositories | |
| 77 | -- whose settings protect anything. | |
| 78 | INSERT INTO rulesets (id, level, workspace, repo_id, name, enforcement, target, spec, source, created_by, created_at, updated_by, updated_at) | |
| 79 | SELECT | |
| 80 | 'rs_' || lower(hex(randomblob(12))), | |
| 81 | 'repository', | |
| 82 | '', | |
| 83 | s.repo_id, | |
| 84 | 'Default branch protection', | |
| 85 | 'active', | |
| 86 | 'branch', | |
| 87 | json_object( | |
| 88 | 'name', 'Default branch protection', | |
| 89 | 'enforcement', 'active', | |
| 90 | 'target', 'branch', | |
| 91 | 'conditions', json_object('ref_name', json_object('include', json_array('~DEFAULT_BRANCH'), 'exclude', json_array())), | |
| 92 | 'bypass_actors', json_array(), | |
| 93 | 'rules', ( | |
| 94 | SELECT json_group_array(json(rule.value)) | |
| 95 | FROM json_each(json_array( | |
| 96 | CASE WHEN s.required_approvals > 0 OR s.require_code_owner_review != 0 THEN json_object( | |
| 97 | 'type', 'pull_request', | |
| 98 | 'parameters', json_object( | |
| 99 | 'required_approvals', s.required_approvals, | |
| 100 | 'count_agent_approvals', json(CASE WHEN s.count_agent_approvals != 0 THEN 'true' ELSE 'false' END), | |
| 101 | 'dismiss_stale_reviews_on_push', json('false'), | |
| 102 | 'require_code_owner_review', json(CASE WHEN s.require_code_owner_review != 0 THEN 'true' ELSE 'false' END), | |
| 103 | 'require_last_push_approval', json('false'), | |
| 104 | 'allowed_merge_methods', json_array(), | |
| 105 | 'allow_direct_pushes', json('true') | |
| 106 | ), | |
| 107 | 'applies_to', 'everyone' | |
| 108 | ) END, | |
| 109 | CASE WHEN s.required_checks != '[]' OR s.require_up_to_date != 0 THEN json_object( | |
| 110 | 'type', 'required_status_checks', | |
| 111 | 'parameters', json_object( | |
| 112 | 'checks', (SELECT json_group_array(json_object('context', checks.value)) FROM json_each(s.required_checks) AS checks), | |
| 113 | 'strict', json(CASE WHEN s.require_up_to_date != 0 THEN 'true' ELSE 'false' END), | |
| 114 | 'paths', json_array(), | |
| 115 | 'allow_bypass_on_merge', json(CASE WHEN s.allow_ignoring_checks != 0 THEN 'true' ELSE 'false' END) | |
| 116 | ), | |
| 117 | 'applies_to', 'everyone' | |
| 118 | ) END, | |
| 119 | CASE WHEN s.merge_queue != 0 THEN json_object( | |
| 120 | 'type', 'merge_queue', | |
| 121 | 'parameters', json_object( | |
| 122 | 'merge_method', 'merge', | |
| 123 | 'max_entries_to_build', 4, | |
| 124 | 'min_entries_to_merge', 1, | |
| 125 | 'min_entries_wait_minutes', 0, | |
| 126 | 'check_response_timeout_minutes', 45 | |
| 127 | ), | |
| 128 | 'applies_to', 'everyone' | |
| 129 | ) END | |
| 130 | )) AS rule | |
| 131 | WHERE rule.type != 'null' | |
| 132 | ) | |
| 133 | ), | |
| 134 | 'branch_protection', | |
| 135 | s.updated_by, | |
| 136 | s.updated_at, | |
| 137 | s.updated_by, | |
| 138 | s.updated_at | |
| 139 | FROM repo_settings s | |
| 140 | WHERE s.required_approvals > 0 | |
| 141 | OR s.require_code_owner_review != 0 | |
| 142 | OR s.required_checks != '[]' | |
| 143 | OR s.require_up_to_date != 0 | |
| 144 | OR s.merge_queue != 0; |
This file's history is long; its oldest lines are credited to the oldest commit read.