Files
Documentos-Unicos/desuso/scoreodonto_DEPLOY-PRODUCAO_2026-06-17.md
T
2026-06-17 17:31:50 +02:00

122 lines
5.7 KiB
Markdown

> ⚠️ EM DESUSO desde 2026-06-17 — consolidado em /home/deploy/stack/documentos-unicos/ (ver LEIA-PRIMEIRO.md). Mantido só como histórico; NÃO usar como referência.
---
# Deploy & Versionamento — Runbook ScoreOdonto
> Auditado contra o sistema em **17/jun/2026**. Cada item carrega seu **status real**.
>
> **Legenda:** ✅ EM PRODUÇÃO · 🧪 EM DEV (não promovido) · 🎯 ALVO (não implementado).
>
> **Produção AGORA:** `v1.0.16 · commit 471c2c2 · 2026-06-17` (`curl https://scoreodonto.com/api/version`).
> Modelo **Build Once → Promote → Deploy** completo — Passo 5 validado em v1.0.16. Tudo abaixo ✅.
---
## 1. O modelo ✅
> **Push** na `main` builda **uma vez** e publica por **commit**; a **tag `vX.Y.Z`** **re-tagueia** esse mesmo artefato (sem rebuild) e deploya. **Produção nunca builda — só executa imagens.**
```
PUSH main (commit C) TAG vX.Y.Z (no commit C)
│ │
▼ ▼
CI: build (1x) CI: promote (SEM build) ✅
publica :C + :latest re-tag :C → :vX.Y.Z (MESMO digest) + deploy
▼ ▼
registry VPS1: pull :vX.Y.Z + up --no-build
APP_VERSION=tag injetada em runtime
```
Prova (v1.0.16): `:v1.0.16` tem **digest idêntico** a `:471c2c2` — a tag é só um rótulo sobre a imagem já testada.
---
## 2. Estado por componente (verificado)
| Componente | Status | Detalhe |
|---|---|---|
| Infra VPS1/3/4 + Docker rootless | ✅ | Mapa na §3 |
| Registry (`git.clube67.com/ruicesar/...`) | ✅ | Ver `REGISTRY.md` |
| CI: job `build` publica por **commit** em push (sem `APP_VERSION`) | ✅ | `.gitea/workflows/build.yml` (runner `vps4-builder`) |
| Job `promote` por tag: re-tag `:<commit>→:vX.Y.Z` (sem rebuild) + deploy | ✅ | validado em v1.0.16 (`:v1.0.16` == `:471c2c2`) |
| Validação de integridade no promote (commit existe? digest igual? front+back mesmo commit) | ✅ | falha se o commit não foi pushado |
| 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` |
| Versão em runtime (`/api/version`) → Configurações + telas públicas | ✅ | `useAppVersion()`; sem `APP_VERSION` manual |
| `APP_VERSION`/`APP_ENV` injetados no deploy em runtime | ✅ | `compose.prod` `environment` |
| Versão **nasce da tag git** (`constants.ts`/`update-version.js` removidos) | ✅ | Passo 5 |
---
## 3. Mapa de máquinas ✅
| Onde | Host | Papel | Docker |
|---|---|---|---|
| VPS1 | `10.99.0.1` | **Produção** (Traefik + apps) | rootless |
| VPS3 | `10.99.0.3` | Postgres (prod) + Gitea + registry | — |
| VPS4 | `10.99.0.4` | **Dev + Builder** (código; runner CI; `pgdev`) | rootless |
- Repo: `ssh://git@10.99.0.3/ruicesar/scoreodonto.com.git`. Project Compose: `scoreodontocom`.
---
## 4. De onde vem a versão (`/api/version`)
```json
{ "name": "ScoreOdonto API", "version": "v1.0.16", "commit": "471c2c2",
"build": "2026-06-17 10:35 UTC", "environment": "PROD" }
```
- **commit / build** = carimbados no **build** (imutáveis — identidade do artefato).
- **version / environment** = **injetados no deploy em runtime** (a partir da tag). A mesma imagem é promovida sob qualquer tag, sem rebuild.
- **Frontend** lê tudo de `/api/version` (`useAppVersion()`); não embute versão. Fonte única = backend.
---
## 5. Runbook — subir um release ✅
> ⚠️ **Regra de ouro:** confirme **DEV ou PRODUÇÃO**. `dev.scoreodonto.com` = VPS4 (banco `pgdev`). `scoreodonto.com` = VPS1 (real). **Nunca** `git push --force` na `main`. Push/tag exigem autorização explícita.
```bash
# 1) VPS4: validar em DEV
cd /home/deploy/stack/scoreodonto.com
node --check backend/server.js
docker compose build scoreodonto-backend scoreodonto-frontend
docker compose up -d --force-recreate scoreodonto-backend scoreodonto-frontend # https://dev.scoreodonto.com
# 2) commit + push → CI builda 1x e publica :<commit> + :latest (NÃO deploya)
git add -A && git commit -m "feat: <descrição>"
git push origin main
# 3) tag = "aprovado p/ produção" → job PROMOTE re-tagueia :<commit>→:vX.Y.Z (SEM rebuild) + deploya
# (o número da versão é livre — não precisa casar com nenhum arquivo)
git tag -a vX.Y.Z -m "release vX.Y.Z" && git push origin vX.Y.Z
# 4) verificar (sem SSH)
curl -s https://scoreodonto.com/api/version # → vX.Y.Z · <commit> · PROD
```
**Backup do banco de PRODUÇÃO antes de releases sensíveis** (via container, pois não há shell na VPS3):
```bash
docker run --rm -e PGPASSWORD=<senha> -v /home/deploy/backups:/b postgres:18 \
pg_dump -h 10.99.0.3 -U scoreodonto_user -d scoreodonto -Fc -f /b/scoreodonto_$(date +%Y%m%d_%H%M).dump
```
---
## 6. Rollback ✅
Por imagem, **sem rebuild** — na VPS1:
```bash
/home/deploy/stack/scoreodonto.com/deploy-prod.sh <tag-ou-commit-anterior> # pull + up --no-build
```
⚠️ A referência confiável é o **commit** (`:<sha>`). Tags `:vX.Y.Z` antigas (pré-Passo 5) podem ter sido republicadas com código diferente — a partir do Passo 5, `:vX.Y.Z` é sempre um alias imutável do commit. Migrações são aditivas (voltar o código é seguro). Dump em `/home/deploy/backups/` só em extremo.
---
## 7. Follow-ups (não bloqueiam) 🎯
- `GET /api/health` (monitoramento/diagnóstico).
- **Política de retenção** do registry (uma imagem `:<commit>` por push acumula).
- Reconciliar o repo na VPS1 (working tree sujo, não afeta o deploy por imagem).
Racional do modelo em `deploy.md`; histórico em `project-cicd-tag-promove-nao-rebuilda` (memória).