Publish release images on v* tags; production deploys from iac-repo (#154) #159
No reviewers
Labels
No labels
area:ai
area:ci-cd
area:notifications
area:observability
area:public-pages
backlog
bug
duplicate
enhancement
help wanted
invalid
question
type:decision
type:feature
type:infra
type:maintenance
type:security
v1.0.1
v1.1.0
v1.2.0
v1.3.0
v2.0.0
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/WeatherBot!159
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/release-image-publish"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #154. Companion to Rhoving/iac-repo#220, which adds the Ansible role that consumes these images. Merge order between the two no longer matters — this workflow no longer invokes the play.
Problem
CD runs on every push to
mainand deploys the dev host. Nothing deployed production at all; it was a manual procedure someone had to remember. It sat six days and five alert-correctness fixes behind while four consecutive CD runs went green — because a green CD run reads as "shipped" when it only ever meant "dev is current".Change
release.yml: av*tag builds and pushesgit.rhoving.com/rbrooks/weatherbot:<version>— and that is all. Deployment is an operator step in iac-repo:git tag v1.7.1 && git push origin v1.7.1→ image publishedweatherbot_imageininventory/group_vars/weatherbot/vars.yml(PR)ansible-playbook site.yml -l docker-host(fromweatherbot-ansible/)Why no deploy job (revised from the first version of this PR): deploying from CI needs
PROD_SSH_KEY+ANSIBLE_VAULT_PASSWORDin Actions secrets — root-equivalent access todocker-host, exposed to anything that can push a tag or compromise a runner. Publish-only leaves CI holding apackage:writetoken; the worst case is a poisoned image that still has to get past the operator bumping the pin and running the play.This also settles the open design question from the first revision (
-e weatherbot_image=<tag>leaving the committed pin stale): with deploys operator-run, the committed pin in iac-repo is the deployed state. Git stays authoritative, matching the fleet convention.Watchtower was considered and rejected — no health-gated rollback while Alembic migrations run in the startup lifespan; full rationale on #154.
Details worth reviewing
APP_VERSIONis baked in at build time rather than derived fromgit describeon the deploy host. That is what lets production stop keeping a git checkout entirely — and removes the root-owned-git-objects problem the manual recipe had to work around.No
:latesttag. The fleet pins exact versions in Ansiblegroup_vars(iac-repo's "never use latest" rule), and a moving tag is precisely what makes "which version is production actually running?" unanswerable.The push gates on its secret and skips cleanly when unset, matching how
cd.ymlgates onDEV_SSH_KEY. Safe to merge before the secret exists. Required, one-time, in Settings → Actions:REGISTRY_TOKENpackage:writecd.ymlis renamed "CD (dev only)" and says so in its header. That was the other half of #154 — the hazard was never that CD was broken, only that its name implied more than it did.Verification
Both workflow files parse (
yaml.safe_load, jobs enumerated). An un-configured run builds the image (keeping the Dockerfile honest) and skips the push with a log line rather than failing.Note on rollback scope
The play's automatic rollback restores the previous image, not the previous schema. Migrations are forward-only, so a release whose migration ran before the app failed its health check needs a database restore, not just a re-deploy. Documented in the README alongside the pipeline table — and iac-repo#220 adds the nightly
pg_dumpthat makes such a restore possible at all, which production did not previously have.🤖 Generated with Claude Code
Deploy production on release tags, not on merge (#154)to Publish release images on v* tags; production deploys from iac-repo (#154)