Building Eventra · Part 6 of 102 min read

How Eventra's deploy pipeline took shape in 60 commits

  • buildinpublic
  • devops
  • docker
  • githubactions
git pushliveVerifylint, tests, build01Buildcontainer images02Deploymigrate, restart03Healthservice answers04

A deploy pipeline for a solo project gets built through iteration, and the git history shows it better than the final workflow file does. Across three stretches of work, about 60 commits turned a local build into a pipeline that tests, builds images, migrates the database and checks health on every push.

March 5: the first deploy

Until March 5, Eventra ran only on my machine. At 13:17 I committed "setup deploy": a Dockerfile, a compose file, a .dockerignore and a GitHub Actions workflow that builds the app and ships it to a server.

By 20:28 there were about twenty commits on the pipeline. A pipeline can only be tested by running it: push, wait for the runner, read the log, adjust, push again. Each of those cycles takes minutes, so the day went to getting the first full run green.

March 10 to 13: everything around the deploy

The second round covered what surrounds a deploy: pipeline fixes on the 10th, splitting out the public SDK repository, and on the 12th a day of health checks, redirects and a database connection fix. The connection issue was simple: I was pointing the service at the wrong database.

A green pipeline does not prove a working service. The container can start and the pipeline can pass while the app behind it is not ready, is not talking to the database, or is redirecting incorrectly. The health check turns "a process is running" into "the service answers", and from that point a deploy only counts when the check passes.

GREEN PIPELINEContainer started?App is ready?Database connected?Redirects correctWITH A HEALTH CHECKContainer startedApp is readyDatabase connectedRedirects correct
A green pipeline proves that the container started. The health check proves the service answers.

April 17: the server and the deploy order

On April 17 there were 28 commits between 19:32 and 00:44. When they were done, ci.yml had changed by about 150 lines, and docker-compose.prod.yml and the Dockerfile had been reworked. A large part of the evening was server setup: what has to be running before what, and the state the machine must be in before a deploy touches it.

The deploy now runs in a fixed order: prepare the environment, pull the new images, bring up the database and wait until it is ready, apply migrations, and only then start the application and wait for its health check.

The pipeline today

It has three jobs. verify runs lint, tests and the build. build creates the container images. deploy updates the server, migrates, restarts and checks health. Lint and build must pass before a deploy can start, which is tracked under stability on the roadmap.

A pipeline needs maintenance as its environment moves. On August 27 it needed an update for a dependency check and for a deprecation in the CI platform.

What I do now

I run each new deploy step by hand on the server first, and move it into the workflow only after it works. A command over SSH gives feedback in seconds. The same command inside a pipeline gives feedback after a push and a wait. For anything that touches the server, the fast loop comes first.