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 7 slice 8: a tag push builds the release
0f442b1c87ca3920f770531c9ad97277d0231f51 · Keenan Nemetz · 17d ago · parent 88e980b0
Phase 7 slice 8: a tag push builds the release on.push.tags opens CI to tag pushes; release: true on an artifact publishes it to that tag's release rather than only to the run. The runner commits the same pointers `vole release attach` writes, so the release page, the ETags, the immutability rules and the sweep needed no changes: CI gained a trigger, not a publish path. Three rules, each from something that went wrong in the first draft: - a workflow that says tags: runs ONLY on tags. Saying what you trigger on is saying it; the first version defaulted to every branch too and queued a doomed release build on every commit - a tag run never counts as a branch's required check. A tag on a branch tip produces a second run for the same sha, and ForSHA would have let a release build satisfy — or break — the gate for the commit it tags. It now filters to refs/heads/% - a lightweight tag cannot name a release: the build runs and the publish fails saying so, because a tag with no message has no notes and no tagger. The server resolves annotated-ness at enqueue (the tag object's type) rather than having the runner parse ls-remote peeled lines Tag and annotated-ness ride the run and the job payload beside the release artifact patterns, pinned at enqueue like everything else. Measured through the binary: a branch push queued nothing, a tag push queued the release job, the runner published dist/tool-linux, the release page listed it with the tag marked annotated, the download returned the bytes, and git log vole read "release: v1.0.0 artifacts from run 01M5MSX3...".
README.md +38−1
| @@ -226,7 +226,41 @@ vole runner --remote ssh://git@host:2222 # long-poll; --once runs one job | |||
| 226 | 226 | ||
| 227 | 227 | A push that touches a workflow queues one run per job, pinned to the commit *and* to | |
| 228 | 228 | the workflow file's blob, so editing the workflow afterwards cannot change what a | |
| 229 | queued run executes. The runner leases a job over the same SSH key you push with, | ||
| 229 | queued run executes. `on.push.branches` filters branch pushes and `on.push.tags` | ||
| 230 | filters tag pushes: a workflow with neither runs on every branch, and one that says | ||
| 231 | `tags:` runs *only* on tags, because naming your trigger is naming it. | ||
| 232 | |||
| 233 | ### Releases built by CI | ||
| 234 | |||
| 235 | A tag push is a release build. Mark the artifacts `release: true` and the run commits | ||
| 236 | them as that tag's release artifacts — the same pointers `vole release attach` writes, | ||
| 237 | so the release page, the ETags and the immutability rules are unchanged: | ||
| 238 | |||
| 239 | ```yaml | ||
| 240 | version: 1 | ||
| 241 | on: | ||
| 242 | push: | ||
| 243 | tags: ['v*'] | ||
| 244 | jobs: | ||
| 245 | release: | ||
| 246 | steps: | ||
| 247 | - name: build | ||
| 248 | run: make dist | ||
| 249 | artifacts: | ||
| 250 | - path: dist/* | ||
| 251 | release: true | ||
| 252 | ``` | ||
| 253 | |||
| 254 | ```sh | ||
| 255 | git tag -a v1.0.0 -m "first release" # a release needs notes and a tagger | ||
| 256 | git push origin refs/tags/v1.0.0 # the runner builds and publishes | ||
| 257 | ``` | ||
| 258 | |||
| 259 | The metadata commit names the build (`release: v1.0.0 artifacts from run 01M5...`), so | ||
| 260 | `git log vole` says which run shipped the bytes. A lightweight tag is refused at the | ||
| 261 | publish — `git tag -a`, not `git tag` — because a tag with no message has no release | ||
| 262 | notes and no tagger. A run for a tag never counts as a branch's required check, even | ||
| 263 | when the tag points at that branch's tip. The runner leases a job over the same SSH key you push with, | ||
| 230 | 264 | checks out the commit, runs the steps with per-step timeouts, heartbeats while it | |
| 231 | 265 | works, and reports the exit code and log. A runner that disappears has its job | |
| 232 | 266 | requeued; after five attempts the job fails instead of cycling forever. Protected | |
| @@ -313,6 +347,9 @@ git push --follow-tags | |||
| 313 | 347 | git tag -a v1.0.0 -F notes.md && git push --follow-tags | |
| 314 | 348 | ``` | |
| 315 | 349 | ||
| 350 | A workflow can build the release instead of a person attaching files by hand — see | ||
| 351 | [Releases built by CI](#releases-built-by-ci). | ||
| 352 | |||
| 316 | 353 | `/r/<repo>/releases` lists every tag and marks the lightweight ones, because a tag with | |
| 317 | 354 | no tagger has no notes to show. The release page carries the notes, the commits since the | |
| 318 | 355 | previous release, and two downloads: | |