# Deploy ScoreOdonto — Como um commit vira produção (estado-ALVO) > Este documento responde **uma** pergunta: **"como um commit vira produção?"** > Descreve o **fluxo-alvo** com **Gitea como motor de CI/CD**. O que já existe hoje está marcado como ✅; o que ainda será construído está marcado como 🔜. > Para a realidade da infra ver `arquitetura.md`. Para o procedimento manual executável **hoje** ver `DEPLOY-PRODUCAO.md`. --- ## 1. Princípios (inegociáveis) 1. **Gitea (VPS3) é a fonte única da verdade** e o motor de CI/CD. 2. **Produção (VPS1) nunca builda e nunca recebe código-fonte** — só consome **imagens versionadas** prontas. 3. **Build acontece fora da produção** (na CI / na VPS4). 4. **Deploy é um ato deliberado por TAG**, nunca automático em todo push (a `main` é usada para desenvolvimento e o banco é compartilhado — promover sem querer é perigoso). 5. **Rollback é trocar a imagem** por uma tag anterior — sem rebuild, sem recompilar, sem copiar arquivo. 6. **Toda imagem é rastreável**: carrega versão semântica + commit + data de build. --- ## 2. O fluxo-alvo, em uma frase > **Push** abastece o desenvolvimento e (🔜) **produz uma imagem versionada no registry**; > **criar uma tag `vX.Y.Z`** é o que **promove** essa imagem para produção. ``` git push ──► Gitea (VPS3) ──► CI: build da imagem ──► Registry privado (VPS3) (na main) (versão+commit+data) imagem :vX.Y.Z │ criar tag vX.Y.Z ────┘ ▼ VPS1: docker compose pull + up -d (troca o container pela imagem da tag) ▼ Produção rodando vX.Y.Z ``` --- ## 3. As duas metades do fluxo ### Metade A — Integração contínua (push → imagem) ✅ FEITO 1. Desenvolvedor trabalha na VPS4 e valida em `https://dev.scoreodonto.com`. 2. `git push origin main` (ou tag `v*`) para o Gitea (VPS3). 3. A **CI do Gitea** (Gitea Actions) builda backend+frontend via `docker compose build`, injetando **versão, commit curto e data de build** (build args → `VITE_*`/`process.env`). 4. As imagens são enviadas ao **Container Registry do Gitea** com tags `:`, `:` e `:latest`. 5. **Nada vai para produção aqui.** Esta metade só produz e guarda o artefato. > **Implementado em 16/jun/2026.** Workflow: `.gitea/workflows/build.yml`. Runner: `vps4-builder` (act_runner 0.6.1, **modo host** com Docker, serviço systemd `act_runner` na VPS4, label `self-hosted`). Login no registry usa o secret `REGISTRY_TOKEN` se presente, senão a credencial do host. Validado: push na main → build → `scoreodonto-{backend,frontend}:v1.0.13`/`:`/`:latest` publicados. ### Metade B — Entrega por tag (tag → produção) ✅ FEITO 1. Quando uma versão está aprovada, cria-se uma **tag semântica**: `git tag v1.0.15 && git push origin v1.0.15`. 2. A CI builda e publica a imagem `:v1.0.15` no registry **e** o job `deploy` (só em tags `v*`) promove para a VPS1. 3. Na VPS1, o `deploy-prod.sh ` faz `docker compose pull` + `up -d --no-build` apontando para a imagem da tag. 4. A versão visível (rodapé/endpoint `/api/version`) confirma a tag no ar com `environment: PROD`. > **Implementado em 16/jun/2026.** `docker-compose.prod.yml` (imagens do registry, sem build) + `deploy-prod.sh ` (na VPS1) + job `deploy` no workflow (SSH VPS4→VPS1, só em tags). **Push na main NÃO deploya — só tags.** Rollback: `deploy-prod.sh `. Validado: v1.0.13 promovida e confirmada (`V1.0.13 · fc0d65f · PROD`). --- ## 4. Versionamento visível (pré-requisito da confiança) ✅ FEITO > Implementado em 16/jun/2026 (Etapa 3). O build carimba versão/commit/data/ambiente via build args (`GIT_COMMIT`, `BUILD_TIME`, `APP_ENV`, `APP_VERSION`) → `import.meta.env.VITE_*` no frontend e `process.env` no backend. Visível no **rodapé do Sidebar**, no endpoint **`GET /api/version`** e na **linha de boot** `[VERSION] …` dos logs. Cada build carimba e **exibe**: ``` ScoreOdonto v1.0.15 commit: 7a9b3c1 build: 2026-06-16 14:32 UTC ambiente: PRODUÇÃO ``` Visível no **rodapé** da aplicação, em um **endpoint de diagnóstico** (ex.: `GET /api/version`) e na **linha de boot** dos logs. Hoje a versão fica escondida no bundle `index-.js` (ver `arquitetura.md` §7) — esta é a primeira melhoria de maior valor. --- ## 5. Rollback 🔜 - Listar as tags/imagens no registry da VPS3. - Na VPS1, apontar o compose para a tag anterior (`:v1.0.14`) e `docker compose up -d`. - 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) ✅/❌ - ✅ `git push` para o Gitea **funciona** (guarda o código). - ❌ **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`). --- ## 7. Roadmap para sair do "hoje" e chegar no "alvo" | Etapa | Entrega | Status | |-------|---------|--------| | 3 | Versionamento visível (rodapé + endpoint + log) | ✅ | | 4 | Registry Docker privado na VPS3 | ✅ (Gitea Container Registry — ver `REGISTRY.md`) | | 5 | Pipeline de build no Gitea (push → imagem → registry), **sem deploy** | ✅ (`.gitea/workflows/build.yml` + runner `vps4-builder`) | | 6 | Deploy por TAG (`vX.Y.Z` → produção na VPS1) + rollback por imagem | ✅ (`deploy-prod.sh` + job `deploy` em tags) | Quando as Etapas 3–6 estiverem prontas, este documento deixa de ter marcações 🔜 e passa a descrever o fluxo corrente.