Thermograph monorepo: graded-climate API + SSR frontend + infra, domain-specific containerized deploys
Find a file
Emi Griffith f1664bc0f5
All checks were successful
shell-lint / shellcheck (pull_request) Successful in 7s
PR build (required check) / build-frontend (pull_request) Has been skipped
PR build (required check) / validate-observability (pull_request) Successful in 22s
PR build (required check) / gate (pull_request) Successful in 2s
PR build (required check) / changes (pull_request) Successful in 6s
secrets-guard / encrypted (pull_request) Successful in 5s
PR build (required check) / build-backend (pull_request) Has been skipped
runbook: spell out that the CI secrets must exist before the merge
infra-sync fires on any push to dev/main touching infra/**, which this change
does heavily. Without VPS1_SSH_*/VPS2_SSH_* those jobs SSH to an empty host and
fail; sync-beta also targets a checkout that does not exist until step 1.
Nothing is damaged (the jobs only fetch and render) but the red run reads like
an outage. Also records that the app Deploy workflow does NOT fire here, being
path-filtered to backend/** and frontend/**.
2026-07-25 15:03:29 -07:00
.claude infra: split the estate into vps1/vps2, moving beta next to prod and dev onto vps1 2026-07-25 15:01:29 -07:00
.forgejo/workflows infra: split the estate into vps1/vps2, moving beta next to prod and dev onto vps1 2026-07-25 15:01:29 -07:00
backend frontend: fix the three inconsistencies the onboarding guide found (#99) 2026-07-25 21:11:32 +00:00
docs/onboarding infra: split the estate into vps1/vps2, moving beta next to prod and dev onto vps1 2026-07-25 15:01:29 -07:00
frontend frontend: fix the three inconsistencies the onboarding guide found (#99) 2026-07-25 21:11:32 +00:00
infra runbook: spell out that the CI secrets must exist before the merge 2026-07-25 15:03:29 -07:00
observability infra: split the estate into vps1/vps2, moving beta next to prod and dev onto vps1 2026-07-25 15:01:29 -07:00
.gitignore Drop accidentally-committed worktrees; ignore .claude/worktrees 2026-07-24 15:57:34 -07:00
CLAUDE.md infra: split the estate into vps1/vps2, moving beta next to prod and dev onto vps1 2026-07-25 15:01:29 -07:00
CUTOVER-NOTES.md infra: split the estate into vps1/vps2, moving beta next to prod and dev onto vps1 2026-07-25 15:01:29 -07:00
README.md infra: split the estate into vps1/vps2, moving beta next to prod and dev onto vps1 2026-07-25 15:01:29 -07:00

thermograph

The Thermograph monorepo — the split repos reunified (2026-07-22) with full history via subtree merges, while keeping everything the split was actually for: per-domain images, per-domain deploys, and an async FE/BE contract.

Domains

Dir What CI
backend/ FastAPI graded-climate API, accounts, notifications (Discord bot, push, mail), data pipeline build-push → image emi/thermograph/backend; deploy
frontend/ Public client: static JS/CSS + SSR pages same build-push / deploy workflows, matrixed by domain; image emi/thermograph/frontend
infra/ Compose (dev, on vps1) + two Swarm stacks co-resident on vps2 (beta, prod), deploy scripts, terraform, SOPS secrets vault, ops cron infra-sync (host checkout + secrets render), secrets-guard, ops-cron
observability/ Loki + Grafana + Alloy stack observability-validate

thermograph-docs deliberately stays its own repo (ADRs + runbooks, no build artifacts, different change cadence).

New here?

docs/onboarding/ is the developer onboarding path: orientation, verified local-setup recipes, a per-domain deep dive, the cross-service contracts that break silently, the release flow, and a list of which docs in this repo are currently stale.

How CI stays decoupled

Every workflow in .forgejo/workflows/ is path-filtered to its domain: a push touching only frontend/** builds/deploys nothing else. Images stay separate (emi/thermograph/backend, emi/thermograph/frontend, each tagged sha-<12hex>), deploys stay per-service (infra/deploy/deploy.sh SERVICE=backend|frontend|all), and the API version contract (GET /api/version, PAYLOAD_VER) still lets FE and BE ship out of lockstep. The one intentionally coupled piece is pr-build.yml: a single always-running gate required check that builds only the domains a PR touches (a path-filtered required check would deadlock auto-merge).

Branch model (unchanged from the split era): PRs → dev, main → beta, release → prod. Infra isn't environment-staged the same way app images are: beta's and prod's checkouts (both on vps2) track main; dev's checkout (on vps1) tracks dev itself, since it's the one environment that isn't a rehearsal for something downstream.

Before pointing anything live at this repo, read CUTOVER-NOTES.md.