style: prettier — runbook/impl plan/unit test (OPS66)
All checks were successful
CI (PR) / checks (pull_request) Successful in 4m11s
PR Ready + auto-merge / ready-automerge (pull_request) Successful in 4m22s
Main merge flips claimed issues to done + in-prod / issue-done (pull_request) Successful in 15s
Promote plan-issue Related on main merge / plan-issue-ready (pull_request) Has been skipped

This commit is contained in:
Francisco Solla 2026-08-19 10:07:14 -03:00
parent 228f2217c7
commit 8d33e89102
3 changed files with 20 additions and 16 deletions

View file

@ -31,7 +31,7 @@ da suite/deploy (~15–25 min cada; tipicamente < 1 h no total).
5. O script, no **homeserver**: guarda de HEAD (`main` remoto == SHA do job,
senão skip) → `flock` (serializa) → guard "already deployed" (revision do
container) → **build do migrator** (o estágio migrator não roda `next
build` — builda mesmo contra o schema antigo; BuildKit, secrets do
build` — builda mesmo contra o schema antigo; BuildKit, secrets do
`~/stack/teqo-1313.env`) → push/tag do migrator em `localhost:5000` →
swap dos tags de imagem no `~/stack/docker-compose.yml` (backup antes) →
**migrations**
@ -94,20 +94,20 @@ a correção se re-mergeia e a próxima janela completa o deploy.
## Falhas conhecidas
| Sintoma | Causa | Tratamento |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Job verde sem deploy ("stale run") | Push mais novo venceu; o deploy antigo saiu da fila | Nada a fazer — o run do SHA novo deploya |
| Job verde sem deploy ("already deployed") | O container rodando já tem a revision do SHA do job (ex.: `workflow_dispatch` duplicado da mesma HEAD) | Nada a fazer — o site já roda esse SHA. Forçar rebuild da MESMA HEAD não é suportado via dispatch: edite o tag da imagem no compose (`image: teqo-1313:<sha>-rebuild`) e `docker compose up -d`, ou espere um commit novo |
| Gate `gate` vermelho (erro de git/`.dockerignore`) | SHA deployado ilegível para o git (ex.: história reescrita) ou `.dockerignore` corrompido no checkout | Fail-open: suite roda; deploy pula (nunca deploy às cegas). Corrigir a causa e esperar a próxima janela (auto-cura). Se `ssh homeserver` estiver fora, o gate lê revision vazia e roda tudo (verde) — checar tailnet se a suite roda sem deploy recorrente |
| Sem revision no container (label ausente no compose) | O compose do homeserver não define `org.opencontainers.image.revision` (deploy pré-OPS53 ou edição manual) | Degradação conservadora: toda janela roda suite + rebuild (verde). Corrigir adicionando o label ao serviço `teqo-1313` no compose e re-deployando |
| Todo job docker quebra com `exec: "node": executable file not found in $PATH` | `runner.envs.PATH` do `~/.forgejo-runner/config.yaml` (workstation) com paths só de host (nvm/bun) — o container perde o node do toolcache (`/opt/acttoolcache`); edição do config exige o toolcache primeiro (ver comentário no próprio config) | Corrigir o PATH no config (toolcache primeiro — ver comentário no próprio arquivo) + `systemctl --user restart forgejo-runner` (incidente 2026-08-17) |
| Deploy para logo após o migrate ("Done." e nada mais, EXIT=0) | `docker compose run` anexa stdin por padrão — o container consome o resto do script que vai no pipe do `bash -s`; o bash chega a EOF e termina sem rodar o rollout | O script já usa `< /dev/null` no `run --rm` do migrate (não remover); sintoma visto 2026-08-17 no primeiro deploy |
| Build falha: `network mode "stack_default" not supported by buildkit` | BuildKit (drivers docker e docker-container) recusa rede bridge custom no `--network` | O script builda com `--network host` + proxy socat `teqo-1313-build-proxy` (na `stack_default`, publicado em 127.0.0.1:5433, criado idempotentemente com `restart: unless-stopped`) + `DATABASE_URL` reescrita para o loopback |
| Build OOM no homeserver | Laptop 8c/16GB com o stack ativo (~12GB livres medidos) | Re-dispatch; se recorrente, item futuro: build na workstation com túnel |
| Build do runner falha: `relation "..." does not exist` no `next build` | Migration nova criou tabela lida em geração estática. Pré-OPS66 a ordem era build→migrate e o deploy morria aqui para sempre (incidente 2026-08-18, S2) | Pós-OPS66 não deve ocorrer: migrate roda antes do build do runner. Se reaparecer, confira no log se o passo migrate rodou; recovery manual: `docker build --target migrator` + `docker run --rm --network stack_default --env-file ~/stack/teqo-1313.env localhost:5000/teqo-1313-migrator:<sha>` e re-dispatch do workflow |
| `checkout@v5` falha no job `host` | Label host do act_runner | Fallback: baixar o script direto do Forgejo (`curl -s https://git.solla.dev/fsolla/teqo/raw/branch/main/scripts/deploy-homeserver.sh`) |
| Migrate falha | Drift/erro de schema | Job vermelho; site segue no container antigo; corrigir e re-mergear |
| Smoke falha pós-up | Regressão de runtime | Rollback automático (restore + `up -d`) + job vermelho; investigar |
| Sintoma | Causa | Tratamento |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Job verde sem deploy ("stale run") | Push mais novo venceu; o deploy antigo saiu da fila | Nada a fazer — o run do SHA novo deploya |
| Job verde sem deploy ("already deployed") | O container rodando já tem a revision do SHA do job (ex.: `workflow_dispatch` duplicado da mesma HEAD) | Nada a fazer — o site já roda esse SHA. Forçar rebuild da MESMA HEAD não é suportado via dispatch: edite o tag da imagem no compose (`image: teqo-1313:<sha>-rebuild`) e `docker compose up -d`, ou espere um commit novo |
| Gate `gate` vermelho (erro de git/`.dockerignore`) | SHA deployado ilegível para o git (ex.: história reescrita) ou `.dockerignore` corrompido no checkout | Fail-open: suite roda; deploy pula (nunca deploy às cegas). Corrigir a causa e esperar a próxima janela (auto-cura). Se `ssh homeserver` estiver fora, o gate lê revision vazia e roda tudo (verde) — checar tailnet se a suite roda sem deploy recorrente |
| Sem revision no container (label ausente no compose) | O compose do homeserver não define `org.opencontainers.image.revision` (deploy pré-OPS53 ou edição manual) | Degradação conservadora: toda janela roda suite + rebuild (verde). Corrigir adicionando o label ao serviço `teqo-1313` no compose e re-deployando |
| Todo job docker quebra com `exec: "node": executable file not found in $PATH` | `runner.envs.PATH` do `~/.forgejo-runner/config.yaml` (workstation) com paths só de host (nvm/bun) — o container perde o node do toolcache (`/opt/acttoolcache`); edição do config exige o toolcache primeiro (ver comentário no próprio config) | Corrigir o PATH no config (toolcache primeiro — ver comentário no próprio arquivo) + `systemctl --user restart forgejo-runner` (incidente 2026-08-17) |
| Deploy para logo após o migrate ("Done." e nada mais, EXIT=0) | `docker compose run` anexa stdin por padrão — o container consome o resto do script que vai no pipe do `bash -s`; o bash chega a EOF e termina sem rodar o rollout | O script já usa `< /dev/null` no `run --rm` do migrate (não remover); sintoma visto 2026-08-17 no primeiro deploy |
| Build falha: `network mode "stack_default" not supported by buildkit` | BuildKit (drivers docker e docker-container) recusa rede bridge custom no `--network` | O script builda com `--network host` + proxy socat `teqo-1313-build-proxy` (na `stack_default`, publicado em 127.0.0.1:5433, criado idempotentemente com `restart: unless-stopped`) + `DATABASE_URL` reescrita para o loopback |
| Build OOM no homeserver | Laptop 8c/16GB com o stack ativo (~12GB livres medidos) | Re-dispatch; se recorrente, item futuro: build na workstation com túnel |
| Build do runner falha: `relation "..." does not exist` no `next build` | Migration nova criou tabela lida em geração estática. Pré-OPS66 a ordem era build→migrate e o deploy morria aqui para sempre (incidente 2026-08-18, S2) | Pós-OPS66 não deve ocorrer: migrate roda antes do build do runner. Se reaparecer, confira no log se o passo migrate rodou; recovery manual: `docker build --target migrator` + `docker run --rm --network stack_default --env-file ~/stack/teqo-1313.env localhost:5000/teqo-1313-migrator:<sha>` e re-dispatch do workflow |
| `checkout@v5` falha no job `host` | Label host do act_runner | Fallback: baixar o script direto do Forgejo (`curl -s https://git.solla.dev/fsolla/teqo/raw/branch/main/scripts/deploy-homeserver.sh`) |
| Migrate falha | Drift/erro de schema | Job vermelho; site segue no container antigo; corrigir e re-mergear |
| Smoke falha pós-up | Regressão de runtime | Rollback automático (restore + `up -d`) + job vermelho; investigar |
## Segurança (decisão deliberada)

View file

@ -28,6 +28,7 @@ flowchart LR
**Opções consideradas:** A | B | C
**Recomendação:** A — reordenar o script movendo o migrate para antes do build do runner, mantendo o `compose run teqo-1313-migrate` como caminho canônico (o swap passa a ser feito logo após o build do migrator). É a opção 1 da própria intenção, sem custo adicional (o migrate e o build do migrator já rodavam em todo deploy — só mudam de posição) e sem caminho paralelo ao serviço de maintenance.
**Rejeitadas:**
- **B — `payload migrate` pré-check dentro do build do runner:** efeito colateral de escrita no banco de prod a partir de um processo de build; contradiz o desenho deliberado do Dockerfile ("migrations run separately through the migrator") e a decisão (B) do OPS53. Qualquer build CI em ambiente errado migraria o banco de prod.
- **C — `docker run --rm --network stack_default --env-file ~/stack/teqo-1313.env localhost:5000/teqo-1313-migrator:<sha>` antes do build do runner** (o comando manual de recuperação do incidente): evita o swap precoce, mas duplica a definição do serviço de maintenance do compose (envs/networks/labels) e cria caminho paralelo ao serviço canônico que OPS51/53 e o runbook documentam. O swap precoce (A) é inofensivo: nada referencia o tag do runner até o `compose up -d`, que só roda depois do push.

View file

@ -94,7 +94,10 @@ describe('scripts/deploy-homeserver.sh (OPS53 deploy pipeline)', () => {
// The invariant OPS66 depends on: the migrator image can always be built,
// even before the new migrations exist in the DB.
const dockerfile = readFileSync(join(repoRoot, 'Dockerfile'), 'utf8')
const migratorStage = dockerfile.slice(dockerfile.indexOf('AS migrator'), dockerfile.indexOf('AS builder'))
const migratorStage = dockerfile.slice(
dockerfile.indexOf('AS migrator'),
dockerfile.indexOf('AS builder'),
)
expect(migratorStage).toContain('CMD ["pnpm", "migrate"]')
expect(migratorStage).not.toContain('next build')
const builderStage = dockerfile.slice(dockerfile.indexOf('AS builder'))