# Deploy runbook (Swarm) — Arquivo

Nota: este runbook foi arquivado. Utilize `docs/operations.md` para o fluxo atualizado de deploy.

Este guia documenta o fluxo de deploy atual e os principais passos de diagnóstico/correção que resolveram o problema do front não atualizar mesmo com o CI verde.

## Visão geral (como você trabalha)

- Você dá push na `main` e aguarda o GitHub Actions concluir.
- O pipeline cria um build imutável no servidor em `/home/renan/apps/sistema.build.<release>`.
- Um symlink estável aponta para o release ativo: `/home/renan/apps/sistema.current`.
- O serviço `sistema_web` monta sempre `/home/renan/apps/sistema.current:/app`. Para atualizar, basta mudar o symlink e forçar a task.

Resultado: front/back sobem com o novo código sem editar o stack a cada release.

## Fluxo de release (mínimo)

1. Gerar build em `/home/renan/apps/sistema.build.<stamp-ou-sha>` (CI faz isso).
2. Atualizar symlink: `ln -sfn /home/renan/apps/sistema.build.<novo> /home/renan/apps/sistema.current`.
3. Rollout do serviço web: `docker service update --force sistema_web`.
4. Opcional: se o `stack.yml` mudou, aplicar: `docker stack deploy --with-registry-auth -c /home/renan/apps/sistema.build.<novo>/stack.yml sistema`.

## Stack estável (essência)

- Mount fixo: `/home/renan/apps/sistema.current:/app` (não interpolar APP_DIR).
- Comando inline (sem script), com migrations na subida:
  - `command: ["bash","-lc","bun install --frozen-lockfile && bun x prisma migrate deploy && bun run start:bun"]`
  - **Se você optar por usar `/app/scripts/start-web.sh`** (como no workflow atual), garanta que o script execute `bun install` antes de rodar Prisma/Next. Certifique-se de copiar esse arquivo para o build publicado; sem ele, a task cai com `bun: command not found`.
- Env obrigatórias (URLs válidas):
  - `DATABASE_URL=file:/app/data/db.sqlite`
  - `NEXT_PUBLIC_CONVEX_URL=http://sistema_convex_backend:3210`
  - `NEXT_PUBLIC_APP_URL=https://tickets.esdrasrenan.com.br`
  - `BETTER_AUTH_URL=https://tickets.esdrasrenan.com.br`
- Update com `stop-first` (evita `database is locked` em SQLite) + healthcheck.

## Prisma/SQLite do stack

- O volume do stack é namespaced: `sistema_sistema_db` (não `sistema_db`).
- Ao operar Prisma fora do Swarm, use SEMPRE este volume e a mesma `DATABASE_URL`:

```
APP_DIR=/home/renan/apps/sistema.current
docker run --rm -it \
  -e DATABASE_URL=file:/app/data/db.sqlite \
  -v "$APP_DIR:/app" -v sistema_sistema_db:/app/data -w /app \
  oven/bun:1 bash -lc "bun install --frozen-lockfile && bun x prisma migrate status"
```

## Diagnóstico rápido

- Ver a task atual + erros: `docker service ps --no-trunc sistema_web`
- Logs frescos do serviço: `docker service logs --since=2m -f sistema_web`
- Spec aplicado (Args + Mounts):

```
docker service inspect sistema_web \
  --format '{{json .Spec.TaskTemplate.ContainerSpec.Args}} {{json .Spec.TaskTemplate.ContainerSpec.Mounts}}'
```

- Envs do serviço: `docker service inspect sistema_web --format '{{json .Spec.TaskTemplate.ContainerSpec.Env}}'`

## O incidente (front não atualizava) — causa e correções

Sintomas:
- Actions verde, mas UI antiga; logs com rollbacks de `docker service update`.

Causas encontradas:
1) Serviço ainda montava build antigo e comando antigo (spec não mudava).
   - Inspect mostrava `Source=/home/renan/apps/sistema.build.<antigo> -> /app` e comando inline antigo.
   - Correção: redeploy do stack com mount em `/home/renan/apps/sistema.current` + `docker service update --force sistema_web`.

2) Migration P3009 ("failed migrations") no SQLite do stack.
   - Motivo: resolver/aplicar migrations no volume errado (`sistema_db`), enquanto o serviço usa `sistema_sistema_db`.
   - Correção determinística:
     - `docker service scale sistema_web=0`
     - `prisma migrate resolve --rolled-back 20251015223259_add_company_provisioning_code` no volume `sistema_sistema_db` (comando acima em "Prisma/SQLite do stack").
     - `bun x prisma migrate deploy`
     - `docker service scale sistema_web=1` (ou `update --force`).

3) Rollback por script ausente (`/app/scripts/start-web.sh`).
   - Task caía com exit 127 porque o build não continha o script.
   - Correção: voltar ao comando inline no stack (sem depender do script) OU garantir o script no build e executável.

4) Falha de env (Invalid URL em `NEXT_PUBLIC_APP_URL`/`BETTER_AUTH_URL`).
   - Correção: definir URLs válidas no stack ou via `docker service update --env-add ...`.

## Cheatsheet de correções

- Forçar rollout da task:
  - `docker service update --force sistema_web`

- Aplicar build novo (sem tocar stack):
  - `ln -sfn /home/renan/apps/sistema.build.<novo> /home/renan/apps/sistema.current`
  - `docker service update --force sistema_web`

- Corrigir mount/args no serviço (hotfix):

```
docker service update \
  --mount-rm target=/app \
  --mount-add type=bind,src=/home/renan/apps/sistema.current,dst=/app \
  --args 'bash -lc "bun install --frozen-lockfile && bun x prisma migrate deploy && bun run start:bun"' \
  sistema_web
```

- Resolver P3009 (volume certo) e aplicar migrations:

```
APP_DIR=/home/renan/apps/sistema.current
docker service scale sistema_web=0
docker run --rm -it -e DATABASE_URL=file:/app/data/db.sqlite \
  -v "$APP_DIR:/app" -v sistema_sistema_db:/app/data -w /app \
  oven/bun:1 bash -lc "bun install --frozen-lockfile && bun x prisma migrate resolve --rolled-back 20251015223259_add_company_provisioning_code && bun x prisma migrate deploy"
docker service scale sistema_web=1
```

- Criar DB se faltar (P1003):
  - `docker run --rm -v sistema_sistema_db:/data busybox sh -lc ': >/data/db.sqlite'`

- Ajustar envs em runtime:
  - `docker service update --env-add NEXT_PUBLIC_APP_URL=https://tickets.esdrasrenan.com.br --env-add BETTER_AUTH_URL=https://tickets.esdrasrenan.com.br sistema_web`

## Notas finais

- Como o stack monta `/home/renan/apps/sistema.current`, um novo release exige apenas atualizar o symlink e forçar a task. O `stack.yml` só precisa ser redeployado quando você altera labels/envs/serviços.
- Se a UI parecer não mudar, valide o mount/args via inspect, confira logs da task atual e force hard‑reload no navegador.
