Faragiri

Learn ShippingCode

Tomas overwrote a working deploy on a Friday and the previous version existed nowhere. The shop counted screws by hand until Monday.

5Sections
5Min read
2Depth

The subject nobody announced

None of these turns on its own, which is why learning one at a time fails

There is no first one here. Each is nearly useless without the other two, and that is why the whole subject arrives at once and feels like a wall.

  • The history
  • The build from nothing
  • The evidence
  • The historyCommits and branches. Without it there is no previous version to go back to.
  • The build from nothingA declared environment. Without it the history records code that only runs on one laptop.
  • The evidenceTests. Without them the other two move fast and nobody can say whether anything still works.

The teeth are the same size because none of the three is the big wheel. What the figure leaves out is that they are usually adopted in the wrong order, and the automation is bolted on before any of them.

Tomas Lind deployed the stock checker for a hardware shop in Umea by copying a folder over SSH, which worked for eight months. On a Friday afternoon he copied a version that could not read the previous week's stock file, and discovered that the previous version no longer existed anywhere. He had overwritten it. The shop counted screws by hand until Monday.

Nothing in that story is about writing code, and everything in it is this topic. Shipping is the set of practices that make a change reversible, repeatable and inspectable by somebody who is not you, and it is the subject the pillar brief calls the one nobody told you was a subject.

Reversible first

The property that would have saved Tomas's weekend is not testing and it is not containers. It is that a rollback is a deploy of the previous version, and it has to be as easy. If going back is a different procedure from going forward, it will be improvised at the worst possible moment by the most frightened person available. Deployment done properly is a switch between versions that both still exist, and the previous one is kept precisely so that the answer to a bad Friday is a command rather than an evening.

The same idea, one layer down, is why history is kept at all. Two commands undo things and they are not interchangeable: git revert makes a new commit; git reset moves the branch. Revert is the one that is safe on anything anybody else has, because it adds a change that undoes a change and leaves the record of both. Reset rewrites what the branch points at, which is the right tool on work nobody has seen and a way of destroying a colleague's afternoon on work they have. That distinction is the practical half of the history of a project, and working in parallel.

The machine that has nothing

Tomas's deploy worked because his laptop had accumulated eight months of small adjustments: a library installed once, an environment variable set in a shell profile, a folder that happened to exist. None of it was written down, and none of it was on the shop's server until he put it there by hand.

The pipeline runs on a machine that has nothing, which is what makes it honest. A build server starts from an empty box every time, so anything the project needs has to be declared somewhere a file can record it. That is the actual value of the machine that builds and releases for you, and it is worth more than the automation: it is a continuous, unforgiving audit of whether the project can be built by somebody who is not its author.

The same instinct, taken one step further, produces the container. A container image is the dependencies, the runtime and the code in one file, built once and run identically wherever it lands. It removes the whole class of fault where the server has a different version of something from the laptop, which is what shipping the environment along with the code is for. What it does not remove is the requirement to know what went into the image: a container built from an unpinned base is the same undeclared dependency as before, sealed in a box and shipped with more confidence.

Evidence, and what it is actually for

The argument for tests that persuades people is not that they catch bugs, because a beginner reasonably observes that they mostly catch bugs the author was already thinking about. The argument that holds is that tests are what make a change safe to make. Tomas can rewrite the stock parser on a Tuesday with confidence in proportion to how much of its behaviour is written down as something a machine checks.

That is why evidence that it works, that survives your next change is phrased around survival rather than correctness. A test suite is a description of what the program is supposed to do, kept in a form that complains when the description stops being true, and its value arrives months after it is written, on the day somebody edits a file they do not fully understand.

The useful first test is not a unit test. It is the one that runs the whole thing on last week's stock file and checks the total, because that is the failure Tomas actually had, and because a test written against a real past input needs no theory about what the units are. The elaborate structure can come later, and for most small projects it never needs to.

Friday afternoon

What each layer stops, and what it hands straight through

Four layers between a change and a shop counting screws by hand, and each one is transparent to the fault the next one catches.

  1. The test suiteBehaviour that used to work and now does notAnything nobody thought to describe, and every environment difference
  2. The build from nothingThe undeclared library and the variable set in a shell profileCode that is wrong in a way that builds perfectly
  3. The containerThe server and the laptop disagreeing about a versionA bad change, faithfully and identically, everywhere
  4. The kept previous versionEverything the other three let past, for as long as it takes to noticeNothing, and it is the layer that gets deleted to save disk
One change, going out

The seal is the noticing, and it is not a layer here. All four assume somebody finds out, and Tomas found out because a shop rang him.

The order, and the stall

None of this is the language, and that is the point of putting it inside programming, from the first variable to a deployed system rather than beside it. The order that works is version control, then a way of running the thing from nothing, then tests, then automating the release. Almost everybody does the fourth first, because it is the one with the interesting tooling, and ends up with a pipeline that automates a deployment nobody can reverse.

The stall is the one the pillar brief names, and it arrives immediately after the first program that works. Syntax made sense, the terminal does not, git is four concepts pretending to be one, the deployment target has its own vocabulary, and somebody concludes they are bad at programming. They are not. They have hit a second subject with no announcement, and the specific evidence for that is that none of the difficulty is about the language they just learned.

What to open, in 2026

Git is not optional and has not been since it took over from Subversion during the 2010s. It is free, and the single highest value hour on this topic is the one spent understanding that a commit is a snapshot and a branch is a pointer to one, after which most of the confusion resolves itself.

GitHub Actions is the default pipeline for projects already on GitHub, is free for public repositories, and replaced Jenkins for most small teams, which is what tutorials older than about 2019 still assume. Docker remains the way containers are built and is free for individual use. For the last step, in putting it somewhere the public can reach, the platforms that deploy a repository on push replaced the folder copy Tomas was doing, and they replaced it specifically by keeping the previous build.

A coding assistant writes a passable pipeline file immediately and is confidently wrong about credentials and permissions, which is the part where being wrong is expensive rather than annoying. What none of this covers is what happens after the deploy, when the thing is running and somebody has to notice that it has stopped.

Alongside this

Above this