Back to Ideas 4 min read

Run It by Hand Until It Is Boring

E
EkoHacks Team
·
Run It by Hand Until It Is Boring

Encoding the release, part 1 of 8.

We are a small distributed team shipping open source to npm, with strict TDD and trunk-based development. Like every team, we have operations we repeat: releasing, keeping docs in step with the code, setting up a new package. And like every team, we felt the pull to automate them immediately.

We have a rule that resists that pull: every repeated operation gets written down first, run by hand until it is boring, and only then encoded.

Releasing EkoLite is the first operation to make the whole journey. It started as a document, RELEASING.md: branch release/vX.Y.Z off main, bump the version, write the changelog entry, open a PR, let CI go green, merge; cut a GitHub Release; approve the deployment gate; let the workflow publish to npm with OIDC trusted publishing, so no token ever leaves anyone's machine. Two human decisions, and the machines do the rest.

We ran that document by hand for several releases. That period was not wasted time — it was the requirements phase. Running it by hand told us which steps needed judgement (writing the changelog entry, approving the gate) and which were pure rail (everything else). It told us where mistakes actually happen: a mirror registry quietly rewriting lockfile URLs, a changelog entry forgotten until the Release notes were due. You cannot design good checks for a process you have not felt fail.

When the document was boring, we encoded it: ekohacks release <version>, a command in our operations CLI. The name of the game is that the document is the spec. The command does not do anything the manual process does not do. Its preflight is the document's "Before cutting" checklist, line for line. When we discover the process needs a new step — and part 6 of this series is about the day we did — the rule is: the process changes in RELEASING.md first, by hand, then in the tool. The document leads; the command mirrors it.

This ordering sounds bureaucratic and is the opposite. Automation that grows ahead of the process it automates becomes the process, silently, and nobody can say why it does what it does. Automation that trails a living document can always answer the question "why does the tool insist on this?" with a sentence a human wrote down after a bad afternoon.

The rest of this series is the story of building that command: how a failing test became our review artefact, how you test "wait for CI, then merge" without a CI in sight, which one decision we refused to automate — and what the first real release taught us that no test could have.

Next: The Failing Test Is the Review.

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