docs(rx-server): plano de padronização Build Once/Promote (peças em dev, build local validado)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Deploy Agent
2026-06-18 02:36:29 +02:00
parent ccc96c6c9f
commit 114b106503
@@ -0,0 +1,36 @@
# rx.scoreodonto.com (server) — Plano de deploy (padronização Build Once → Promote → Deploy)
> Delta deste projeto. Modelo universal em `../../deploy/`. Aqui o que **difere**: é um app web
> monolítico (Express serve o React `dist/` + `/api` + `/updates/` do auto-update dos clients).
> O **client.exe** é outro projeto (ver `../rx.scoreodonto.com-client/`).
## O que torna este projeto diferente
- **App único** (`dental-server`): Express serve o front React (Vite, buildado no `dist/`), a API e o
diretório **`/updates/`** (auto-update dos clients — volume `dental-server/updates`, **não pode quebrar**).
- **Banco**: Postgres `dental_images` + Redis em 10.99.0.3. Migrações no boot.
- Frontend **não tem imagem própria** (como no scoreodonto): o React é buildado como **step do CI**
antes do `docker build` (o `Dockerfile` atual espera o `dist/` pronto — mantido p/ menor risco).
## Estado ANTES (modelo antigo)
- **webhook 9003** (VPS4) → `deploy-prod.sh`: build na VPS4 → `docker save`/`gzip`/`rsync``docker load`+`up` na VPS1.
- Imagem sempre `:latest`; **bump automático** de PATCH (`update-version.js`). Sem registry, sem build-once, sem promote.
## Plano (modelo da stack)
| Fase | O que | Status |
|---|---|---|
| 1 | `/api/health` + `/api/version` + **badge** no canto (lê `/api/health`) | ✅ (em dev) |
| 2 | `/api/health` usa **APP_VERSION** (tag) em runtime, fallback `version.txt` | ✅ (em dev) |
| 3 | **CI** `.gitea/workflows/build.yml`: push→build `rx-scoreodonto:<sha>` no registry; tag→promote (digest) + deploy | 🧪 build local validado |
| 4 | `docker-compose.prod.yml` (`image:` do registry, `up --no-build`, `APP_VERSION`/`GIT_COMMIT` em runtime) | 🧪 criado |
| 5 | `deploy-prod.sh` novo (VPS1 pull + up --no-build) — substitui o antigo | 🧪 `deploy-prod.sh.novo` |
| 6 | **Corte**: desligar webhook 9003 → push (CI builda) → tag → promote+deploy prod → validar | 🎯 aguarda aprovação |
## Imagem / registry
- `git.clube67.com/ruicesar/rx-scoreodonto:<sha>` (build-once por commit) → promovida a `:vX.Y.Z` (sem rebuild).
- Versão semântica nasce da **tag**, injetada em runtime (`APP_VERSION`) — não entra no build.
## Riscos a tratar (corte)
- **NÃO quebrar `/updates/`** (auto-update dos clients) — é volume bind, preservado no `up --no-build`.
- **Banco**: migrações rodam no boot → backup do `dental_images` antes do 1º deploy por tag.
- Rollback: reativar webhook 9003 (modelo antigo) **ou** `deploy-prod.sh <tag-anterior>`.
- Regra da stack: **testar em dev.rx + aprovação para prod**.