Pular para o conteúdo
Development

Testar um gate de deploy acabou fazendo o deploy da coisa que eu estava testando

Por Victor Da Luz
astrocloudflarecidev-logsite

O pipeline de deploy do imperfectsystems.com tinha exatamente um gate: “compilou ou não.” Isso já era verdade quando o GitHub Actions rodava tudo, e continuou verdade depois que eu mudei o deploy para o Cloudflare Workers Builds algumas semanas atrás. Nada checava tipos, nada checava formatação, e o auto-merge do dependabot que costumava se apoiar nesse mesmo sinal fraco tinha acabado de ser desligado junto com o resto do Actions. Hora de adicionar gates que realmente significam algo: astro check e Prettier, rodando antes de cada deploy.

A configuração foi a parte fácil

Copiei o .prettierrc do vdaluz.com palavra por palavra, adicionei @astrojs/check e prettier-plugin-astro como devDependencies, conectei os scripts check / format / format:check. Sem ESLint dessa vez, o repositório é pequeno o suficiente para não valer o custo de configuração, a mesma decisão que o spike que definiu esse issue já tinha tomado.

Então eu de fato rodei o astro check em vez de assumir que ia passar, porque “provavelmente passa hoje” numa descrição de issue é um chute, não um resultado.

O gate encontrou algo real na primeira rodada

Um erro: astro.config.mjs:12:5 - Type '{ themes: { light: string; dark: string; }; defaultColor: false; }' is not assignable to type 'Partial<ShikiConfig>'. Vindo do objeto shikiConfig compartilhado que este site e o vdaluz.com importam do @vdaluz/astro-blog.

Meu primeiro palpite foi drift de versão. Este repositório ainda estava fixado numa versão mais antiga do Astro; o vdaluz.com roda uma mais nova. Subi a versão, reinstalei, rodei a checagem de novo. Mesmo erro, palavra por palavra. Teoria errada.

Então fui de fato olhar como o próprio astro.config.mjs do vdaluz.com lida com o mesmo import, em vez de continuar chutando. Ele já tinha o fix, com um comentário explicando:

// The package types `themes` values as plain strings, so cast to satisfy astro check.
shikiConfig: /** @type {Partial<import('astro').ShikiConfig>} */ (shikiConfig),

O pacote compartilhado tipa themes.light/themes.dark como string genérica, não a união de nomes literais de tema que o próprio tipo do Astro espera. Não era um problema de versão, só um tipo que nunca esteve totalmente certo, aceito silenciosamente porque nada aqui nunca tinha rodado astro check antes. Copiei o mesmo cast. Erro resolvido. Mantive o bump de versão do Astro mesmo assim, já que reduz o drift entre os dois sites e nada quebrou, mas nunca foi ele o fix.

Verificar o gate significou testá-lo contra alguma coisa, e foi aí que ficou interessante

Eu não queria só configurar o novo comando de build no dashboard da Cloudflare e assumir que funcionava. Eu queria ver rodando de fato. A API do Workers Builds tem um endpoint para disparar manualmente um build contra qualquer branch que você nomear, então apontei um para minha branch de feature para checar o novo comando com gate antes de mergear qualquer coisa na main.

Voltou verde. Bom. Só que o log tinha uma linha a mais do que eu esperava:

Executing user deploy command:  npx wrangler deploy --config wrangler.toml dist/server/entry.mjs
✨ Success! Uploaded 7 files (23 already uploaded) (0.91 sec)
Success: Deploy command completed

O passo de deploy do gatilho não checa qual branch você mandou buildar. Ele simplesmente roda, incondicionalmente, depois de qualquer build bem-sucedido. Apontar o gatilho de produção para uma branch de feature para “só testar o comando de build” também mandou aquela branch de feature direto para produção, antes de qualquer merge, antes de qualquer review. wrangler deployments list confirmou: um deploy novinho, com timestamp da minha chamada manual à API, não de um git push.

O dano real aqui foi próximo de zero. A branch só mexia em tooling e formatação, nada que um visitante notaria, e eu já tinha revisado o diff de cada mudança de formatação antes disso. Mas o mecanismo é a parte que vale lembrar: uma ação de “deixa eu só testar isso” chegou em produção sem nenhum passo de confirmação no meio, porque assumi que um build disparado manualmente era mais seguro do que era. Não era um dry run. Não existe dry run.

Uma vez que percebi, o fix foi só colocar a main em dia com o que já estava no ar: mergear a branch, verificar que o build real disparado por push (não um manual) também ficou verde, pronto. O que aconteceu, hash de commit e tudo, ligado a um git push de verdade, gates passando de verdade dessa vez.

O que eu faria diferente

Testar mudanças de comando de build mergeando primeiro, não apontando o gatilho de deploy de produção para código ainda não mergeado e torcendo para o parâmetro “branch” significar o que parece significar. Se uma API deixa você especificar um alvo, isso não é o mesmo que ela respeitar um limite. Pergunte o que acontece em caso de sucesso antes de descobrir vendo acontecer.

Leitura relacionada

Development

O CSP que só quebrou em produção

Quatro falhas atrás de um único header: middleware morto, regras de _headers que se combinam em vez de sobrescrever, um worker de blob URL sob script-src, e um script que só o edge injeta.

Ler

Você também pode achar útil

Proton

Proton VPN

VPN comercial com filtragem NetShield e interruptor de desligamento automático.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
Proton

Proton Mail

E-mail criptografado de ponta a ponta, com arquitetura de acesso zero.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
NordPass

NordPass

Gerenciador de senhas da equipe por trás da NordVPN, com um plano gratuito.

Como afiliado da NordPass, ganho com compras qualificadas.

Saiba mais