sistema-de-chamados/docs/SETUP-HISTORICO.md

5.9 KiB
Raw Permalink Blame History

Histórico de Setup e Decisões — Sistema de Chamados

Registro das etapas realizadas, problemas encontrados e decisões tomadas para colocar o projeto em produção (Traefik + Swarm + Convex selfhosted) com CI/CD via runner selfhosted.

Arquitetura final

  • Frontend Next.js (app) em tickets.esdrasrenan.com.br.
  • Convex selfhosted (backend realtime) em convex.esdrasrenan.com.br.
  • Traefik no Docker Swarm (rede traefik_public) roteando por hostname (HTTPS/LE).
  • Banco Prisma (SQLite) persistente via volume sistema_db.
  • Estado do Convex persistente via volume convex_data.
  • Runner GitHub Actions selfhosted na VPS (usuário renan).

Mudanças no repositório

  • stack.yml — Stack Swarm (web + convex_backend + convex_dashboard opcional).
  • .env.example e apps/desktop/.env.example — exemplos de ambiente.
  • .github/workflows/ci-cd-web-desktop.yml — pipeline de deploy web + desktop + deploy do Convex.
  • docs/OPERACAO-PRODUCAO.md — runbook de operação (deploy, seeds, CI/CD, troubleshooting).
  • docs/SETUP-HISTORICO.md — este histórico.
  • pnpm-workspace.yaml — inclui packages: ['.', 'apps/desktop'] para permitir comandos e builds do desktop. No deploy do web usamos filtros/paths; se preferir isolar, volte para apenas '.'.
  • scripts/deploy-from-git.sh — fallback de deploy pullbased na VPS (sem Actions).

Gestão de .env

  • .env não é commitado; usamos o arquivo local na VPS: /srv/apps/sistema/.env.
  • Workflow atualizado para NÃO apagar .env no destino (rsync com filtros protect).
  • Valor com espaços deve ter aspas: MAILER_SENDER_EMAIL="Nome <no-reply@dominio>".
  • Em selfhosted, comentar CONVEX_DEPLOYMENT, e usar NEXT_PUBLIC_CONVEX_URL=https://convex....

Stack (Traefik/Swarm)

  • Binds absolutos (Portainer/Swarm exigem): /srv/apps/sistema:/app.
  • Volumes: sistema_db/app/data (SQLite), convex_data/convex/data.
  • Labels Traefik por hostname; WebSocket do Convex funciona via TLS.

Convex selfhosted

  • Evitamos convex dev no Swarm (CLI interativo). Adotada imagem oficial ghcr.io/get-convex/convex-backend.
  • Geração de Admin Key dentro do container: ./generate_admin_key.sh.
  • Publicação de functions com pnpm exec convex deploy via container Node (CONVEX_SELF_HOSTED_URL + CONVEX_SELF_HOSTED_ADMIN_KEY).
  • Adicionado convex_dashboard opcional (DNS convex-admin.*).

CI/CD (GitHub Actions)

  • Runner selfhosted vps-sistema com labels self-hosted, linux, vps.
  • Job Deploy (web) roda sempre em push para main.
  • Job Deploy Convex functions roda apenas quando arquivos em convex/** mudam (paths-filter).
  • rsync com --filter='protect .env*' para preservar .env local.
  • Secrets no repositório: CONVEX_SELF_HOSTED_URL, CONVEX_SELF_HOSTED_ADMIN_KEY (e secrets do desktop se usados).

Problemas e soluções (pitfalls)

  1. WebSocket 1006 no front
  • Causa: Convex não rodando corretamente (CLI interativo) → migração para imagem oficial selfhosted.
  1. .env sendo apagado pelo rsync
  • Causa: --delete no rsync no job de deploy.
  • Solução: adicionar filtros protect e exclude para .env* (raiz/desktop/convex).
  1. MAILER_SENDER_EMAIL com erro de parsing
  • Causa: valor com espaços sem aspas quando foi "sourced" por shell.
  • Solução: sempre usar aspas. Depois, com backend oficial, não foi mais necessário source.
  1. prisma: not found no build
  • Causa: instalar só prod deps.
  • Solução: NPM_CONFIG_PRODUCTION=false e pnpm install --prod=false no container de build.
  1. Lockfile/Workspace quebrando CI
  • Causa: conflito de versões quando o desktop entrou no workspace.
  • Solução: hoje mantemos ['.', 'apps/desktop'] e usamos filtros no CI/deploy. Alternativa: isolar o desktop fora do workspace.
  1. Bind relativo no Swarm/Portainer
  • Causa: ./:/app vira path inválido.
  • Solução: usar path absoluto: /srv/apps/sistema:/app.
  1. Flags --port/--hostname no convex dev
  • Causa: versão do CLI.
  • Solução: remover flags, e posteriormente substituir por backend oficial.
  1. Billing do GitHub bloqueado
  • Causa: cobrança travada bloqueia todos workflows (mesmo selfhosted).
  • Solução: regularizar billing; opcionalmente usar scripts/deploy-from-git.sh até normalizar.

Checklists de operação

  • Deploy manual (pullbased): bash /srv/apps/sistema/scripts/deploy-from-git.sh.
  • Deploy via Actions: commit em main.
  • Seeds: https://tickets.../dev/seed e docker exec ... pnpm auth:seed.
  • Verificação: docker stack services sistema e logs dos serviços.

Melhorias futuras

  • Rodar job de "Detect changes" também em runner selfhosted (zero minutos GitHubhosted).
  • Fixar versão do convex-backend (ao invés de latest) para releases mais controladas.
  • Substituir bindmount por imagens construídas no CI (tempo de deploy menor, reprodutibilidade).
  • Adicionar cache de dependências pnpm no container de build.

TODOs (próximos técnicos)

  • Prisma Client desatualizado x schema (Company.isAvulso/contractedHoursPerMonth)

    • Sintoma: Tipos gerados do Prisma não exibem os campos isAvulso e contractedHoursPerMonth em CompanyCreateInput/CompanyUpdateInput.
    • Temporário: rotas src/app/api/admin/companies/[id]/route.ts e mapeamento em src/app/admin/companies/page.tsx possuem guardas/casts para compilar.
    • Ação:
      1. Rodar pnpm prisma:generate no mesmo ambiente de build/execução (VPS e local) para regenerar o client.
      2. Confirmar que os campos aparecem nos tipos gerados.
      3. Remover casts e eslint-disable do update; reintroduzir campos no create se desejado (com tipagem estrita).
      4. Se ainda não existirem fisicamente na base, aplicar migração que adicione os campos ao modelo Company.
  • Next TS x Desktop (plugin Keyring)

    • Mantido apps/desktop/** no tsconfig.exclude para o typecheck do Next. Avaliar, em outro momento, ambient d.ts no desktop para editor.