0027 — Adota o smoke de produção pós-deploy e a identidade de build¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-15 · Decidido em: 2026-09-08
Contexto¶
Esta não é uma decisão nova: é o registro local de que o central-backend adotou uma
norma da casa. O porquê está no ADR central
0031 — Smoke de produção pós-deploy
e na página engenharia/smoke-producao
(constituição §9, versão 1.3.0). Este documento existe para o rastro do quando e do como
neste repo — não re-litiga a escolha da casa.
O que a norma corrige é um ponto cego que o central-backend tem em dose dupla:
- O
POST /api/ci/deployé assíncrono — retorna sucesso e o pipeline fica verde antes de o container novo servir. "Deployado" sem nada ter verificado o resultado. - O app deploya a si mesmo por esse endpoint (0022). Um deploy ruim aqui não derruba só este app: derruba o control-plane que toda a frota usa para deployar. O incidente que escreveu a norma da URL flavor-agnóstica foi exatamente esse.
- O app tem dois deploys da mesma versão (jar e native, 0018).
Sem discriminador, os dois
/healtheram indistinguíveis.
Decisão¶
Adotar as quatro peças da norma, no mesmo PR.
-
XADM_COMMITatravessa o pipeline inteiro. O CI passa--build-arg XADM_COMMIT=<sha>nos dois builds;DockerfileeDockerfile.nativedeclaramARG/ENVtarde (depois doCOPY, no estágio final) — no topo, oARGinvalidaria o cache de tudo abaixo e onativeCompile(~13 min) rodaria de novo a cada commit.A env se chamava
SOURCE_COMMIT— e o nome estava erradoCorrigido em 2026-09-09, depois da v0.8.0.
SOURCE_COMMITé variável predefinida do Coolify: em recurso pull-only ele a injeta em runtime com o literalHEAD, por cima doENVda imagem. Este app foi onde o defeito apareceu — o build passou--build-arg SOURCE_COMMIT=81cbb619…, a imagem no registry carregava o sha, e produção respondia"commit":"HEAD". A camada 1 do smoke passou por liveness sem provar nada. Cura:XADM_COMMIT(namespace da casa) +xadm-comum-web0.9.0, que trataHEADcomo ausente. Norma: smoke-producao §6 e coolify §Carimbar o commit. -
xadm-comum-websobe para0.9.0(era0.8.0no corte original), que lê essa env e emitecommitno/health(e usa o mesmo sha comoreleasedo Sentry/GlitchTip quandoSENTRY_RELEASEnão está setada). O mesmo bump trazflavor(native|jvm), que responde "qual dos dois deploys está no ar". - Job
smokenopipeline.yml, depois dodeploy, rodando osmoke.pyda casa contra as rotas declaradas emdocs/app.json→smoke.routes. Reprovou → reverte para a tag imutável<imagem>:<sha anterior>-<target>, confirma a reversão e fica vermelho. CENTRAL_DEPLOY_URLdeixa de carregar flavor de build — passa ahttps://central-backend.xadm.biz/api/ci/deploy. Ver "Consequências".
Correção (2026-09-15): a reversão do item 3 não é automática. O
smoke.pypede ao control-plane a tag imutável, e oPOST /api/ci/deploysó aceita a tag móvel<target>-amd64— responde400 invalid_image. O smoke reprova e reporta o alvo; o operador reverte à mão (Deploy, Reversão). A norma da casa registra o rollback automático como pendente no control-plane.
Alternativas descartadas¶
- Seguir só com o
/healthcomo gate./healthverde é liveness, não "as rotas respondem": o JWKS pode estar vazio, o banco pode ter subido sem a chave, e o/healthdeste app é 200-fixo de propósito (não flapa por indicador JDBC — 0016). Liveness verde com JWKS quebrado derruba o login de toda a frota em silêncio. versaocomo discriminador de entrega. Não distingue: dois deploys da mesma versão (umworkflow_dispatchsem bump) servem a mesma string. Semcommit, o smoke não tem nem critério de identidade nem alvo de rollback.- Declarar a camada 3 (log-guarantee) agora. Declarar
smoke.glitchtipsem cadastrar oGLITCHTIP_API_TOKENreprova por desenho — é defeito de configuração, não aviso. O bloco fica de fora até o secret existir; é o self-skip previsto na norma, não omissão.
Consequências¶
- O
CENTRAL_DEPLOY_URLmudou de host. Eracentral-backend-jar.xadm.biz— flavor de build numa URL que outro sistema consome, exatamente o que a constituição §9 proíbe desde o incidente em que parar o jar numa promoção a native derrubou oPOST /api/ci/deployda frota (503). Pré-condição operacional:central-backend.xadm.biztem de rotear para um recurso no ar que sirva/api/ci/deploy. Enquanto não roteia, o deploy da frota inteira falha nocurl -fsS. - Rotas do smoke começam públicas.
/health,/.well-known/jwks.jsone/api/auth/jwks— as três que a frota e o PowerSync consomem sem credencial. Rotam2mentra quando houverSMOKE_M2M_TOKEN; rotasessionnão se aplica (este app rodamicronaut.security.enabled=false, postura do hub — 0016 — logo não há seam de sessão a expor). - A mesma lista serve dois gates: o e2e native afirma
≠404no binário antes do deploy; o smoke afirma o status esperado depois. - 404 autenticado passou a glitchar (efeito do bump da lib, 0.7.1). Rota morta batida por cliente com credencial vira evento no GlitchTip — é o sinal desejado, e a rede de runtime para a classe de defeito "AOT podou rota registrada" que motivou a mudança na lib.