From 114b10650380d1b3f3471a5f543ac8421556d84d Mon Sep 17 00:00:00 2001 From: VPS 4 Deploy Agent Date: Thu, 18 Jun 2026 02:36:29 +0200 Subject: [PATCH] =?UTF-8?q?docs(rx-server):=20plano=20de=20padroniza=C3=A7?= =?UTF-8?q?=C3=A3o=20Build=20Once/Promote=20(pe=C3=A7as=20em=20dev,=20buil?= =?UTF-8?q?d=20local=20validado)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- projetos/rx.scoreodonto.com/plano-deploy.md | 36 +++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 projetos/rx.scoreodonto.com/plano-deploy.md diff --git a/projetos/rx.scoreodonto.com/plano-deploy.md b/projetos/rx.scoreodonto.com/plano-deploy.md new file mode 100644 index 0000000..af24c0e --- /dev/null +++ b/projetos/rx.scoreodonto.com/plano-deploy.md @@ -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:` 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:` (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 `. +- Regra da stack: **testar em dev.rx + aprovação para prod**.