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.
Phase 4 slice 3: checks on the gate, and statuses on the page
35eaeccffdab9d07e13fb7b346060e535697fee7 · Keenan Nemetz · 17d ago · parent b44cbfaf
Phase 4 slice 3: checks on the gate, and statuses on the page A protected branch now requires both an approved change request and passing checks for the commit being landed. Approvals say a person read the change; checks say it works. Neither substitutes for the other. The gate asks about the *approved head*, not about the merge commit somebody may be pushing: CI ran on the head, and a merge commit is a new object nobody built. That also keeps the gate consistent with what approvals already name. Details that decide whether this is usable: - A repository with no workflows is unaffected — nothing to run means nothing to wait for — so existing repositories do not start failing pushes. - A job with no run is refused with an explanation that names the branch filter, because `on: push: branches: [main]` never produces a result for a feature branch. That is the one configuration that can deadlock a merge, and the error says so instead of leaving somebody guessing. - Failed, cancelled, still-running and missing are four different messages; a reviewer should be able to tell which. - `vole acl checks <repo> on|off` turns it off, default on. Statuses are readable: the repository page lists recent runs (job, commit, status, attempts, age) and a change request shows its head's job statuses next to the approvals, so the reviewer sees the same facts the gate uses. Tests cover the three interesting shapes: approved + green lands; approved + red is refused naming the failed job; approved + no run at all is refused with the branch-filter hint. Verified on a live instance: pushing a workflow queues and runs it, the repository page shows `build · .vole/workflows/ci.yaml · success`, and the change request shows `wilbur · current` alongside `build · success`. Phase 4 is now complete except signed run records, which are Phase 7's.
internal/web/templates.go +35
| @@ -83,6 +83,24 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde | |||
| 83 | 83 | {{template "footer" .}} | |
| 84 | 84 | {{end}} | |
| 85 | 85 | ||
| 86 | {{define "repo-ci"}} | ||
| 87 | {{if .Runs}} | ||
| 88 | <h2>CI</h2> | ||
| 89 | <table> | ||
| 90 | <tr><th>Job</th><th>Commit</th><th>Status</th><th>Attempts</th><th>Age</th></tr> | ||
| 91 | {{range .Runs}} | ||
| 92 | <tr> | ||
| 93 | <td>{{.Job}} <span class="muted">{{.Workflow}}</span></td> | ||
| 94 | <td class="sha">{{short .SHA}}</td> | ||
| 95 | <td class="muted">{{.Status}}{{if eq .Status "failed"}} (exit {{.ExitCode}}){{end}}</td> | ||
| 96 | <td class="muted">{{.Attempts}}</td> | ||
| 97 | <td class="muted">{{since .Created.Unix}}</td> | ||
| 98 | </tr> | ||
| 99 | {{end}} | ||
| 100 | </table> | ||
| 101 | {{end}} | ||
| 102 | {{end}} | ||
| 103 | |||
| 86 | 104 | {{define "repo"}} | |
| 87 | 105 | {{template "header" .}} | |
| 88 | 106 | <h1>{{.Name}}</h1> | |
| @@ -129,6 +147,8 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde | |||
| 129 | 147 | ||
| 130 | 148 | <h2>Recent commits</h2> | |
| 131 | 149 | {{template "commitlist" .}} | |
| 150 | |||
| 151 | {{template "repo-ci" .}} | ||
| 132 | 152 | {{template "footer" .}} | |
| 133 | 153 | {{end}} | |
| 134 | 154 | ||
| @@ -331,6 +351,21 @@ commit to land, plus <code>approvals/<user>.json</code> from each approver | |||
| 331 | 351 | <p class="muted">No approvals yet. An approval names one commit, so pushing a new head starts over.</p> | |
| 332 | 352 | {{end}} | |
| 333 | 353 | ||
| 354 | <h2>Checks</h2> | ||
| 355 | {{if .Checks}} | ||
| 356 | <table> | ||
| 357 | <tr><th>Job</th><th>Status</th></tr> | ||
| 358 | {{range .Checks}} | ||
| 359 | <tr> | ||
| 360 | <td>{{.Job}} <span class="muted">{{.Workflow}}</span></td> | ||
| 361 | <td class="muted">{{.Status}}{{if eq .Status "failed"}} (exit {{.Exit}}){{end}}</td> | ||
| 362 | </tr> | ||
| 363 | {{end}} | ||
| 364 | </table> | ||
| 365 | {{else}} | ||
| 366 | <p class="muted">No CI run for this commit yet.</p> | ||
| 367 | {{end}} | ||
| 368 | |||
| 334 | 369 | <h2>What would land</h2> | |
| 335 | 370 | {{if .AlreadyMerged}} | |
| 336 | 371 | <p class="muted">Already merged into {{.Request.Base}}.</p> | |