Back to Ideas 6 min read

What One Real Release Taught Us in an Afternoon

E
EkoHacks Team
·
What One Real Release Taught Us in an Afternoon

Encoding the release, part 7 of 8.

Part 3 ended with a promissory note: our nulls fake the shapes of GitHub's answers but never its behaviour, so the real side of the gh wrapper would be proven by a real release rather than a faked GitHub. This is the afternoon the bill arrived. It cost two crashes and one near-miss, and it was the cheapest education we have ever bought.

Crash one: the race we had never met. The second run of ekohacks release 0.4.1 sailed through preflight, branched, bumped, pushed, opened PR #198 — and died:

Error: gh pr checks 198 failed:
no checks reported on the 'release/v0.4.1' branch

In the seconds between a PR opening and CI registering its checks, gh pr checks exits non-zero with "no checks reported". Our code treated any such failure as fatal. No test caught this because every test ran against our null — and we would never have thought to fake an error message we did not know existed. A hand-written fake GitHub would have encoded exactly the same ignorance and then certified it. Testing against a fake you wrote yourself proves only that you agree with yourself; reality is the only oracle for the boundary. The fix: "no checks reported" parses as an empty round, not an error.

The near-miss inside the crash. Fixing it exposed something worse. Had checks() quietly returned an empty list there, the cut policy considered zero checks "all concluded" — and would have merged the release PR before CI ever started. The crash, embarrassing as it was, had been standing guard over an insta-merge. Both fixes landed red-first: cut now waits while no checks are reported, pinned by a test that walks empty → green → merge.

Crash two: the human did a human thing. With PR #198 finished by hand, the operator did the natural thing — ran the whole command again. It crashed again:

fatal: a branch named 'release/v0.4.1' already exists

Why? The rail has no memory. The first attempt's local branch was still sitting there; the re-run started from the beginning, tried to create it again, and git — correctly — refused to overwrite the record of the earlier attempt. Preflight could not warn anyone, because every one of its checks was genuinely true: it verifies "is this a good place to start a release?", and has no concept of "this release is already half-done". Nothing about the release was broken. The stop protected the state. It just said so in the worst possible language: a stack trace.

That is the deepest lesson of the three. Our stories had promised that every stop condition "stops the rail with a named reason", which makes a raw stack trace not a cosmetic flaw but a specification violation. People re-run failed commands — twice, in our sample of one afternoon — so the failure mode of a stopped rail is not an edge case, it is the primary interface of a bad day. Cut now answers in its own voice:

stopped: branch release/v0.4.1 already exists from an earlier cut

We kept the no-resume design. Clean named stops plus standalone stages-as-recovery is still a better bargain than resume logic that must correctly diagnose every partial state. But we no longer believe the design is done when the happy path is; it is done when every way it stops has a name.

Three lessons, one afternoon, all found within minutes of touching reality — precisely because we had refused to fake it.

Next: The Release Is the Acceptance Test, which is still being written.

E

Written by

EkoHacks Team

More from Ideas

·6 min read

What the Nullable Gave Back

One file, seven behaviours held fixed, the database swapped for a Nullable: about 180 times less time inside the tests, and coverage flat to two decimals.

E
EkoHacks Team
·6 min read

Twenty Six More Tests, Four Fewer Behaviours

Removing the mocks grew the suite from 44 tests to 70 and quietly deleted four behaviours, every one of them a failure path. Test count is not coverage.

E
EkoHacks Team
·6 min read

The Best Coverage Number in the Room

Same commit, same spec, same test count. The mocked suite ran 5.6 times faster, covered 3.5 fewer points of real code, and posted the best branch coverage.

E
EkoHacks Team