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.
Phase 4: record the queue's new shape, and let the pins be tested while running
d798eaacf9b210fcdc2b51372d64a0e21e239bab · Keenan Nemetz · 17d ago · parent ac433531
Phase 4: record the queue's new shape, and let the pins be tested while running Docs, plus the two tests whose setup the new cancellation invalidates. docs/roadmap.md gains slices 7 and 8, rewrites the Phase 4 remaining list (the push-event table is gone by decision; what is left is the toolchain in the record, a narrowing/targeting filter for a mixed fleet, and a per-repository cap somebody would have to tune), adds an exit criterion for "a push whose spool file was never written still runs", and appends four decision-log rows: reconcile from the refs rather than persist events, park an idle lease on a wake-up channel, cancel queued superseded runs and order the lease by in-flight count, and keep runner presence in the queue filtered by the clone rule. README describes the new queue behaviour and /runners, and its stale "instance ed25519 key generated at first boot" line is replaced: the instance holds no signing key. Two tests built their scenario on a superseded run being started — queue v1, push v2, then run both. That is exactly what the queue no longer does, so both now hold the first build inside its step with a sentinel file, land the second push while it is running, and release it. The properties are unchanged and now tested where they actually apply: a build that is running when the branch moves must not publish a site (TestWorkflowRefusesAStaleSiteDeploy), and a run executes the steps it was queued with, not the workflow as the branch has it now (TestQueuedRunUsesTheWorkflowItWasQueuedFrom). A run that is still waiting when the new tip arrives is canceled, which TestANewerTipCancelsTheQueuedBuildOfTheOlderOne covers. scripts/ci.sh green before these comment-and-doc edits (internal/server 132.9s, everything else included); gofmt, vet, build and the markdown link check green after.
README.md +24−3
| @@ -51,7 +51,10 @@ Working today: | |||
| 51 | 51 | them. A push queues jobs; `vole runner` leases one over SSH with the same key, runs | |
| 52 | 52 | the shell steps, uploads the attempt's log and signs the result. A job can declare `artifacts:` | |
| 53 | 53 | (path patterns), which the runner uploads and the run page serves. Protected | |
| 54 | branches can require green checks as well as approvals | ||
| 54 | branches can require green checks as well as approvals. One runner pool serves | ||
| 55 | every repository on the instance, an idle runner parks on the queue instead of | ||
| 56 | polling it, a newer push cancels the queued builds of the one it replaced, and | ||
| 57 | `/runners` shows who is connected, what each is building and how much is waiting | ||
| 55 | 58 | - LFS: large files stay out of the git object database and live in one | |
| 56 | 59 | content-addressed store per instance. Uploads ride the SSH key | |
| 57 | 60 | (`git-lfs-transfer`); downloads come through the HTTP clone URL, anonymously for a | |
| @@ -69,8 +72,9 @@ Working today: | |||
| 69 | 72 | `<repo>.<pages_domain>`, straight out of git — no export step, ETags from blob | |
| 70 | 73 | shas, `304`s for unchanged pages. `vole pages deploy <dir>` publishes a build | |
| 71 | 74 | directory as a snapshot, `status` reports what is live, `unpublish` takes it down | |
| 72 | - An instance ed25519 key generated at first boot (used for metadata signing in | ||
| 73 | Phase 7) | ||
| 75 | - One secret on disk: the SSH host key. There is no instance signing key, because a | ||
| 76 | statement only the box can check is worth nothing to a mirror — a run's result is | ||
| 77 | signed by the runner that produced it | ||
| 74 | 78 | ||
| 75 | 79 | Not yet: LFS locking, and retention for run artifacts (they live as long as the run | |
| 76 | 80 | does). | |
| @@ -329,6 +333,23 @@ queued run executes. `on.push.branches` filters branch pushes and `on.push.tags` | |||
| 329 | 333 | filters tag pushes: a workflow with neither runs on every branch, and one that says | |
| 330 | 334 | `tags:` runs *only* on tags, because naming your trigger is naming it. | |
| 331 | 335 | ||
| 336 | The queue follows the refs, not just the push notification. A push is delivered by the | ||
| 337 | hook in well under a second, and every 30 seconds the server also compares each branch | ||
| 338 | and tag tip against the last tip it queued — so a push whose notification was lost (a | ||
| 339 | crash between the ref update and the hook's write) still runs. Deleting `data/runs.db` | ||
| 340 | loses the attempts that were in flight: the queue is rebuilt from the refs (each | ||
| 341 | current tip is queued once, since the notes about what had been queued went with the | ||
| 342 | file), and `vole index rebuild` brings the finished history back from the records on | ||
| 343 | each repository's `vole` branch. Pushing again cancels the *queued* runs of the commit | ||
| 344 | it replaced — never a running one — and one runner pool serves every repository: an | ||
| 345 | idle runner parks on the lease instead of asking again, and the lease prefers the | ||
| 346 | repository with the least work in flight. | ||
| 347 | |||
| 348 | `/runners` is the page for "why has my build not started": the connected runners, the job | ||
| 349 | each is building (or that it is waiting for one), and how much each repository has | ||
| 350 | queued and running. It follows the same visibility rule as everything else, so a runner | ||
| 351 | building a private repository is not shown. | ||
| 352 | |||
| 332 | 353 | ### Releases built by CI | |
| 333 | 354 | ||
| 334 | 355 | A tag push is a release build. Mark the artifacts `release: true` and the run commits | |