deploy: nothing syncs deploy/compose.yaml to the hosts — both are a month stale, and #117's worker split isn't deployed anywhere #155
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
deploy/compose.yamlis described in CLAUDE.md as "the source of truth for that compose file", but there is no mechanism that gets it onto a host. It was hand-copied once at cutover and has not moved since.Current state
workerBoth hosts run the pre-#117 file. So the worker split — the whole point of #117 — is not in effect on either host:
RUN_WORKERS_IN_APIis unset, the image defaults it totrue, and background jobs still run inside the API process. That is a working configuration, just not the one the repo anddeploy/README.mddescribe, and nobody would notice from either side.The same gap is what makes #152 a no-op in practice: the restart-policy flip is now correct in the repo, and neither host will ever see it.
Discovered while diagnosing the prod outage (Rhoving/iac-repo#318) — separate root cause, same underlying "the deployed artifact drifts from the repo silently" shape.
Why the image pipeline doesn't cover this
Watchtower swaps images, not topology.
deploy/README.mdis explicit about it: "an image auto-update alone never changes topology". Anything expressed in the compose file — a new service, an env var, a restart policy, a port, a volume — needs the file itself to move. Today that means someone remembering toscpit, on two hosts, with no signal when they forget.Options
A. Ansible-managed, like the manifest (recommended)
Add a
tealeavesrole (or extenddocker-host-ansible) that templatescompose.yamlinto~/tealeaves-deploy/on both hosts from the repo, withTEALEAVES_CHANNEL/APP_PORTas host vars, anddocker compose up -don change. Pros: same mechanism, same review path and drift-detection asstaggered-stacksitself — and iac-repo#318 is about to touch that role anyway, so the two land together..envstays hand-managed (secrets). Cons: a TeaLeaves change now needs an iac-repo run to reach the hosts; the two repos have to stay in step.B. CI publishes the compose file as a release asset; host pulls it
release-images.ymlattachescompose.yamlto each release; a small host-side unit fetches the one matching its channel beforecompose up. Pros: keeps the file's lifecycle attached to the release that needs it, so "this version needs a new service" travels with the version. Cons: new host-side machinery, and it races Watchtower — the image can land before the compose file does.C. Make the hosts pull the repo
git clonethe repo to each host,git pullin a timer, run compose fromdeploy/. Pros: trivially correct, no new tooling. Cons: puts a source checkout back on the hosts — which is precisely what caused iac-repo#318. Recommend against.D. Do nothing; document the manual step
Add a "when you change
deploy/compose.yaml, copy it to both hosts" line to the post-phase checklist. Honest and free, but it is the process we already have, and it has already failed once for a month.Whichever way this goes, a drift check is worth having independently: compare the deployed file against the repo's and report. That is a smaller piece of work than any of the above and would have caught this in July.
Immediate, regardless of option
deploy/compose.yamlto~/tealeaves-deploy/on both hosts and re-up, so #152 and #117 are actually deployedRefs #152, #117, #134, Rhoving/iac-repo#318
restart: on-failurein the compose file —unless-stoppedbypasses docker-host's boot pacing #152Option A (Ansible-managed) chosen and implemented.
8cd5ad5—deploy/compose.yamldeleted,deploy/README.mdrewritten to document the split,CLAUDE.md's post-phase checklist and release steps updated. Keeping a copy here would have relocated the drift rather than fixed it, so there is now exactly one place the deployed topology exists.tealeaves-ansible/project renderingcompose.yaml+.envinto/opt/tealeaves-svcon both hosts. Open for review; not merged, and no playbook has been run against either host.One decision worth recording here because it changes this repo's release process: prod no longer auto-deploys. It runs an image tag pinned in iac-repo's
group_varsand moves on an explicit playbook run that pulls, snapshots the database and gates on/health. Dev keeps the:betaWatchtower loop. Shipping a release is now tag here → bump the pin there →ansible-playbook site.yml -l docker-host.That is a direct response to what this issue turned up: the auto-deploy prod was supposed to have never actually reached its api/app containers (Rhoving/iac-repo#318), so "prod is current" was an assumption nothing checked. A pinned tag plus a health-gated run makes it a question with an answer.
The drift check floated in the original write-up is now unnecessary for the compose file — there is only one copy — but the same reasoning still applies to the
.env, which remains hand-managed for secrets.Leaving this open until #319 merges and both hosts have actually been cut over.
unhealthy— it inherits the API image's HTTP healthcheck but serves no HTTP #156Deployed — both hosts cut over, verified
Rhoving/iac-repo#319merged and the play has been run against both hosts.Every item this issue raised is resolved:
docker compose lsshows a singlecompose.yamlper project — the split-stack state from Rhoving/iac-repo#318 is gone.workerservice is deployed for the first time (5 containers on prod, 6 on dev — the difference is dev's Watchtower, by design).on-failureis live, on the file the boot path actually reads.Closing.
One thing the cutover surfaced, filed as #156: the
workercontainer is permanentlyunhealthyon both hosts. It runs the API image with a different command and so inherits that image's HTTP healthcheck, but serves no HTTP. The worker is functioning correctly — 11 workers up, nightly purge ran — so it is a false negative, not an outage. It was invisible until now precisely because of this issue: the worker container had never actually run anywhere.