diff --git a/docs/changelog/2026-08-27-deploy-sharp-override.md b/docs/changelog/2026-08-27-deploy-sharp-override.md new file mode 100644 index 00000000..90fe149e --- /dev/null +++ b/docs/changelog/2026-08-27-deploy-sharp-override.md @@ -0,0 +1 @@ +**Deploy destravado — override sharp@0.32.6 → 0.34.2: o pnpm install deixa de depender de github releases (2026-08-27):** os 4 deploys falhados desde 10:59 UTC morriam na camada `deps` do Dockerfile: o `postinstall` do `sharp@0.32.6` (dependência do `@imgly/background-removal-node`, usado só pelo script local `resize-images.mjs`) baixa o libvips de `objects.githubusercontent.com` e estoura timeout no homeserver (`sharp: Installation error: Request timed out`) — o egress não conclui downloads de github releases embora o `git fetch` funcione (hostname distinto da CDN); a cache do BuildKit não esconde a classe porque o `builder prune` do pós-deploy limpa a camada a cada deploy bem-sucedido. Fix estrutural (PR #929, reverted em outro eixo o #927 que tentou a rota da cache): override no `pnpm-workspace.yaml` força o sharp transitivo para 0.34.2 (versão direta do app) — a partir do 0.33 os binários vêm de pacotes do **npm registry** (`@img/sharp-libvips-*`), alcançável pelo homeserver; lockfile regenerado remove o sharp@0.32.6 e toda a subárvore do prebuild-install (−296 linhas, tar-fs/simple-get/bare-\*/etc.). Verificação: `pnpm why sharp` (imgly → 0.34.2 via override; next/payload → 0.34.5), smoke do `resize-images` (processamento webp OK), format/lint/tsc verdes, suíte int completa verde (78/712), gate:ci verde, PR CI verde. **Deploy do main (`4d6533c0`, run 33074305879) verde: verify 19m + deploy 16m — e o admin voltou a renderizar em produção** (login do Payload com formulário, 0 erros de console; verificação read-only via browser, confirmação final do humano pendente). Candidato a registro no runbook: a regra "nenhum binário de github releases no `pnpm install` de produção" — qualquer dep futura que baixe de github.com/objects.githubusercontent.com na instalação volta a travar o deploy. diff --git a/docs/postmortems/2026-08-26-admin-branco-importmap-s3.md b/docs/postmortems/2026-08-26-admin-branco-importmap-s3.md index 2cbc981d..5c3f3a77 100644 --- a/docs/postmortems/2026-08-26-admin-branco-importmap-s3.md +++ b/docs/postmortems/2026-08-26-admin-branco-importmap-s3.md @@ -4,24 +4,24 @@ ## Registro -| Campo | Valor | -| ------------------- | ---------------- | -| Data do post-mortem | 2026-08-26 | -| Severidade | crítica | -| Ambiente | prod | -| Issue(s) | sem Issue | -| PR do fix | — (em andamento) | -| Detectado por | humano | +| Campo | Valor | +| ------------------- | --------------------------------------------------- | +| Data do post-mortem | 2026-08-26 | +| Severidade | crítica | +| Ambiente | prod | +| Issue(s) | sem Issue | +| PR do fix | #926 (+ #927 e #929 para os desbloqueios do deploy) | +| Detectado por | humano | ## Timeline -| Momento | Data/hora | Evento | -| ------------------ | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Início provável | 2026-08-23 | commit 1c865bd8 (refactor "E1 simplify — pin loading/retry/stale-quirk no spec e tipo local") regenerou o importMap sem as envs S3\_\*, removendo a entrada do handler | -| Detecção | 2026-08-26 | relato do usuário: admin em branco em produção | -| Correção mergeada | em andamento | PR ainda sem número | -| Deploy | ainda não feito | dispatch manual do deploy.yml (só humano) | -| Verificado em prod | não | aguarda deploy + confirmação do humano | +| Momento | Data/hora | Evento | +| ------------------ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Início provável | 2026-08-23 | commit 1c865bd8 (refactor "E1 simplify — pin loading/retry/stale-quirk no spec e tipo local") regenerou o importMap sem as envs S3\_\*, removendo a entrada do handler | +| Detecção | 2026-08-26 | relato do usuário: admin em branco em produção | +| Correção mergeada | 2026-08-27 | PRs #926 (importMap +2 linhas + guard/pin), #927 (package.json revertido — desbloqueio 1 do deploy), #929 (override sharp — desbloqueio 2 do deploy) | +| Deploy | 2026-08-27 | dispatch manual do deploy.yml (run 33074305879, 12:56 UTC) — verify 19m + deploy 16m verdes, revision `4d6533c0` | +| Verificado em prod | 2026-08-27 | verificação read-only via browser: `/admin/login` renderiza o formulário (Email/Senha/Login, título "Login - Payload"), 0 erros de console; confirmação final do humano pendente | ## O bug @@ -54,22 +54,22 @@ Regeneração do importMap com envs S3\_\* dummy — o diff foi de exatamente +2 - Suíte: unit completa 284 arquivos / 2682 testes verdes; `tsc --noEmit` e lint exit 0 - E2E original: admin servido com S3\_\* dummy (PORT 4093) — login renderiza (título "Login - Payload", form Email/Senha), login admin@test.invalid funciona, dashboard "Painel de Controle - Payload" monta, log do servidor com 0 `getFromImportMap`, 0 erros de console - CI: gate:fast verde (284 arquivos, 2682 testes) -- Prod: não verificado — aguarda deploy manual + confirmação do humano +- Prod: deploy do run 33074305879 (revision `4d6533c0`) concluído verde; verificação read-only via browser (2026-08-27): `/admin/login` renderiza o formulário com 0 erros de console — confirmação final do humano pendente ## Prevenção -| Estratégia | Custo | Estado | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Pin unit `importMapS3UploadHandler.unit.spec.ts` (falha se a entrada sumir) | barata | implementada agora (mesmo PR) | -| Guard `scripts/check-importmap-s3.mjs` no ci-pr.yml (content guards) e no job verify do deploy.yml | barata | implementada agora (mesmo PR) | -| Wrapper `scripts/generate-importmap.mjs` no `pnpm generate:importmap` (injeta S3\_\* dummy quando ausentes) | barata | removida no follow-up (2026-08-27) — a mudança de package.json invalida a cache BuildKit da camada `deps` no homeserver e força reinstall cujo `postinstall` do `sharp@0.32.6` falha (timeout do libvips em objects.githubusercontent.com; 2 deploys falhos). Re-ligar junto com o hardening do Dockerfile | -| Contrato compartilhado `scripts/lib/importMapContract.mjs` (chave + prefixo do handler, chaves das envs S3) | barata | implementada agora (mesmo PR) | -| AGENTS.md: instrução das envs S3\_\* no generate:importmap + referência aos guards | barata | implementada agora (mesmo PR) | -| Gerar o importMap no BUILD (prebuild com S3\_\* via BuildKit secrets) em vez de commitá-lo | cara | documentada — não implementada neste fluxo | -| Tornar o plugin s3Storage incondicional no config (adaptador local em dev) | cara | documentada — não implementada neste fluxo | -| Smoke real de deploy: abrir /admin em headless e assertar o mount da raiz Payload (não só HTTP 200) | cara | documentada — não implementada neste fluxo | -| Fail-fast/erro estruturado quando getFromImportMap retorna undefined (hoje é console.error silencioso no log do servidor) | cara | documentada — não implementada neste fluxo | -| Hardening da camada `deps` do Dockerfile (retry do `pnpm install` / libvips via apk / proxy do download do sharp) — qualquer mudança em package.json/pnpm-lock/pnpm-workspace busta a cache e o egress do homeserver para objects.githubusercontent.com não conclui downloads | cara | documentada — não implementada neste fluxo | +| Estratégia | Custo | Estado | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Pin unit `importMapS3UploadHandler.unit.spec.ts` (falha se a entrada sumir) | barata | implementada agora (mesmo PR) | +| Guard `scripts/check-importmap-s3.mjs` no ci-pr.yml (content guards) e no job verify do deploy.yml | barata | implementada agora (mesmo PR) | +| Wrapper `scripts/generate-importmap.mjs` no `pnpm generate:importmap` (injeta S3\_\* dummy quando ausentes) | barata | removida no follow-up (2026-08-27) — a mudança de package.json invalida a cache BuildKit da camada `deps` no homeserver e força reinstall cujo `postinstall` do `sharp@0.32.6` falha (timeout do libvips em objects.githubusercontent.com; 2 deploys falhos). Re-ligar junto com o hardening do Dockerfile | +| Contrato compartilhado `scripts/lib/importMapContract.mjs` (chave + prefixo do handler, chaves das envs S3) | barata | implementada agora (mesmo PR) | +| AGENTS.md: instrução das envs S3\_\* no generate:importmap + referência aos guards | barata | implementada agora (mesmo PR) | +| Gerar o importMap no BUILD (prebuild com S3\_\* via BuildKit secrets) em vez de commitá-lo | cara | documentada — não implementada neste fluxo | +| Tornar o plugin s3Storage incondicional no config (adaptador local em dev) | cara | documentada — não implementada neste fluxo | +| Smoke real de deploy: abrir /admin em headless e assertar o mount da raiz Payload (não só HTTP 200) | cara | documentada — não implementada neste fluxo | +| Fail-fast/erro estruturado quando getFromImportMap retorna undefined (hoje é console.error silencioso no log do servidor) | cara | documentada — não implementada neste fluxo | +| Hardening da camada `deps` do Dockerfile (retry do `pnpm install` / libvips via apk / proxy do download do sharp) — o egress do homeserver para objects.githubusercontent.com não conclui downloads | cara | resolvida em grande parte pelo PR #929 (override sharp → binários via npm registry, alcançável); retry/proxy seguem documentados para deps futuras que usem github releases | **Estratégia implementada:** pin unit que falha se o handler sumir do importMap; guard de CI+deploy que regenera com S3\_\* dummy e falha em divergência (drift + restore do arquivo); contrato compartilhado da chave/prefixo e das envs; doc no AGENTS.md. O wrapper do `generate:importmap` foi removido no follow-up (a mudança de package.json que o ligava quebrou o deploy — ver tabela); a proteção fica com o guard + pin.