@[TechFace] Honestly the “what’s actually deployed where?” problem is what pushed me away from trying to make CI/CD feel “perfect" and toward making it painfully obvious instead.
Right now my setup is intentionally boring.
Every deployment creates a tiny release manifest on the server itself:
git commit hash
deployment timestamps
branch/tag
who triggered it
previous release references
For now, it's just a flat file + symlink structure I can inspect in 5 seconds over SSH without opening a dashboard or clicking through three different SaaS products.
I learned the hard way that during incidents.. People seem to want:
“what changed?”
“when did it change?”
“how do we undo it?”
So my deploys basically work like this:
CI builds and validates artifacts
artifacts get versioned
deployment script pulls a specific artifact/version
current release becomes a symlink
previous release stays intact
That last part saved me multiple times. One bad nginx config and rollback becomes changing a symlink back + restarting a service instead of rebuilding/redeploying/re-praying.
For coordinating environments, I stopped trying to fully automate promotion chains because they became harder to reason about than the app itself. Staging and production are explicit actions now. Humans choose when prod changes. Especially after I had a deployment start while I was actively debugging another issue once. That was a special kind of misery.
I know some people hear “bash deployment scripts” and think duct tape, but honestly I trust 200 lines of readable bash more than 2,000 lines of abstracted YAML magic hidden behind marketplace actions I didn’t write.
The funny part is the older I get, the more I optimize for:
“Can sleep-deprived me understand this at 2am?”
If the answer is yes, it’s probably a good deployment system.
Cheers! <3