docs: reconcilia deploy/versionamento com o estado real (pós v1.0.15)

- VERDADE-HOJE.md: reescrito p/ a verdade de 17/jun — banco DEV isolado (pgdev, não
  compartilha mais), produção roda imagem v1.0.15, versão em runtime via /api/version.
  Declarado documento principal (prevalece em divergência).
- deploy.md: §5 rollback  (existe); §6 corrigida — remove o "não há CI/registry/deploy"
  (era falso/contraditório); CI/CD por tag ATIVO, falta só o Passo 5.
- DEPLOY-PRODUCAO.md: status 🧪 dos Passos 1/3/4 (promovidos em v1.0.15).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-06-17 11:34:51 +02:00
parent f2eb90ccc8
commit 0f50835114
3 changed files with 40 additions and 44 deletions
+12 -12
View File
@@ -8,8 +8,8 @@
> - 🧪 **EM DEV** — implementado no working tree da VPS4 / `dev.scoreodonto.com`; **não commitado, não promovido**. > - 🧪 **EM DEV** — implementado no working tree da VPS4 / `dev.scoreodonto.com`; **não commitado, não promovido**.
> - 🎯 **ALVO** — desenhado/aprovado, **ainda não implementado**. > - 🎯 **ALVO** — desenhado/aprovado, **ainda não implementado**.
> >
> **Produção AGORA:** `v1.0.14 · commit 081985c · 2026-06-16` (`curl https://scoreodonto.com/api/version`). > **Produção AGORA:** `v1.0.15 · commit f2eb90c · 2026-06-17` (`curl https://scoreodonto.com/api/version`).
> Todo o trabalho de versionamento abaixo marcado 🧪 está no working tree da VPS4 (não commitado). > Os Passos 1/3/4 (versão em runtime) foram **promovidos a produção** em 17/jun (tag `v1.0.15`).
--- ---
@@ -26,7 +26,7 @@
▼ 🎯 alvo (Passo 5): só re-tag :C→:vX.Y.Z, SEM build ▼ 🎯 alvo (Passo 5): só re-tag :C→:vX.Y.Z, SEM build
registry ▼ registry ▼
VPS1: pull + up --no-build ✅ VPS1: pull + up --no-build ✅
APP_VERSION=tag em runtime 🧪 (Passo 3) APP_VERSION=tag em runtime (Passo 3, em prod)
``` ```
--- ---
@@ -41,11 +41,11 @@
| Deploy por tag (job `deploy` SSH VPS4→VPS1) | ✅ | `deploy-prod.sh` na VPS1 | | Deploy por tag (job `deploy` SSH VPS4→VPS1) | ✅ | `deploy-prod.sh` na VPS1 |
| Produção não builda (`image:` + `pull` + `up --no-build`) | ✅ | `docker-compose.prod.yml` | | Produção não builda (`image:` + `pull` + `up --no-build`) | ✅ | `docker-compose.prod.yml` |
| Banco DEV isolado em `pgdev`; prod no Postgres da VPS3 | ✅ | Ver `BANCO-DEV-ESTRATEGIA.md` | | Banco DEV isolado em `pgdev`; prod no Postgres da VPS3 | ✅ | Ver `BANCO-DEV-ESTRATEGIA.md` |
| `GET /api/version` responde (de `process.env`) | ✅ | Em prod, valores vêm do **build** da imagem | | `GET /api/version` responde (de `process.env`) | ✅ | No ar: v1.0.15 · f2eb90c · PROD |
| **Versão exibida em Configurações → "Sobre o sistema"** | 🧪 | Passo 1. Em **produção a versão está no Sidebar** | | **Versão exibida em Configurações → "Sobre o sistema"** | | Passo 1 (promovido em v1.0.15; saiu do Sidebar) |
| **Front/telas consomem `/api/version` (`useAppVersion`); app não usa `APP_VERSION`** | 🧪 | Passos 1/4. Em **prod o front usa `APP_VERSION` do bundle** | | **Front/telas consomem `/api/version` (`useAppVersion`); app não usa `APP_VERSION`** | | Passos 1/4 (em prod desde v1.0.15) |
| **Deploy injeta `APP_VERSION`/`APP_ENV` em runtime (`environment`)** | 🧪 | Passo 3 (`compose.prod`/`deploy-prod.sh` no working tree) | | **Deploy injeta `APP_VERSION`/`APP_ENV` em runtime (`environment`)** | | Passo 3 (`compose.prod`/`deploy-prod.sh` em prod) |
| **Tag promove sem rebuild + validação de integridade** | 🎯 | Passo 5 (§7) | | **Tag promove sem rebuild + validação de integridade** | 🎯 | Passo 5 (§7) — único item pendente |
--- ---
@@ -65,12 +65,12 @@
## 4. De onde vem a versão (contrato `/api/version`) ## 4. De onde vem a versão (contrato `/api/version`)
```json ```json
{ "name": "ScoreOdonto API", "version": "v1.0.14", "commit": "081985c", { "name": "ScoreOdonto API", "version": "v1.0.15", "commit": "f2eb90c",
"build": "2026-06-16 08:06 UTC", "environment": "PROD" } "build": "2026-06-17 03:37 UTC", "environment": "PROD" }
``` ```
- **commit / build** = carimbados no **build** da imagem (imutáveis — identidade do artefato). ✅ - **commit / build** = carimbados no **build** da imagem (imutáveis — identidade do artefato). ✅
- **version / environment** **hoje (✅)** também vêm do build da imagem (build arg no CI). **🧪 (Passo 3):** passam a ser injetados no **deploy** em runtime (a partir da tag), liberando a mesma imagem para qualquer tag sem rebuild. - **version / environment** = **injetados no deploy em runtime** (a partir da tag) via `environment` do `compose.prod` ✅ (Passo 3, em prod) — a mesma imagem pode ser promovida sob qualquer tag sem rebuild.
- **Frontend** **🧪 (Passos 1/4):** lê tudo de `/api/version` via `useAppVersion()`; deixa de embutir versão. **Em produção** ainda embute `APP_VERSION` no bundle. - **Frontend** = lê tudo de `/api/version` via `useAppVersion()`; **não embute mais a versão** ✅ (Passos 1/4, em prod). Fonte única = backend.
--- ---
+21 -24
View File
@@ -1,45 +1,42 @@
# Qual é a verdade hoje? — Auditoria de infra ScoreOdonto # Qual é a verdade hoje? — Auditoria de infra ScoreOdonto
> Resposta direta às 6 perguntas essenciais, **verificada em 16/jun/2026**. Sem teoria, sem fantasma. > Resposta direta às 6 perguntas essenciais, **verificada em 17/jun/2026**. Somente fatos do estado atual.
> Detalhes em `arquitetura.md` (real), `deploy.md` (alvo) e `DEPLOY-PRODUCAO.md` (runbook). > **Documento principal: em caso de divergência entre docs, este prevalece.**
> Como operar → `DEPLOY-PRODUCAO.md` (runbook). Para onde vamos → `deploy.md` (arquitetura-alvo).
--- ---
### 1. Onde está o código? ### 1. Onde está o código?
- **Fonte da verdade:** Gitea na **VPS3**, repo `ruicesar/scoreodonto.com` (`ssh://git@10.99.0.3/ruicesar/scoreodonto.com.git`). - **Fonte da verdade:** Gitea na **VPS3**, repo `ruicesar/scoreodonto.com`.
- **Cópia de trabalho (dev):** VPS4 em `/home/deploy/stack/scoreodonto.com` (onde se programa). - **Dev (trabalho):** VPS4 em `/home/deploy/stack/scoreodonto.com`.
- **Cópia de produção:** VPS1 em `/home/deploy/stack/scoreodonto.com` (HEAD verificado: `19dbbae`). - **Produção:** VPS1 roda **imagens versionadas do registry** (não código-fonte). No ar: **v1.0.15 · commit `f2eb90c`**.
- **Documentação:** centralizada em `scoreodonto.com/documentação/` (este diretório). - **Documentação:** centralizada em `scoreodonto.com/documentação/`.
### 2. Onde está o banco? ### 2. Onde está o banco?
- **PostgreSQL** no host da **VPS3** (`10.99.0.3:5432`), banco `scoreodonto`, usuário `scoreodonto_user`. - **Produção:** PostgreSQL no host da **VPS3** (`10.99.0.3:5432`), banco `scoreodonto`, user `scoreodonto_user`.
- ⚠️ **DEV e PROD usam o MESMO banco.** Não há isolamento. Backup (`pg_dump -Fc`) é a única rede de segurança. - **DEV ISOLADO:** a VPS4 usa um container PostGIS próprio **`pgdev`** (banco `scoreodonto_dev`), **NÃO mais o banco de produção**. Dev e prod **não compartilham** mais. (Ver `BANCO-DEV-ESTRATEGIA.md`.)
- Cache **DragonflyDB** (`10.99.0.3:6379`, índice `/1`). Mensageria **NATS** (`:4222`) e **Temporal** (`:7233`). - Cache **DragonflyDB** (`10.99.0.3:6379`, índice `/1`). **NATS** (`:4222`) e **Temporal** (`:7233`).
### 3. Onde estão os containers? ### 3. Onde estão os containers?
- **Produção (VPS1, docker rootless `unix:///run/user/1000/docker.sock`):** - **Produção (VPS1, docker rootless):** `scoreodontocom-scoreodonto-{frontend,backend}-1` rodam a **imagem do registry** (`git.clube67.com/ruicesar/scoreodonto-*:<tag>`). Produção **não builda**. Também na VPS1: `traefik` (borda TLS), rx, newwhats, subdominio, mercado.
- `scoreodontocom-scoreodonto-frontend-1` — roda **imagem versionada do registry** (`git.clube67.com/ruicesar/scoreodonto-frontend:<tag>`), promovida por deploy-por-tag. Produção **não builda** mais. - **Dev (VPS4, docker rootless):** `nginx-1` (`8020→80`, alvo do Traefik para `dev.`), `frontend-1` (`:3013`), `backend-1` (`:8018`) — **buildados localmente** e apontados ao `pgdev`.
- `scoreodontocom-scoreodonto-backend-1` — idem (`:8018`).
- `traefik-traefik-1` — borda TLS (Up ~13 dias). Também: rx, newwhats, subdominio, mercado.
- **Dev (VPS4, docker root `/var/run/docker.sock`):**
- `scoreodontocom-nginx-1` (`0.0.0.0:8020->80`, alvo do Traefik para `dev.`), `scoreodonto-frontend-1` (`:3013`), `scoreodonto-backend-1` (`:8018`).
- **Roteamento:** Traefik na VPS1 → `scoreodonto.com` (containers locais) e `dev.scoreodonto.com``http://10.99.0.4:8020`. - **Roteamento:** Traefik na VPS1 → `scoreodonto.com` (containers locais) e `dev.scoreodonto.com``http://10.99.0.4:8020`.
### 4. Quem faz deploy? ### 4. Quem faz deploy?
- **CI/CD por tag (Gitea Actions).** `git tag vX.Y.Z && git push origin vX.Y.Z` → o runner `vps4-builder` builda as imagens, publica no registry e o job `deploy` promove para a VPS1 (`deploy-prod.sh`). **Push na main NÃO deploya — só builda.** - **CI/CD por tag (Gitea Actions).** Push na `main` → o runner `act_runner` "vps4-builder" (VPS4, rootless) builda e **publica no registry** (NÃO deploya). `git tag vX.Y.Z && git push` → CI + job `deploy` promove para a VPS1 (`deploy-prod.sh`).
- **Produção não builda mais:** consome a **imagem versionada** do registry (`docker compose -f docker-compose.yml -f docker-compose.prod.yml pull && up -d --no-build`). - **Produção consome imagem** (`pull` + `up -d --no-build`).
- Deploy manual também disponível: na VPS1, `./deploy-prod.sh <tag>`. Ver `deploy.md` e `REGISTRY.md`. - ⚠️ Hoje a **tag rebuilda** antes de promover; o **Passo 5** mudará para a tag apenas **re-taguear** o artefato já construído por commit.
### 5. Como versiona? ### 5. Como versiona?
- `APP_VERSION` em `frontend/constants.ts` (dev hoje **`V1.0.13`**), incrementado por `update-version.js` (patch++). - A versão exibida vem do **backend em runtime**: `GET /api/version` (de `process.env`), mostrada em **Configurações → "Sobre o sistema"** e nas telas públicas (o frontend consome via `useAppVersion()`, não embute mais a versão). No ar: **v1.0.15 · `f2eb90c` · PROD**.
- ⚠️ **Bump é manual** — nada chama `update-version.js` no build (`npm run build` = só `vite build`). Por isso a versão fica parada se ninguém rodar o script. - No deploy, `APP_VERSION` (= tag) e `APP_ENV=PROD` são **injetados em runtime**; `commit`/`build` vêm carimbados na imagem.
- **Versão visível** (Etapa 3): rodapé do Sidebar + `GET /api/version` + log de boot `[VERSION] …`. Carimbo (versão/commit/data/ambiente) injetado no build. **No ar em DEV e em PRODUÇÃO** (prod hoje: `v1.0.14 · 081985c · PROD`). - ⚠️ **Legado transitório:** `frontend/constants.ts` (`APP_VERSION`) + `update-version.js` ainda existem **só** para o CI nomear a imagem (bump manual evita colisão de tag). Serão **eliminados no Passo 5** (a versão nascerá da tag git).
### 6. Como volta uma versão (rollback)? ### 6. Como volta uma versão (rollback)?
- **Por imagem, sem rebuild:** na VPS1, `./deploy-prod.sh <tag-anterior>` (ex.: `./deploy-prod.sh v1.0.13`) — puxa a imagem da tag anterior do registry e sobe. Minutos, sem recompilar. - **Por imagem, sem rebuild:** na VPS1, `./deploy-prod.sh <ref-anterior>` `pull` + `up -d --no-build`.
- Seguro porque as migrações são **aditivas** (voltar código não quebra o schema). Restaurar o dump (`/home/deploy/backups/`) só em caso extremo. - ⚠️ A referência confiável é o **commit** (`:<sha>`): tags `:vX.Y.Z` podem ter sido **republicadas** com código diferente (colisão de tags pré-Passo 5 — confirmado: `:v1.0.14` do registry ≠ o que rodava). Migrações são **aditivas** (voltar o código é seguro). Dump em `/home/deploy/backups/` só em caso extremo.
--- ---
## Veredito de uma linha ## Veredito de uma linha
> O código está salvo no Gitea (VPS3) e roda em containers na VPS1 (prod) e VPS4 (dev), ambos no **mesmo banco** da VPS3. **CI/CD por tag ativo**: `git tag vX.Y.Z` → CI builda imagem → deploy automático na VPS1, com **versão visível** no rodapé/`/api/version` e **rollback por imagem** (`deploy-prod.sh <tag-anterior>`). Pendência estrutural restante: **isolar um banco `scoreodonto_dev`** (dev e prod ainda compartilham o banco). > O código vive no Gitea (VPS3); a **produção (VPS1) roda imagens versionadas do registry** (hoje **v1.0.15**), sem buildar; o **DEV está isolado no `pgdev`** (não toca o banco de produção). **CI/CD por tag ativo**, com **versão visível em runtime** (`/api/version` → Configurações). Pendência técnica principal: **Passo 5** (tag promove sem rebuild; eliminar o `APP_VERSION` manual).
+7 -8
View File
@@ -75,19 +75,18 @@ Visível no **rodapé** da aplicação, em um **endpoint de diagnóstico** (ex.:
--- ---
## 5. Rollback 🔜 ## 5. Rollback
- Listar as tags/imagens no registry da VPS3. - Por imagem, **sem rebuild**: na VPS1, `./deploy-prod.sh <tag-ou-commit-anterior>``pull` + `up -d --no-build`.
- Na VPS1, apontar o compose para a tag anterior (`:v1.0.14`) e `docker compose up -d`. - ⚠️ Use uma referência que corresponda ao que estava no ar: a tag `:vX.Y.Z` pode ter sido **republicada** com outro código (colisão de tags pré-Passo 5) — o **commit** (`:<sha>`) é a referência confiável. O banco é aditivo (voltar o código é seguro); restaurar dump só em caso extremo.
- Recuperação em minutos, **sem rebuild**. O banco é aditivo (ver `arquitetura.md` §5), então voltar o código é seguro; restaurar dump só em caso extremo.
--- ---
## 6. Estado de hoje (honesto) ✅/❌ ## 6. Estado de hoje (corrente) ✅
-`git push` para o Gitea **funciona** (guarda o código). **O CI/CD por tag está ATIVO** (Etapas 36 concluídas, ver §7): push na `main` builda e publica no registry; tag `vX.Y.Z` promove para a VPS1. Produção **não builda** — consome a imagem do registry. Para o estado atual factual ver **`VERDADE-HOJE.md`**; para operar ver **`DEPLOY-PRODUCAO.md`**.
-**Não há build automático**, **não há registry**, **não há deploy automático**. O antigo listener (porta 9002) foi deletado e não há webhook do scoreodonto.com no Gitea.
- ➡️ Enquanto a CI acima não existe, a promoção para produção é **manual** e está documentada passo a passo em **`DEPLOY-PRODUCAO.md`** (build na VPS4 → enviar imagem para a VPS1 → `up -d`). O que **ainda falta** (o alvo deste documento) é o **Passo 5**: hoje a **tag rebuilda** antes de promover; o alvo é a tag apenas **re-taguear** o artefato já construído por commit (*Build Once → Promote*), eliminando `constants.ts`/`APP_VERSION` manual.
--- ---