skip to content
Jobs

Gantry Builds Its Own Releases

Replacing the GitHub Actions release pipeline with one local, self-verifying command.

Gantry milestones
Replacing the GitHub Actions release pipeline with one local, self-verifying command.

Gantry used to ship the way many projects do: push a version tag, let GitHub Actions build the binaries for several targets, and re-host the artifacts for download. This job replaced that whole arrangement with a single command you run on your own machine. `scripts/release/build-local-release.sh` builds every file a Gantry release ships — the Linux binaries, the installer, the source-review archive, the software bill of materials, the checksums and their signature — lays them out in exactly the shape the website's download page expects, and then checks its own output before it exits: it re-verifies every checksum and the signature and refuses to finish if anything is wrong. Alongside the producer, the job rewrote Gantry's documentation to describe the real acquisition path — download your build from your license page, verify it locally — and deleted the GitHub Actions workflow, the cargo-dist configuration, and every claim that a GitHub Release still exists.

Build

The work split into three pieces in a forced order: build the replacement command first, correct the documentation second, retire the old machinery last — each piece placed so it could stand on the one before it.

The producer landed first because everything else depended on it existing. The documentation could only describe a real command once there was one, and the retirement piece could only delete the old pipeline once its replacement was present and covered by a test. The brief names it the load-bearing deliverable, and builds it to reuse the existing source-archive script verbatim rather than reimplement source archiving.

The documentation pass sat in the middle and was scoped to touch no code — only to remove the false GitHub-Release framing and state the website model. That placement was not cosmetic: the final piece adds a test asserting that no live GitHub-release download URL survives in the primary docs, so the docs had to be clean before that assertion could be both honest and passing. Splitting them this way kept each change small and each gate meaningful.

The concentrated difficulty was in the last piece, and the plan fused two jobs into it deliberately: deleting the configuration and rewriting the tests that pinned the old shape. The reason is stated in the brief — the tests cross-check the configuration against itself and against each other, so removing a configuration fact without moving its test in the same change turns the gate red. It could not be two pieces. The run stayed green across all three; the difficulty here was dissolved by drawing the boundary around the config-and-tests pair instead of through it, and the clean gate is what that choice bought.

Feature

Before this job, releasing Gantry meant a tagged commit triggering CI to build and re-host artifacts across several targets. After it, one local command produces the shipped set and proves it, and the CI release path no longer exists.

The old model is legible in what the job deleted: a GitHub Actions workflow that built several targets including two macOS variants, signed and notarized them, generated a pipe-to-shell installer, and assembled the release. A reader was told to expect a GitHub Release and to fetch re-hosted CI artifacts. None of that is true now — the workflow file is gone from the tree, leaving only the unrelated license-compliance workflow beside it.

In its place stands `scripts/release/build-local-release.sh`, still present and since grown at today's `HEAD`. It runs a preflight that fails loudly and names each missing prerequisite, refuses to write a partial output when the signing key is absent or still the placeholder, builds only the two Linux musl targets, and finishes by re-verifying the checksums and signature inside the output directory so a broken release cannot reach a customer. The version-check module was kept but made honest: it is still an inert stub that returns nothing, but its documentation now points at the website's version manifest as the future source of truth rather than a GitHub Releases API.

Some of what the job left has since moved. The README sections it rewrote have been rewritten again since, so its introduced lines there are no longer present. The standalone contract-test files it added were folded into a single integration test harness rather than living as separate files — the producer and retirement assertions are still there under `tests/integration/`, not removed. The producer script, the deleted workflow, and the honest version-check stub all still hold.

unavailable sessions
unavailable context
61,868 in / 120,090 out tokens
$16.71 cost
0 x 3 milestones x sprints
unavailable edits
unavailable commands
52m duration
3 execute · 3 review · 2 plan · 1 gate-build roles
0 x 0 fixes x replans
- harness