|
All checks were successful
secrets-guard / encrypted (pull_request) Successful in 10s
PR build (required check) / changes (pull_request) Successful in 17s
shell-lint / shellcheck (pull_request) Successful in 14s
PR build (required check) / validate-observability (pull_request) Successful in 44s
PR build (required check) / build-frontend (pull_request) Successful in 2m13s
PR build (required check) / build-backend (pull_request) Successful in 2m31s
PR build (required check) / gate (pull_request) Successful in 3s
The four domain CLAUDE.md files still described the pre-monorepo split-repo topology, and several statements were the exact inverse of current reality: infra/CLAUDE.md told a reader that emi/thermograph is archived and must not be pointed at, when that is the live repo; backend/ and frontend/ both claimed there is no Makefile and no requirements-dev.txt when all four files exist; frontend/ described itself as one of four sibling repos; observability/ claimed a single unprotected main branch. These files are read before every change, so a stale one is a correctness problem rather than a documentation one. Rewritten against the tree: - Root CLAUDE.md now owns the cross-cutting truth once — branch model, the SERVICE + *_IMAGE_TAG deploy contract, image names, which orchestrator each environment runs, and that everything is a PR. Domain files carry only what differs and are capped at ~70 lines. - Records that prod runs Swarm from deploy/stack/thermograph-stack.yml while beta and LAN dev run compose, routed by /etc/thermograph/deploy-mode. - Documents the *-deploy-dev.yml workflows as inert rather than leaving a reader to discover it. Deletes infra/docker-stack.yml. It defined db/app/worker, matched nothing that deploys, and was referenced only by prose describing it as a future design record — while the real 8-service prod stack lives under deploy/stack/. A file that looks authoritative and affects nothing is the worst case for a reader asked to change the prod stack. infra/README.md claimed "compose in production today" and that Swarm was "not currently live"; corrected, and infra-sync.yml's existence is now recorded instead of "there is no separate infra deploy trigger". The compose file's timescale-pin comment now points at how deploy-stack.sh actually resolves the digest from the running container. |
||
|---|---|---|
| .. | ||
| .claude/skills/key-gaps | ||
| deploy | ||
| lake-iceberg | ||
| ops | ||
| terraform | ||
| .env.example | ||
| .gitignore | ||
| .sops.yaml | ||
| ACCESS.md | ||
| CLAUDE.md | ||
| DEPLOY-DEV.md | ||
| DEPLOY.md | ||
| docker-compose.dev.yml | ||
| docker-compose.openmeteo.yml | ||
| docker-compose.yml | ||
| Makefile | ||
| README.md | ||
infra/
Infrastructure for Thermograph: Terraform host
provisioning, the SOPS+age secrets vault, WireGuard/Swarm networking, Forgejo,
Caddy, mail, and the deploy scripts that run the already-built app images on each
host. This is a domain of the emi/thermograph monorepo — hosts' /opt/thermograph
is a checkout of the whole monorepo, and infra/ never builds app source; it only
runs published images.
terraform/— provisions/configures hosts (SSH-driven by default; an optional GCP-creating module is scaffolded, no live resources yet). Seeterraform/README.md. No tfstate is persisted anywhere — treatapplyas executable documentation, not a routine operation.deploy/secrets/— the git-native SOPS+age secrets vault (every app secret, encrypted at rest, rendered at deploy time). Seedeploy/secrets/README.md.deploy/swarm/,deploy/forgejo/— the WireGuard/Swarm cluster hosting Forgejo (git + CI + registry). SeeACCESS.md.deploy/deploy.sh— the single deploy entry point for beta and prod. TakesSERVICE=backend|frontend|allplusBACKEND_IMAGE_TAG/FRONTEND_IMAGE_TAG, resets the host checkout, renders secrets, and routes to the right orchestrator.deploy/stack/— the Swarm path, live on prod:thermograph-stack.yml(db, web, worker, lake, daemon, frontend, autoscaler, autoscaler-lake),deploy-stack.sh,autoscale.sh, and the LB. Rolling updates are start-first, health-gated, with auto-rollback.STACK_TEST=1rehearses the whole stack on throwaway volumes and ports.docker-compose*.yml— the compose path, live on beta and LAN dev (db, backend, lake, daemon, frontend).docker-compose.dev.ymlis the LAN overlay;docker-compose.openmeteo.ymlis the self-hosted Open-Meteo overlay.
Which path a host takes is decided by /etc/thermograph/deploy-mode: the string
stack makes deploy.sh exec deploy/stack/deploy-stack.sh; anything else is
compose. The workflows never need to know which mode a host runs.
Branches & how changes reach each environment
main— what prod and beta run.infra-sync.ymlfires on a push tomaintouchinginfra/**, fast-forwards each host's/opt/thermographcheckout and re-renders/etc/thermograph.envfrom the vault. It deliberately does not roll any service: image tags are the app domains' axis, not infra's. A compose or stack change that must recreate containers takes effect on the next app deploy, or a by-handSERVICE=all … deploy/deploy.sh.dev— what LAN dev would run viadeploy/deploy-dev.sh. The CI trigger for this is currently inert (the LAN box still holds a split-era checkout); usemake dev-uplocally.release— consumed by app deploys only. Both hosts track infra viamain; prod's app images are staged byrelease, but its checkout followsmain.
Note the asymmetry with the app domains: app code IS environment-staged
(dev→main→release maps to LAN→beta→prod via image tags); infra is not.