Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Tail run logs in the browser and make steps accordions

34d6fd7a9210fca265ea4aea1d5733b3eeeb2569 · Keenan Nemetz · 10d ago · parent 5ece70a5

Tail run logs in the browser and make steps accordions

The log endpoint now serves from a byte offset and marks an attempt's log final,
so the run page can poll only while the job runs. The job output accordion follows
the stream; each step is its own accordion with its slice or a clear empty state.
The steps table is gone; the logs card is the whole viewer.

server/web/templates/run.html +23−41

@@ -58,52 +58,34 @@
58 58 {{if .Attestation}}<p class="muted">reported by <strong>{{.Signer}}</strong> · the instance accepted this result from that account's runner connection, and logged it</p>{{end}}
59 59 {{if .Counts}}<p class="muted">counts as a check for this repository</p>{{else if .CountsWhy}}<p class="muted">does not count as a check: {{.CountsWhy}}</p>{{end}}
60 60
61 <h2>{{icon "list"}}Steps</h2>
62 {{if .Steps}}
63 <div class="panel run-steps">
64 <table>
65 <thead>
66 <tr><th>#</th><th>Step</th><th>Result</th><th>Duration</th><th>Log</th></tr>
67 </thead>
68 <tbody>
69 {{range .Steps}}
70 <tr>
71 <td class="fit muted">{{.Number}}</td>
72 <td>{{.Name}}</td>
73 <td class="fit"><span class="status {{.Status}}">{{.Label}}</span></td>
74 <td class="nowrap">{{if .Duration}}{{duration .Duration}}{{else}}<span class="muted">—</span>{{end}}</td>
75 <td>{{if .LogURL}}<a href="{{.LogURL}}">open</a>{{else}}<span class="muted">—</span>{{end}}</td>
76 </tr>
77 {{if .LogURL}}
78 <tr class="run-step-log">
79 <td></td>
80 <td colspan="4">
81 <details class="run-log" hx-get="{{.LogURL}}" hx-trigger="toggle once" hx-target="find pre" hx-swap="textContent">
82 <summary>{{icon "terminal"}}Show step log</summary>
83 <pre class="run-log-text"></pre>
84 </details>
85 </td>
86 </tr>
87 {{end}}
88 {{end}}
89 </tbody>
90 </table>
91 </div>
92 {{else}}
93 <p class="muted">This run has no steps recorded.</p>
94 {{end}}
95
96 61 <h2>{{icon "terminal"}}Logs</h2>
97 62 {{if .HasLog}}
98 63 <div class="run-logbar">
99 <span class="muted">{{bytes .LogBytes}} archived log{{if gt (len .Logs) 1}} · {{len .Logs}} attempts{{end}}</span>
100 <a href="/r/{{.Name}}/runs/{{.Run.ID}}/log">Open full log</a>
64 <span class="muted">{{bytes .LogBytes}} {{if .Live}}streaming{{else}}log{{end}}</span>
101 65 {{if gt (len .Logs) 1}}{{range .Logs}}<a class="chip" href="/r/{{$.Name}}/runs/{{$.Run.ID}}/log?attempt={{.Attempt}}">{{icon "file"}}attempt {{.Attempt}}</a> {{end}}{{end}}
102 66 </div>
103 <details class="run-log" hx-get="/r/{{.Name}}/runs/{{.Run.ID}}/log" hx-trigger="toggle once" hx-target="find pre" hx-swap="textContent">
104 <summary>{{icon "terminal"}}Show the full job log</summary>
105 <pre class="run-log-text"></pre>
106 </details>
67 <div class="card run-log-card">
68 <details class="run-log run-log-live" {{if .Live}}open{{end}}>
69 <summary>
70 {{icon "terminal"}}<span class="run-log-title">Job output</span>
71 <span class="run-log-meta">attempt {{.LogAttempt}}{{if .Live}} · live{{else}} · complete{{end}}</span>
72 </summary>
73 <pre class="run-log-text" data-log-stream
74 data-log-url="/r/{{.Name}}/runs/{{.Run.ID}}/log?attempt={{.LogAttempt}}"
75 data-log-final="{{if .Live}}0{{else}}1{{end}}"></pre>
76 </details>
77 {{range .Steps}}
78 <details class="run-log{{if .LogURL}} run-step-log{{end}}"{{if .LogURL}} hx-get="{{.LogURL}}" hx-trigger="toggle once" hx-target="find pre" hx-swap="textContent"{{end}}>
79 <summary>
80 <span class="run-step-num">{{.Number}}</span>
81 <span class="run-step-name">{{.Name}}</span>
82 <span class="status {{.Status}}">{{.Label}}</span>
83 <span class="run-step-meta">{{if .Duration}}{{duration .Duration}}{{else}}—{{end}}</span>
84 </summary>
85 {{if .LogURL}}<pre class="run-log-text"></pre>{{else}}<p class="run-log-empty">{{if eq .Status "running"}}This step is running; its output is in the job output above.{{else if eq .Status "pending"}}Not started yet.{{else if eq .Status "queued"}}Waiting for a runner.{{else if eq .Status "not run"}}Not run.{{else}}No output was captured for this step.{{end}}</p>{{end}}
86 </details>
87 {{end}}
88 </div>
107 89 {{else}}
108 90 <p class="muted">No log was archived for this run.</p>
109 91 {{end}}