Commit d19e5181c5
d19e5181c5fae0d0eae2d7d48971e938e5e287c4
parent: dc10160221
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-28 07:04 UTC
wiki: reserved ci/ statuses, trusted reuse, required contexts
Closes #258
Layout: unified · split
.gitbay/wiki/API.org
+16 −2
| @@ -112,8 +112,8 @@ CI reports results through the same command surface (over SSH or the |
| 112 | JSON API with a full-scope token; reporting requires write access): |
112 | JSON API with a full-scope token; reporting requires write access): |
| 113 | |
113 | |
| 114 | #+begin_src sh |
114 | #+begin_src sh |
| 115 | gitbay status set <owner/name> <sha> --context build --state pending |
115 | gitbay status set <owner/name> <sha> --context ext/build --state pending |
| 116 | gitbay status set <owner/name> <sha> --context build --state success --url https://ci.example/run/1 |
116 | gitbay status set <owner/name> <sha> --context ext/build --state success --url https://ci.example/run/1 |
| 117 | gitbay status list <owner/name> <sha> --json # {"combined": "...", "statuses": [...]} |
117 | gitbay status list <owner/name> <sha> --json # {"combined": "...", "statuses": [...]} |
| 118 | #+end_src |
118 | #+end_src |
| 119 | |
119 | |
| @@ -130,6 +130,20 @@ from outside through =status set= looks like. A repository where |
| 130 | nothing has ever reported merges. Each |
130 | nothing has ever reported merges. Each |
| 131 | report also emits a =status= event to webhooks. |
131 | report also emits a =status= event to webhooks. |
| 132 | |
132 | |
| |
133 | Contexts starting with =ci/= are the instance's own: its builds queue, |
| |
134 | reuse, skip and finish them, and =status set= refuses them with exit 4, |
| |
135 | so a writer cannot mark =ci/test= green on a head the build has not |
| |
136 | passed. Report under another prefix, such as =ext/=. |
| |
137 | |
| |
138 | =repo settings require-contexts <repo> ext/deploy ci/test= names |
| |
139 | statuses the checks gate waits for whether or not they have reported: |
| |
140 | one that has not is =pending=, and =mr show= lists it as |
| |
141 | =ext/deploy=missing=. Naming any context turns =require-checks= on; |
| |
142 | with no contexts the command clears the list and leaves |
| |
143 | =require-checks= as it was. =require-checks off= keeps the list, which |
| |
144 | waits for nothing until the gate is on again. =repo settings show= |
| |
145 | prints both. |
| |
146 | |
| 133 | * Webhooks |
147 | * Webhooks |
| 134 | |
148 | |
| 135 | Per-repository outbound POSTs for repository events. Managed by repo |
149 | Per-repository outbound POSTs for repository events. Managed by repo |
.gitbay/wiki/Architecture/07-CI-and-Supply-Chain.org
+2 −2
| @@ -23,7 +23,7 @@ commit instead of failing silently. |
| 23 | 1. *Queue.* The post-receive hook calls =queueJobs= |
23 | 1. *Queue.* The post-receive hook calls =queueJobs= |
| 24 | (=internal/control/build.go=). Each job gets a =ci/<job>= status: |
24 | (=internal/control/build.go=). Each job gets a =ci/<job>= status: |
| 25 | =pending= when queued, =skipped= when path filters exclude it, or |
25 | =pending= when queued, =skipped= when path filters exclude it, or |
| 26 | =success= copied from an earlier build of the same tree (#177). |
26 | =success= copied from an earlier trusted build of the same tree on the same image (#177, #258). |
| 27 | Merge requests from forks are queued against the target repository |
27 | Merge requests from forks are queued against the target repository |
| 28 | with =trusted = false=. |
28 | with =trusted = false=. |
| 29 | 2. *Claim.* A runner calls =runner next= over SSH |
29 | 2. *Claim.* A runner calls =runner next= over SSH |
| @@ -55,7 +55,7 @@ Who may do what: |
| 55 | | =repo secret set/remove/list= | admin on the repository | |
55 | | =repo secret set/remove/list= | admin on the repository | |
| 56 | | =repo runner add/remove= | admin on the repository | |
56 | | =repo runner add/remove= | admin on the repository | |
| 57 | | =runner next/log/done= | =runner= key attached to the repository, or admin | |
57 | | =runner next/log/done= | =runner= key attached to the repository, or admin | |
| 58 | | =status set= | write on the repository (any context name; #258) | |
58 | | =status set= | write on the repository; =ci/*= contexts refused (=status.go=) | |
| 59 | |
59 | |
| 60 | * Runner isolation |
60 | * Runner isolation |
| 61 | |
61 | |
.gitbay/wiki/Architecture/09-Controls.org
+2 −2
| @@ -36,7 +36,7 @@ chapter names of OWASP ASVS 4.0 where one fits. |
| 36 | | Private resources indistinguishable from missing | in place | =resolveRepo= (=internal/control/repo.go=), =runGit=, smart HTTP | |
36 | | Private resources indistinguishable from missing | in place | =resolveRepo= (=internal/control/repo.go=), =runGit=, smart HTTP | |
| 37 | | Credential scopes narrow account rights | in place | key and token scopes (=control.go=, =policy/access.go=) | |
37 | | Credential scopes narrow account rights | in place | key and token scopes (=control.go=, =policy/access.go=) | |
| 38 | | Server-side write protections | in place | pre-receive =CheckPush=, signed commits (=internal/hookd/hookd.go=) | |
38 | | Server-side write protections | in place | pre-receive =CheckPush=, signed commits (=internal/hookd/hookd.go=) | |
| 39 | | Merge gates | partial | =MergeGates=; any writer can post a =ci/*= status (#258) | |
39 | | Merge gates | in place | =MergeGates=; =ci/*= statuses written only by the build subsystem; required contexts | |
| 40 | | Admin functions isolated | in place | =admin= noun gated in =Dispatch=; =audit= admin-only | |
40 | | Admin functions isolated | in place | =admin= noun gated in =Dispatch=; =audit= admin-only | |
| 41 | | CSRF protection | in place | SameSite=Lax plus =checkOrigin= (=accounts.go=) | |
41 | | CSRF protection | in place | SameSite=Lax plus =checkOrigin= (=accounts.go=) | |
| 42 | | Typed confirmation for destructive web actions | in place | =internal/httpd/confirm.go= | |
42 | | Typed confirmation for destructive web actions | in place | =internal/httpd/confirm.go= | |
| @@ -89,7 +89,7 @@ chapter names of OWASP ASVS 4.0 where one fits. |
| 89 | | Runner limited to attached repositories | in place | =runnerMayBuild= (=build.go=) | |
89 | | Runner limited to attached repositories | in place | =runnerMayBuild= (=build.go=) | |
| 90 | | Build images fixed by the operator | in place | =--pull=never= | |
90 | | Build images fixed by the operator | in place | =--pull=never= | |
| 91 | | Build network egress restricted | gap | #260 | |
91 | | Build network egress restricted | gap | #260 | |
| 92 | | Build results reused only across equal trust | gap | tree reuse ignores trust and image (#258) | |
92 | | Build results reused only across equal trust | in place | =SuccessBuildForTree=, =SuccessBuildFor= (=internal/store/builds.go=) | |
| 93 | |
93 | |
| 94 | ** Availability and operations |
94 | ** Availability and operations |
| 95 | |
95 | |
.gitbay/wiki/Architecture/10-Known-Gaps.org
−1
| @@ -10,7 +10,6 @@ what the 2026-09-27 review found; remove a row when its issue closes. |
| 10 | |
10 | |
| 11 | | Issue | Area | Gap | Severity | |
11 | | Issue | Area | Gap | Severity | |
| 12 | |-------+------------------+-----------------------------------------------------------------------+----------| |
12 | |-------+------------------+-----------------------------------------------------------------------+----------| |
| 13 | | #258 | CI integrity | Any writer can post a =ci/*= status; tree reuse ignores trust and image | high | |
| |
| 14 | | #259 | Recovery | No restore has been exercised; verification does not check git connectivity | high | |
13 | | #259 | Recovery | No restore has been exercised; verification does not check git connectivity | high | |
| 15 | | #260 | CI network | Builds share the runner's source address; no egress policy | medium | |
14 | | #260 | CI network | Builds share the runner's source address; no egress policy | medium | |
| 16 | | #261 | Various | Migration foreign-key check after commit; three web writes bypass dispatch; documentation drift | medium | |
15 | | #261 | Various | Migration foreign-key check after commit; three web writes bypass dispatch; documentation drift | medium | |
.gitbay/wiki/CI.org
+10 −1
| @@ -5,7 +5,16 @@ Three mechanisms decide what a push does to CI, and they interact: |
| 5 | - *Dedupe.* A job's result is a property of the commit's tree. A commit |
5 | - *Dedupe.* A job's result is a property of the commit's tree. A commit |
| 6 | that already has a passed, queued or running build for a job is not |
6 | that already has a passed, queued or running build for a job is not |
| 7 | queued again; a commit whose tree already passed a job gets that |
7 | queued again; a commit whose tree already passed a job gets that |
| 8 | result as its status, naming the build it came from (#177). A failed, |
8 | result as its status, naming the build it came from (#177). Only a trusted build counts, and for tree reuse only one on the |
| |
9 | image the job names: a fork's green build does not stand for the |
| |
10 | repository's own, so its commit is built again when it lands on a |
| |
11 | branch (#258). A job that names no =image:= is compared as naming |
| |
12 | none: its reuse does not notice the runner's default image changing, |
| |
13 | because reuse is decided when the push is queued, before any runner |
| |
14 | claims the build, and runners can differ in their default. Name the |
| |
15 | image in =ci.yml= to tie reuse to it; after an operator changes a |
| |
16 | runner's =-image=, =build trigger= builds a job afresh, since a |
| |
17 | triggered build is never reused. A failed, |
| 9 | cancelled or abandoned build does not count: that commit runs again. |
18 | cancelled or abandoned build does not count: that commit runs again. |
| 10 | - *Path filters.* =paths= and =paths-ignore= on a job are evaluated |
19 | - *Path filters.* =paths= and =paths-ignore= on a job are evaluated |
| 11 | against the files the push changed. The diff base is the old tip when |
20 | against the files the push changed. The diff base is the old tip when |
.gitbay/wiki/Parity.org
+1
| @@ -197,6 +197,7 @@ rather than the one the web page shows. |
| 197 | | merge requests only | yes | yes | yes | |
197 | | merge requests only | yes | yes | yes | |
| 198 | | protected tags | yes | yes | yes | |
198 | | protected tags | yes | yes | yes | |
| 199 | | require codeowners | yes | yes | yes | |
199 | | require codeowners | yes | yes | yes | |
| |
200 | | require contexts | yes | yes | no | |
| 200 | | access grants | yes | no | yes | |
201 | | access grants | yes | no | yes | |
| 201 | | effective access | yes | no | yes | |
202 | | effective access | yes | no | yes | |
| 202 | | webhooks | yes | no | yes | |
203 | | webhooks | yes | no | yes | |
.gitbay/wiki/Users.org
+3 −1
| @@ -553,7 +553,9 @@ queues nothing, so look there when a push builds nothing. |
| 553 | |
553 | |
| 554 | Each job becomes a build (=build list=, =build log=, the builds tab on |
554 | Each job becomes a build (=build list=, =build log=, the builds tab on |
| 555 | the web) and a =ci/<job>= commit status, which =repo settings |
555 | the web) and a =ci/<job>= commit status, which =repo settings |
| 556 | require-checks= can gate merges on. =build list= takes =--ref=, |
556 | require-checks= can gate merges on. =repo settings |
| |
557 | require-contexts= names statuses the gate waits for until they report, |
| |
558 | and turns the gate on. =build list= takes =--ref=, |
| 557 | =--status= and =--job= to narrow the listing, combinable; the builds |
559 | =--status= and =--job= to narrow the listing, combinable; the builds |
| 558 | tab reads the same flags from its =?ref=, =?status= and =?job= query |
560 | tab reads the same flags from its =?ref=, =?status= and =?job= query |
| 559 | parameters and groups the result into one row per commit. Steps run |
561 | parameters and groups the result into one row per commit. Steps run |