1
Deploy V.1.0.5
VPS 4 Builder edited this page 2026-06-03 06:28:45 +02:00

🚀 Deploy V.1.0.5 — Nomes de Sistema e Cliente Congelados + Deploy Conjunto

Versão 1.0.5 — inclui tudo da 1.0.4 e formaliza a Regra de Deploy Conjunto: atualizações de funcionalidades que afetam tanto o servidor quanto o cliente exigem push em AMBOS os repositórios. O nome do executável e do sistema permanecem fixos.


📋 Índice

  1. Arquitetura Multi-VPS
  2. Pipeline GitOps (Servidor — Modelo A)
  3. Os Listeners de Webhook
  4. Versionamento — Servidor
  5. Cliente Windows — Build, Publicação e Auto-Update
  6. 🔒 Nomes Congelados — Regra Obrigatória
  7. Erros comuns e soluções
  8. Troubleshooting
  9. Changelog

1. Arquitetura Multi-VPS

Servidor IP (VPN) Função
VPS 1 — App 10.99.0.1 Produção (Docker rootless) + serve /updates/ do cliente
VPS 3 — Data/Git 10.99.0.3 Gitea + PostgreSQL
VPS 4 — Builder 10.99.0.4 Build do servidor e do cliente Windows (cross-compile)
Wasabi S3-compatível Storage de imagens (não no disco)

2. Pipeline GitOps (Modelo A)

Servidor

git push origin main (rx.scoreodonto.com)
    ↓
Gitea dispara webhook → VPS4:9003/webhook
    ↓
listener-rx.js → deploy-prod.sh
    ↓
VPS4: build React (Vite) → docker compose build → docker save → app.tar.gz
    ↓
VPS4: rsync app.tar.gz + docker-compose.yml + version.txt → VPS1
    ↓
VPS1: docker load + docker compose up -d --no-deps app
    ↓
✅ Deploy concluído (~30-40 s)

Cliente Windows (automatizado desde 2026-05-31)

git push origin main (rx.scoreodonto.com-client)
    ↓
Gitea dispara webhook → VPS4:9004/webhook
    ↓
listener-rx-client.js → deploy-client.sh
    ↓
