vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Show run durations and lazy step logs
c765ae2e18691b3f98d93b00b4eb418ce781e3f1 · Keenan Nemetz · 13d ago · parent bdf6a0de
server/web/templates/run.html +84−6
| @@ -5,10 +5,11 @@ | |||
| 5 | 5 | <div class="page-head-main"> | |
| 6 | 6 | <h1>Run · {{.Run.Job}}</h1> | |
| 7 | 7 | <p class="page-sub"> | |
| 8 | {{.Run.Workflow}} · {{if .Run.Tag}}tag {{.Run.Tag}}{{else}}{{.Run.Branch}}{{end}} at <a class="sha" href="/r/{{.Name}}/commit/{{.Run.SHA}}">{{short .Run.SHA}}</a> | ||
| 9 | · {{.Run.Status}}{{if eq .Run.Status "failed"}} (exit {{.Run.ExitCode}}){{end}} | ||
| 8 | <span class="status {{.Run.Status}}">{{.Run.Status}}</span> | ||
| 9 | · {{.Run.Workflow}} | ||
| 10 | · {{if .Run.Tag}}tag {{.Run.Tag}}{{else}}{{.Run.Branch}}{{end}} | ||
| 11 | at <a class="sha" href="/r/{{.Name}}/commit/{{.Run.SHA}}">{{short .Run.SHA}}</a> | ||
| 10 | 12 | · attempt {{.Run.Attempts}} | |
| 11 | · {{since .Run.Created.Unix}} | ||
| 12 | 13 | </p> | |
| 13 | 14 | </div> | |
| 14 | 15 | {{if or .CanCancel .CanRerun}} | |
| @@ -24,13 +25,90 @@ | |||
| 24 | 25 | </div> | |
| 25 | 26 | {{end}} | |
| 26 | 27 | </div> | |
| 28 | |||
| 29 | <div class="run-summary"> | ||
| 30 | <div class="card"> | ||
| 31 | <span class="run-summary-label">{{icon "history"}}Duration</span> | ||
| 32 | {{if .Run.Started.IsZero}} | ||
| 33 | <strong>{{duration .Wait}}</strong> | ||
| 34 | <span class="status-note">{{if eq .Run.Status "queued"}}waiting for a runner{{else}}queued{{end}}</span> | ||
| 35 | {{else}} | ||
| 36 | <strong>{{duration .Duration}}</strong> | ||
| 37 | <span class="status-note">{{if .Run.Finished.IsZero}}running now{{else}}finished {{since .Run.Finished.Unix}}{{end}}</span> | ||
| 38 | {{end}} | ||
| 39 | </div> | ||
| 40 | <div class="card"> | ||
| 41 | <span class="run-summary-label">{{icon "history"}}Queue wait</span> | ||
| 42 | <strong>{{duration .Wait}}</strong> | ||
| 43 | <span class="status-note">{{if .Run.Started.IsZero}}so far{{else}}before the first runner leased it{{end}}</span> | ||
| 44 | </div> | ||
| 45 | <div class="card"> | ||
| 46 | <span class="run-summary-label">{{icon "server"}}Environment</span> | ||
| 47 | {{if .Run.OS}}<strong>{{.Run.OS}}/{{.Run.Arch}}</strong>{{else}}<strong class="muted">not reported</strong>{{end}} | ||
| 48 | <span class="status-note">{{if .Run.Image}}<code>{{if .Run.ImageFile}}{{.Run.ImageFile}}{{else}}{{.Run.Image}}{{end}}</code>{{if .Run.Runtime}} via {{.Run.Runtime}}{{end}}{{else}}no image recorded{{end}}</span> | ||
| 49 | </div> | ||
| 50 | <div class="card"> | ||
| 51 | <span class="run-summary-label">{{icon "git-commit-horizontal"}}Commit</span> | ||
| 52 | <strong><a class="sha" href="/r/{{.Name}}/commit/{{.Run.SHA}}">{{short .Run.SHA}}</a></strong> | ||
| 53 | <span class="status-note">{{if .Run.Tag}}tag {{.Run.Tag}}{{else}}branch {{.Run.Branch}}{{end}}{{if eq .Run.Status "failed"}} · exit {{.Run.ExitCode}}{{end}}</span> | ||
| 54 | </div> | ||
| 55 | </div> | ||
| 56 | |||
| 27 | 57 | {{if .Run.OS}}<p class="muted">ran on {{.Run.OS}}/{{.Run.Arch}}{{if .Run.Image}} · in {{if .Run.ImageFile}}image-file <code>{{.Run.ImageFile}}</code> ({{short .Run.ImageSHA}}){{else}}<code>{{.Run.Image}}</code>{{end}} via {{.Run.Runtime}}{{end}}</p>{{end}} | |
| 28 | 58 | {{if .Attestation}}<p class="muted">reported by <strong>{{.Signer}}</strong>{{if .Attestation.CommitID}} · <a href="/r/{{.Name}}/commit/{{.Attestation.CommitID}}">the commit that records it</a>{{end}} · the instance accepted this from that account's key at the push boundary, and logged it</p>{{end}} | |
| 29 | 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}} | |
| 30 | {{if .HasLog}}<p><a href="/r/{{.Name}}/runs/{{.Run.ID}}/log">log</a>{{if gt (len .Logs) 1}} · by attempt: | ||
| 31 | {{range .Logs}}<a href="/r/{{$.Name}}/runs/{{$.Run.ID}}/log?attempt={{.Attempt}}">{{.Attempt}}</a> {{end}}{{end}}</p>{{end}} | ||
| 32 | 60 | ||
| 33 | <h2>Artifacts</h2> | ||
| 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 | <h2>{{icon "terminal"}}Logs</h2> | ||
| 97 | {{if .HasLog}} | ||
| 98 | <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> | ||
| 101 | {{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 | </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> | ||
| 107 | {{else}} | ||
| 108 | <p class="muted">No log was archived for this run.</p> | ||
| 109 | {{end}} | ||
| 110 | |||
| 111 | <h2>{{icon "hard-drive"}}Artifacts</h2> | ||
| 34 | 112 | {{if .Artifacts}} | |
| 35 | 113 | <table> | |
| 36 | 114 | <tr><th>File</th><th>Size</th><th>SHA-256</th><th></th></tr> | |