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=).
404. *Log.* =runner log <id>= streams stdin into the build row; the server 404. *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=).
425. *Result.* =runner done <id> success|failure= sets the status, 425. *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=).
456. *Reap.* The scheduler fails a running build whose log stream closed 466. *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.
64A restart ends every open follow with a message saying so, rather 64A restart ends every open follow with a message saying so, rather
65than holding the drain; follow again once the daemon is back. 65than holding the drain; follow again once the daemon is back.
66 66
67A 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
69go 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
72lines of whichever was chosen; neither combines with =--follow=. The
73build page folds the finished log into one section per step, opens the
74failed one and links to it from the top as "Jump to failure". Builds
75from before this reported no step; their last section is taken as the
76failed one.
77
67* What a build can reach 78* What a build can reach
68 79
69Builds have outbound internet access, trusted and untrusted alike. On 80Builds 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,
558and turns the gate on. =build list= takes =--ref=, 558and 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
560tab reads the same flags from its =?ref=, =?status= and =?job= query 560tab reads the same flags from its =?ref=, =?status= and =?job= query
561parameters and groups the result into one row per commit. Steps run 561parameters and groups the result into one row per commit. =build show=
562names a failed build's step and how long it ran, and =build log= takes
563=--step <n>|failed= and =--tail <lines>=. Steps run
562with =sh -c= on the instance's runner, stopping at the first failure; 564with =sh -c= on the instance's runner, stopping at the first failure;
563a broken config surfaces as a failed =ci/config= status. Environment: 565a 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"`) {