## Summary
- Closes#47.
- Register `disney_hotel_service` (`DisneyHotel/disney_hotel_service`, branch `master`) for beta and prod on all five webservers.
- Prod port **8023**, beta port **8024** (8021/8022 stay WordPress `relawfirm`). Alert worker profile only on adama.
- Document Postgres databases `disney_hotel_service` / `disney_hotel_service_beta`, NPM hosts, and the control-node secret layout. This app reads `POSTGRES_*`, not `DATABASE_URL`.
## Test plan
- [ ] `disney_hotel_service` is in `app_catalog` and `./scripts/deploy.sh --help` lists it
- [ ] All five hosts have prod **8023** and beta **8024**; only adama sets `compose_profiles: [worker]`
- [ ] After merge (ops): create both databases on `10.0.0.230` and grant `westfarn`
- [ ] After merge (ops): write `~/Documents/secrets/disney_hotel_service/disney_hotel_service_{prod,beta}.env` (mode 600)
- [ ] After merge (ops): NPM `disneyhotel.app` (+ www) → `:8023`, `beta.disneyhotel.app` → `:8024`
- [ ] Deploy waits on `docker-compose.prod.yml` in the app repo (no bundled db, `${WEB_PORT}:8000`, worker profile `worker`)
Reviewed-on: #48
## Summary
- Closes [#27](#27).
- Register `print_forge` in `app_catalog` (`type: django`, repo `ai_ml_operations/print_forge`, default branch `master`).
- Add `host_apps` prod `:8007` / beta `:8019` on **adama**, **roslin**, **starbuck**, **apollo**, and **ai-server-4080**.
- dj-queue **worker singleton on adama** only (`compose_profiles: [worker]`); other hosts web-only.
- Document ports, NPM hosts, Postgres DBs, secrets, Nominatim (`10.0.0.128:8089`), and the app-repo companion ([print_forge#1](ai_ml_operations/print_forge#1)).
- Update `scripts/deploy.sh` `--app` help.
- Move unused `abc_be` prod port reserve **8007 → 8009** so it does not collide with `print_forge`.
## Test plan
- [ ] Confirm `print_forge` appears in `app_catalog` and `--app print_forge` is listed in `deploy.sh --help`
- [ ] Confirm beta `host_apps` on all five hosts (port **8019**); adama has `compose_profiles: [worker]`
- [ ] Confirm prod port **8007** reserved on those hosts (no NPM until launch)
- [ ] After merge (ops, not this PR): create Postgres DBs `print_forge_beta` + `print_forge` on `10.0.0.230`, grant `westfarn`
- [ ] After merge (ops): write `~/Documents/secrets/print_forge/print_forge_{beta,prod}.env` from app `.env.prod.example`; add `print_forge:<token>` to `SHORTENER_API_TOKENS` (beta first)
- [ ] After merge (ops): NPM `print-forge-preview.aimloperations.com` → `:8019` active/active; do **not** NPM-route `printforgeprints.com` until launch
- [ ] After secrets + DBs: `~/Documents/repos/server-infra/scripts/deploy.sh --app print_forge --env beta --ref master` and hit `/healthz/`
Reviewed-on: #28
## Summary
The django deploy sets `COMPOSE_PROFILES` on the **start** step but not on the **build** step, so `docker compose build` skips profile-gated services. `up -d` then reuses whatever image already exists and the container silently keeps running old code.
This adds `COMPOSE_PROFILES` to the build step so it matches the start step. Only affects hosts that set `host_apps.compose_profiles` (today: the `monica_site` dj-queue worker on adama).
## Symptom this fixes
On adama the beta worker image was 20 hours stale while web was current:
| Image | Built | Postgres driver |
|---|---|---|
| `monica_site_beta-web` | today | psycopg 3.3.4 |
| `monica_site_beta-worker` | Aug 8 | psycopg2 2.9.12 |
So the worker crash-looped on LISTEN/NOTIFY (`TypeError: 'list' object is not callable` in `dj_queue/runtime/notify.py`) long after `monica_site` had moved to psycopg3, because its image was never rebuilt.
Branch is merged up with `master`, which already carries the worker auto-start from [#18](#18); the diff here is just the build step.
## Test plan
- [x] Manual `COMPOSE_PROFILES=worker docker compose build worker` on adama produced an image with psycopg 3.3.4 and the notify errors stopped.
- [ ] Beta deploy from this branch recreates the worker with a fresh image, no manual rebuild.
- [ ] Hosts without `compose_profiles` (roslin, ai-server-4080) still build/start web only.Reviewed-on: #19
ai-server-4080 runs dta_service active/active with adama and roslin.
Disable beta_dta_wsgi/prod_dta_wsgi so port 8001/8011 are free for compose.
Co-authored-by: Cursor <cursoragent@cursor.com>