how i automated myself out of friday deploys

a love story between a person and a pipeline

$ cat the_bad_old_days.log

At a previous job, Friday was deploy day. Not because anyone chose it. It just sort of happened, the way bad habits do. And the deploy process was, to use the technical term, a disaster.

Picture it: me, four SSH sessions deep, copying files to servers by hand. One wrong scp and half the environment was running last week's build. There was a checklist. A physical checklist. On paper. I once watched a deploy fail because someone skipped step 14, and step 14 was "remember to restart the thing." The thing was not restarted.

Every Friday afternoon had the same vibe: quiet dread, cold coffee, and the soft click of a team collectively holding its breath. Deploys took hours. Rolling back took longer. I spent too many Friday evenings willing a dead service back to life.

$ vim spite.py

The turning point wasn't a grand vision. It was spite. One Friday, after copying the same config file to the same twelve servers for what felt like the thousandth time, I snapped and wrote a small Python script to do it for me. It was ugly. It had hardcoded hostnames. It worked.

So I kept going. A Bash wrapper here. A health check there. Each script was born the same way: something bored or annoyed me one too many times, so I murdered it with automation. Within a few months I had a scrappy little toolkit that could push a release in minutes instead of hours.

Here's roughly the energy of that era:

# deploy.sh, v1 - do not judge me, it was 2019 and I was tired
$ for host in $(cat servers.txt); do
    ssh $host "systemctl restart the-thing"
done && echo "friday saved"

Was it robust? No. But it turned a two-hour ritual into a two-minute command, and more importantly, it proved the point: the computers should be doing this part.

$ less pipeline.yml

Scrappy scripts have a ceiling, and I hit it. Servers multiplied. Environments multiplied. My beautiful hacky toolkit started creaking. So I built the grown-up version: a real pipeline.

GitLab CI became the backbone: every merge triggered tests, builds, and deployments without a human touching anything. Docker meant "works on my machine" stopped being a sentence anyone could say. Ansible handled configuration across the fleet, and later Terraform let me define infrastructure as code: reviewed, versioned, boring.

Boring is the highest compliment in this business, by the way. A boring deploy is a deploy nobody remembers.

The first time I watched a full release go from merge to production with zero manual steps, I just sat there. It felt like watching my Friday afternoon come back to life.

$ cat results.txt

The numbers, because numbers are fun when they're good: deployments got about 40% faster, and that's just wall-clock time. The real savings were everything around the deploy (the prep, the checklist, the collective anxiety, the post-deploy babysitting), all of which went from hours to roughly zero.

Eventually I was looking after 100+ servers, which sounds impressive until you realize the trick: I wasn't managing 100 servers. I was managing a handful of definitions, and the servers managed themselves.

And Friday afternoons? Peaceful. Genuinely, suspiciously peaceful. The kind of peaceful where you close the laptop at a reasonable hour and go outside like a person.

$ echo "the moral"

People frame automation as efficiency. I think that's wrong. Automation is a quality-of-life project. Every script I've ever written was really just me buying back my own time, one boring task at a time.

Start with spite. Start small. Hardcode the hostnames if you have to. The pipeline of your dreams begins as a hacky script you're slightly embarrassed by.

Mine certainly did.