mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
fix(deploy): reverte package.json para desbloquear o deploy — cache deps do BuildKit
O deploy defea6c645falhou 2x: a mudança do script generate:importmap em package.json invalidou a cache da camada deps do Dockerfile no homeserver, e o pnpm install re-rodou do zero — o postinstall do sharp@0.32.6 (transitivo) estourou o timeout baixando o libvips de objects.githubusercontent.com ('sharp: Installation error: Request timed out'; o git fetch de github.com funciona — o release vai por outro hostname da CDN). Produção intocada (falha pré compose swap). Reverte package.json ao byte do estado cacheado (a9f0c61e) — o install nem roda. Remove o wrapper generate-importmap.mjs (desligado vira dead code); proteção do importMap fica com o guard CI+deploy + pin unit + contrato. Hardening do deps documentado no post-mortem (retry do install / libvips via apk / proxy), changelog do follow-up incluído.
This commit is contained in:
parent
fea6c64514
commit
39fd082055
4 changed files with 16 additions and 49 deletions
|
|
@ -0,0 +1 @@
|
|||
**Admin em branco — follow-up: deploy bloqueado pelo reinstall do deps, package.json revertido (2026-08-27):** o fix do importMap (#926, main em `fea6c645`) não conseguia PUBLICAR: o deploy manual falhou 2× no build do migrator — a mudança de `package.json` (script `generate:importmap` → wrapper) invalidou a cache BuildKit da camada `deps` do Dockerfile, o `pnpm install --frozen-lockfile` re-rodou do zero e o `postinstall` do `sharp@0.32.6` (transitivo) estourou o timeout baixando o libvips de `objects.githubusercontent.com` no homeserver (`sharp: Installation error: Request timed out`; o `git fetch` de github.com funciona — o release vai por hostname diferente da CDN). Produção ficou intocada (falha antes do compose swap). Correção: `package.json` revertido ao byte do estado cacheado (`a9f0c61e`) — a cache do `deps` volta a valer e o install nem roda; wrapper `scripts/generate-importmap.mjs` **removido** (ficaria desligado — dead code); proteção mantida pelo guard `check-importmap-s3.mjs` (ci-pr.yml + verify do deploy) + pin unit + contrato. Dívida documentada no post-mortem: hardening da camada `deps` (retry do install / libvips via apk / proxy do download) — sem ele, qualquer mudança futura em package.json/pnpm-lock/pnpm-workspace volta a bustar a cache e travar o deploy igual. Ação: re-dispatch manual do `deploy.yml` (o guard do HEAD exige main atual; o `verify` já passou 19m verde no run anterior).
|
||||
|
|
@ -58,21 +58,22 @@ Regeneração do importMap com envs S3\_\* dummy — o diff foi de exatamente +2
|
|||
|
||||
## 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 | implementada agora (mesmo PR) |
|
||||
| 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 |
|
||||
| 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 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); wrapper do `generate:importmap` que injeta as envs dummy — a regeneração local nunca mais orfa o handler; contrato compartilhado da chave/prefixo e das envs; doc no AGENTS.md.
|
||||
**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.
|
||||
|
||||
**Estratégia documentada (cara):** gerar o importMap no build (elimina a classe: artefato gerado não drift; toca o pipeline do homeserver); tornar o s3Storage incondicional (estabiliza o importMap; muda storage local e caminho de media); smoke de deploy que abre /admin em headless e asserta o mount da raiz Payload; fail-fast estruturado quando getFromImportMap retorna undefined.
|
||||
**Estratégia documentada (cara):** gerar o importMap no build (elimina a classe: artefato gerado não drift; toca o pipeline do homeserver); tornar o s3Storage incondicional (estabiliza o importMap; muda storage local e caminho de media); smoke de deploy que abre /admin em headless e asserta o mount da raiz Payload; fail-fast estruturado quando getFromImportMap retorna undefined; hardening da camada `deps` do Dockerfile contra o reinstall completo no homeserver.
|
||||
|
||||
## Lições
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
"changelog:build": "node scripts/build-changelog.mjs",
|
||||
"changelog:read": "node scripts/build-changelog.mjs --stdout",
|
||||
"changelog:check": "node scripts/build-changelog.mjs --check",
|
||||
"generate:importmap": "node scripts/generate-importmap.mjs",
|
||||
"generate:importmap": "cross-env NODE_OPTIONS=\"--no-deprecation --conditions=react-server\" payload generate:importmap",
|
||||
"generate:types": "cross-env NODE_OPTIONS=\"--no-deprecation --conditions=react-server\" payload generate:types",
|
||||
"migrate": "cross-env NODE_OPTIONS=\"--no-deprecation --conditions=react-server\" payload migrate",
|
||||
"migrate:create": "cross-env NODE_OPTIONS=\"--no-deprecation --conditions=react-server\" payload migrate:create",
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Wrapper for `payload generate:importmap` that always injects dummy S3_*
|
||||
* envs (when unset) so the generated importMap carries the
|
||||
* S3ClientUploadHandler entry — regenerating without the S3_* envs silently
|
||||
* orphans it and the admin goes blank in production (class
|
||||
* OPS69/OPS72/OPS73). Dummy values are fine: the generator only iterates the
|
||||
* config, it never connects to the bucket.
|
||||
*/
|
||||
import { spawnSync } from 'node:child_process'
|
||||
|
||||
import { S3_STORAGE_ENV_KEYS } from './lib/importMapContract.mjs'
|
||||
|
||||
const DUMMY = {
|
||||
S3_BUCKET: 'dev-dummy-bucket',
|
||||
S3_ENDPOINT: 'http://127.0.0.1:3900',
|
||||
S3_ACCESS_KEY_ID: 'dev-dummy-access-key',
|
||||
S3_SECRET_ACCESS_KEY: 'dev-dummy-secret-key',
|
||||
}
|
||||
|
||||
const env = {
|
||||
...process.env,
|
||||
// Same NODE_OPTIONS as before — the payload CLI loads server-only modules.
|
||||
NODE_OPTIONS: '--no-deprecation --conditions=react-server',
|
||||
...Object.fromEntries(
|
||||
S3_STORAGE_ENV_KEYS.map((key) => [key, process.env[key]?.trim() || DUMMY[key]]),
|
||||
),
|
||||
}
|
||||
|
||||
const result = spawnSync('payload', ['generate:importmap'], {
|
||||
stdio: 'inherit',
|
||||
env,
|
||||
})
|
||||
|
||||
process.exit(result.status ?? 1)
|
||||
Loading…
Reference in a new issue