VPS4: npm install → electron-builder --win --x64 → dist/*.exe + latest.yml (~90s)
    ↓
VPS4: rsync dist/*.exe + *.yml + *.blockmap → VPS1:/dental-server/updates/
    ↓
✅ Client publicado em produção (auto-updater nas clínicas detecta em ~5 min)

⚠️ O build do React roda com NODE_ENV=development npm install --include=dev porque o vite é devDependency e o listener roda com NODE_ENV=production (que pula devDeps).


3. Os Listeners de Webhook

Listener Porta Serviço systemd Repo Script
listener-rx.js 9003 webhook-rx.service rx.scoreodonto.com deploy-prod.sh
listener-rx-client.js 9004 webhook-rx-client.service rx.scoreodonto.com-client deploy-client.sh
listener.js 9000 webhook-listener.service clube67 (system hook) deploy-prod-builder.sh

📌 O webhook do sistema (git.clube67.com/-/admin/hooks10.99.0.4:9000) dispara para todos os repositórios. Os listeners das portas 9003 e 9004 são webhooks por repositório, configurados individualmente em cada repo, e rodam em paralelo.

Todos os listeners seguem o mesmo padrão:

  • Validam token via x-gitea-token header ou ?token= query string
  • Trava de concorrência (isBuilding = true) — ignora pushes enquanto um build roda
  • Anti-loop — ignora commits chore(deploy): bump version
  • Respondem HTTP 202 imediatamente, evitando timeout do Gitea (30s)
  • Atualizam o status do commit no Gitea (pending → success / failure)

Tokens e URLs de webhook

Servidor  → http://10.99.0.4:9003/webhook?token=rx_deploy_token_9003_c7f2a1b4e8d5
Client    → http://10.99.0.4:9004/webhook?token=rx_client_deploy_token_9004_b3e1f7a2c9d6
Clube67   → http://10.99.0.4:9000/webhook?token=gitea_webhook_secret_clube67_58e4a92c3d18

Verificar status dos listeners

sudo systemctl status webhook-rx.service
sudo systemctl status webhook-rx-client.service
sudo systemctl status webhook-listener.service

# Portas abertas (deve mostrar 9000, 9003, 9004):
ss -tlnp | grep -E "900[0-9]"

# Teste rápido (401 = listener respondendo):
curl -s -o /dev/null -w "%{http_code}" -X POST http://10.99.0.4:9004/webhook

Logs (todos compartilham o mesmo arquivo)

tail -50 /home/deploy/stack/webhook-listener/deploy.log
# Prefixos: [rx.scoreodonto.com] | [rx.scoreodonto.com-client] | sem prefixo (clube67)

4. Versionamento — Servidor

Fonte de verdade: dental-server/version.txt (lido em runtime, injetado no sidebar). package.json nunca é tocado no bump (preserva cache do Docker).

ssh deploy@10.99.0.1 "docker exec rx_scoreodonto_app cat /app/version.txt"
curl -s https://rx.scoreodonto.com/ | grep -o 'v[0-9]\.[0-9]\.[0-9]'

5. Cliente Windows — Build, Publicação e Auto-Update

Projeto: rx.scoreodonto.com-client (Electron + electron-updater).

5.1. Fonte de verdade

grep '"version"' /home/deploy/stack/rx.scoreodonto.com-client/package.json
# "version": "1.3.0"

5.2. As DUAS pastas (e por que confundem)

Pasta Onde O que é
rx.scoreodonto.com-client/dist/ VPS4 Saída do build. Tem todos os .exe gerados.
rx.scoreodonto.com/dental-server/updates/ VPS1 O que é servido via HTTP. É o que as clínicas enxergam.

🔑 Buildar ≠ publicar. O cliente só "existe" para as clínicas quando o latest.yml da VPS1 aponta para a nova versão.

5.3. Deploy automático via webhook (desde v1.3.0)

# Basta fazer push para main:
git push origin main
# → Gitea notifica VPS4:9004 → deploy-client.sh roda (~90s) → VPS1 atualizada

Deploy manual (emergência):

cd /home/deploy/stack/rx.scoreodonto.com-client
bash deploy-client.sh

5.4. Fluxo de auto-update nas clínicas

App inicia → GET https://rx.scoreodonto.com/updates/latest.yml
  → versão yml > instalada? → baixa .exe → instala ao reiniciar

5.5. Verificação rápida (3 pontos têm que bater)

# 1. Código:
grep '"version"' /home/deploy/stack/rx.scoreodonto.com-client/package.json

# 2. HTTP público (o que o auto-updater baixa):
curl -s https://rx.scoreodonto.com/updates/latest.yml | head -1

# 3. VPS1 direto:
ssh deploy@10.99.0.1 "head -1 /home/deploy/stack/rx.scoreodonto.com/dental-server/updates/latest.yml"

5.6. Proteções contra perda de dados na atualização (v1.3.0)

  • deleteAppDataOnUninstall: false%APPDATA%\ScoreOdonto Dental Client\ nunca é apagado
  • config.backup.json — espelho do config.json, restaurado automaticamente se o principal corromper (preserva clientId e credenciais — evita reconfiguração do zero)
  • update-state.json — após 3 falhas da mesma versão, para de auto-instalar e exibe balão pedindo reinstalação manual; zerado automaticamente no próximo boot bem-sucedido

6. 🔒 Nomes Congelados — Regra Obrigatória

Agentes de IA e desenvolvedores NÃO devem alterar os nomes abaixo sem aprovação explícita do responsável pelo projeto.

6.1. Nome do sistema (painel web)

Local Valor fixo
dental-client/index.html<title> Score Client — Gerenciador de Imagens
src/components/Sidebar.jsx → cabeçalho Score Client
src/pages/LoginPage.jsx<h1> Score Client
src/pages/DownloadPage.jsx<h2> Score Client — Cliente Windows

6.2. Nome do executável do cliente Windows

{ "productName": "ScoreOdonto Dental Client" }

Gera: ScoreOdonto Dental Client Setup X.Y.Z.exeapenas X.Y.Z muda.

Alterar o productName quebra: latest.yml, URL de download, histórico de instalações no Windows.

6.3. URL de download — resolução dinâmica

DownloadPage.jsxpath: do latest.yml em runtime — sem hardcode. Depende do productName exato.

6.4. Checklist antes de refatorar

  • <title> = Score Client — Gerenciador de Imagens?
  • Sidebar = Score Client?
  • <h1> login = Score Client?
  • productName = ScoreOdonto Dental Client?
  • latest.yml em produção tem path: ScoreOdonto Dental Client Setup X.Y.Z.exe?

6.5. ⚠️ REGRA OBRIGATÓRIA: Deploy Conjunto (Client + Server)

Como o sistema é dividido em dois repositórios independentes (rx.scoreodonto.com e rx.scoreodonto.com-client), o build do cliente não ocorre junto com o do servidor. Sempre que for criada uma funcionalidade que exija comunicação entre as duas pontas (ex: Sockets, API, IPC de Auto-Update, Sincronização), é OBRIGATÓRIO (CRITICAL) confirmar se o git add . && git commit && git push origin main foi executado separadamente nos DOIS repositórios.

  • Fiz o git push no repositório rx.scoreodonto.com (Servidor)?
  • Fiz o git push no repositório rx.scoreodonto.com-client (Cliente Windows)?

7. Erros comuns e soluções

Erro A — Cliente desatualizado nas clínicas

Causa: build no dist/ mas rsync → VPS1 não rodou, ou webhook não disparou.

grep "rx.scoreodonto.com-client" /home/deploy/stack/webhook-listener/deploy.log | tail -10

# Solução rápida (sem rebuild):
rsync -avz dist/*.exe dist/*.yml dist/*.blockmap \
  deploy@10.99.0.1:/home/deploy/stack/rx.scoreodonto.com/dental-server/updates/

Erro B — Botão download → 404

path: no latest.yml ≠ arquivo real. Causa: productName alterado.

curl -s https://rx.scoreodonto.com/updates/latest.yml | grep "^path:"

Solução: restaurar productName para ScoreOdonto Dental Client e rodar deploy-client.sh.

Erro C — vite: not found

deploy-prod.sh usa NODE_ENV=development npm install --include=dev.

Erro D — Imagens em branco

Endpoint de thumb deve servir bytes (image/jpeg), não JSON.

Erro E — Wasabi 403

Chamar storage.loadConfigFromDb() após salvar credenciais.

Erro F — Listener do client não dispara

sudo systemctl status webhook-rx-client.service
curl -s -o /dev/null -w "%{http_code}" -X POST http://10.99.0.4:9004/webhook
# Esperado: 401
sudo systemctl restart webhook-rx-client.service

8. Troubleshooting

Problema Diagnóstico Solução
Cliente desatualizado package.jsonlatest.yml VPS1? Push para main (auto) ou bash deploy-client.sh
Webhook client não dispara systemctl status webhook-rx-client / porta 9004? sudo systemctl restart webhook-rx-client.service
Botão download → 404 path: ≠ arquivo real? Verificar productName; rebuildar
Build client falha electron-builder na VPS4 Ver log; rodar deploy-client.sh manual
Loop de atualização 3+ tentativas mesma versão? v1.3.0 tem trava; atualizar client
Config sumiu após update config.backup.json em AppData? v1.3.0 restaura automaticamente
Deploy servidor vite: not found NODE_ENV=production no install --include=dev no deploy-prod.sh
Imagens em branco thumb retornando JSON? Endpoint deve servir bytes image/jpeg
Wasabi 403 credenciais recarregadas? loadConfigFromDb() após salvar
Deploy servidor lento (3+ min) Modelo B? Modelo A (build na VPS4)

9. Changelog

Versão Data O que mudou
1.0.5 2026-06-03 Regra de Deploy Conjunto: Adicionada a seção 6.5 exigindo a verificação obrigatória de git push em ambos os repositórios para evitar descompasso de versão entre o servidor e o cliente (como ocorreu na versão 1.3.8 do client). Atualização automática transparente via Socket.IO.
1.0.4 2026-05-31 Automação deploy client: listener-rx-client.js (porta 9004) + webhook-rx-client.service + hook por repositório — push para main dispara build e publicação automáticos. Client v1.3.0: anti-loop de atualização, backup automático de config, deleteAppDataOnUninstall: false. Documenta webhook do sistema vs webhooks por repositório. Nomes congelados formalizados.
1.0.3 2026-05-31 Ciclo completo do Cliente Windows. Armadilha "buildado mas não publicado", verificação em 3 pontos, vite: not found.
1.0.2 2026-05-30 Switch para Modelo A (build VPS4), erros comuns, Wasabi. Deploy ~30-40s.
1.0.1 2026-05-30 Consolidação inicial: deploy + versionamento + segurança.
1.0.0 2026-05-30 Versão inicial.