Commit bb4c0aeb12
bb4c0aeb12da38e850e1c92c1df63169a9f56a5a
parent: ec5fe62412
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-28 08:06 UTC
wiki: failed step, build log --step and --tail
Closes #266
Layout: unified · split
.gitbay/wiki/Architecture/07-CI-and-Supply-Chain.org
+2 −1
| @@ -39,7 +39,8 @@ commit instead of failing silently. |
| 39 | (=cmd/gitbay-runner/isolate.go=). |
39 | (=cmd/gitbay-runner/isolate.go=). |
| 40 | 4. *Log.* =runner log <id>= streams stdin into the build row; the server |
40 | 4. *Log.* =runner log <id>= streams stdin into the build row; the server |
| 41 | ends the stream if the build is cancelled (=build.go=). |
41 | ends the stream if the build is cancelled (=build.go=). |
| 42 | 5. *Result.* =runner done <id> success|failure= sets the status, |
42 | 5. *Result.* =runner done <id> success|failure [--step <n>] [--reason |
| |
43 | <text>]= records where a failed build stopped, sets the status, |
| 43 | records an event and mails the repository's watchers a log tail on |
44 | records an event and mails the repository's watchers a log tail on |
| 44 | failure (=build.go=). |
45 | failure (=build.go=). |
| 45 | 6. *Reap.* The scheduler fails a running build whose log stream closed |
46 | 6. *Reap.* The scheduler fails a running build whose log stream closed |
.gitbay/wiki/CI.org
+11
| @@ -64,6 +64,17 @@ seconds: a follower who loses it is told the repository is not found. |
| 64 | A restart ends every open follow with a message saying so, rather |
64 | A restart ends every open follow with a message saying so, rather |
| 65 | than holding the drain; follow again once the daemon is back. |
65 | than holding the drain; follow again once the daemon is back. |
| 66 | |
66 | |
| |
67 | A failed build names the step it stopped at: the log's last line reads |
| |
68 | =step 3/3 failed: exit 1=, and =build show= prints =failed step= (=3/3 |
| |
69 | go test ./... (exit 1)=) and =duration=. =build log <owner/name> <n> |
| |
70 | --step failed= prints only that step's output, =--step 2= another one |
| |
71 | (=0= is the clone before the first step), and =--tail 40= the last forty |
| |
72 | lines of whichever was chosen; neither combines with =--follow=. The |
| |
73 | build page folds the finished log into one section per step, opens the |
| |
74 | failed one and links to it from the top as "Jump to failure". Builds |
| |
75 | from before this reported no step; their last section is taken as the |
| |
76 | failed one. |
| |
77 | |
| 67 | * What a build can reach |
78 | * What a build can reach |
| 68 | |
79 | |
| 69 | Builds have outbound internet access, trusted and untrusted alike. On |
80 | Builds have outbound internet access, trusted and untrusted alike. On |
.gitbay/wiki/Parity.org
+3
| @@ -217,6 +217,9 @@ rather than the one the web page shows. |
| 217 | | build show (one build) | yes | yes | yes | |
217 | | build show (one build) | yes | yes | yes | |
| 218 | | build log | yes | yes | yes | |
218 | | build log | yes | yes | yes | |
| 219 | | build log follow (until it ends) | yes | yes | no | |
219 | | build log follow (until it ends) | yes | yes | no | |
| |
220 | | build failed step, duration | yes | yes | no | |
| |
221 | | build log one step | yes | yes | no | |
| |
222 | | build log tail | yes | no | no | |
| 220 | | build jobs | yes | yes | yes | |
223 | | build jobs | yes | yes | yes | |
| 221 | | build trigger | yes | yes | yes | |
224 | | build trigger | yes | yes | yes | |
| 222 | | build cancel | yes | yes | yes | |
225 | | build cancel | yes | yes | yes | |
.gitbay/wiki/Users.org
+3 −1
| @@ -558,7 +558,9 @@ require-contexts= names statuses the gate waits for until they report, |
| 558 | and turns the gate on. =build list= takes =--ref=, |
558 | and turns the gate on. =build list= takes =--ref=, |
| 559 | =--status= and =--job= to narrow the listing, combinable; the builds |
559 | =--status= and =--job= to narrow the listing, combinable; the builds |
| 560 | 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 |
| 561 | parameters and groups the result into one row per commit. Steps run |
561 | parameters and groups the result into one row per commit. =build show= |
| |
562 | names a failed build's step and how long it ran, and =build log= takes |
| |
563 | =--step <n>|failed= and =--tail <lines>=. Steps run |
| 562 | with =sh -c= on the instance's runner, stopping at the first failure; |
564 | with =sh -c= on the instance's runner, stopping at the first failure; |
| 563 | a broken config surfaces as a failed =ci/config= status. Environment: |
565 | a broken config surfaces as a failed =ci/config= status. Environment: |
| 564 | =GITBAY_REPO=, |
566 | =GITBAY_REPO=, |
e2e/ci_test.go
+10
| @@ -147,6 +147,16 @@ func TestCI(t *testing.T) { |
| 147 | if !strings.Contains(out, "step 1/1 failed: exit 1") { |
147 | if !strings.Contains(out, "step 1/1 failed: exit 1") { |
| 148 | t.Fatalf("broken log:\n%s", out) |
148 | t.Fatalf("broken log:\n%s", out) |
| 149 | } |
149 | } |
| |
150 | out, _, _ = inst.ssh(t, aliceKey, "", "build", "show", "alice/app", brokenN) |
| |
151 | if !strings.Contains(out, "1/1 false (exit 1)") { |
| |
152 | t.Fatalf("build show does not name the failed step:\n%s", out) |
| |
153 | } |
| |
154 | if out, _, _ = inst.ssh(t, aliceKey, "", "build", "log", "alice/app", brokenN, "--step", "failed"); strings.Contains(out, "git clone") || !strings.Contains(out, "exit 1") { |
| |
155 | t.Fatalf("build log --step failed:\n%s", out) |
| |
156 | } |
| |
157 | if _, body := inst.get(t, "/alice/app/builds/"+brokenN); !strings.Contains(body, `id="failed" open`) { |
| |
158 | t.Fatalf("build page does not open the failed step:\n%s", body) |
| |
159 | } |
| 150 | // Statuses resolved, with target URLs pointing at the build pages. |
160 | // Statuses resolved, with target URLs pointing at the build pages. |
| 151 | out, _, _ = inst.ssh(t, aliceKey, "", "status", "list", "alice/app", sha, "--json") |
161 | out, _, _ = inst.ssh(t, aliceKey, "", "status", "list", "alice/app", sha, "--json") |
| 152 | if !strings.Contains(out, `"ci/ok","state":"success"`) && !strings.Contains(out, `"state":"success"`) { |
162 | if !strings.Contains(out, `"ci/ok","state":"success"`) && !strings.Contains(out, `"state":"success"`) { |