Why
The run pages are the only place a person can see what CI did, but they currently show a result, a single log link and nothing about how long the job or its steps took. Debugging a slow or failed build therefore means opening one large log and guessing where each step begins.
Closes #01M5XEE6D6TVA60VVT58N0DDZ0 Closes #01M5XEG4P2TZ2BGF6JTN8RY66Y
What changed
Run metadata
- The runner records each step’s start, finish, exit code and byte range in the
attempt log as
runs/<run-id>/<attempt>/steps/<n>.md, alongside the signed record it already pushes. Records without step files still read unchanged. - The run page gains a summary row with total job duration, queue wait, environment and commit, plus a step table with each step’s result and duration.
- Step definitions pinned on the run fill in steps that never ran, so a failure shows the rest of the plan instead of stopping at the last executed step.
- The runs list, change-request Runs tab and repository overview now show run duration or queue wait.
Logs
GET /r/<name>/runs/<id>/logstreams the archived object withhttp.ServeContent: no whole-log read, no 1 MiB truncation, and range requests work.?attempt=Nstill selects one attempt.?step=Nserves only that step’s byte range in the attempt log.- The run page lazily loads the full job log or an individual step log into a
<pre>using htmx withhx-swap="textContent", so log text can never be interpreted as markup. - Step logs are slices of the one existing log object, not extra uploads.
Integrity
- A run record is now append-only at the attempt boundary: adding a step file or artifact pointer to an attempt that already has a record is refused, because it would change what the signed commit says without changing the commit.
Testing
vole workflow checkvole workflow run verify(format, vet, build, govulncheck, packages, markdown links, race test suite) — passed- Added coverage for step record round-tripping, append-only step enforcement, end-to-end step timing/log ranges, per-step log slicing and HTTP range support.
Scope note
Live log streaming while a step is still running is not included. The runner uploads an attempt’s log when the attempt ends, and changing that needs a new runner-to-server log protocol. This change removes the bulk-load and truncation problems for archived logs and makes per-step reading possible; live streaming can build on the same step-range format later.