en
· 3 min de leitura

O pull request que parece bem

Diff pequeno, testes verdes, descrição clara, aprovação rápida. A anatomia da mudança que derrubou a produção mesmo assim.

auditengineering

O pull request perigoso não é a refatoração de mil linhas. Todo mundo lê aquele com cuidado, ou se recusa a fazer o merge. O perigoso tem quarenta linhas, título claro, passa em todos os testes e é aprovado em oito minutos por alguém que confia no autor. Já rastreei dezenas de incidentes até uma mudança assim, e elas compartilham uma anatomia.

Mudou um valor padrão

A forma mais comum: uma função tinha um parâmetro com valor padrão, e o padrão mudou. Timeout de 30 segundos para 5. Tamanho de página de 50 para 500. Uma flag booleana que era false agora é true. O diff é uma linha. Todo chamador que nunca definiu o parâmetro explicitamente, que é a maioria, acabou de mudar de comportamento sem aparecer no diff. Os testes passaram porque os testes definem o parâmetro. A produção não.

Tocou em algo compartilhado

Um helper num arquivo de utilitários, uma classe base, um middleware, um modelo de banco que seis funcionalidades leem. A mudança estava correta para a funcionalidade em que o autor trabalhava. Estava errada para duas das outras cinco, e nenhuma delas tinha um teste que notaria, porque os testes delas mockam a coisa compartilhada. O revisor leu o diff e viu uma mudança razoável num helper. Ninguém leu os chamadores, porque a ferramenta mostra o diff, não o raio de explosão.

Removeu uma verificação que parecia redundante

Uma checagem de nulo que 'nunca pode acontecer'. Uma validação que 'o frontend já faz'. Uma guarda em volta de um retry que parecia paranoica. Alguém limpou de passagem, num pull request sobre outra coisa, e o revisor concordou porque o código ficou mais limpo. A verificação estava ali por causa de um incidente de dois anos atrás de que ninguém no time atual se lembra. O incidente voltou.

Mudou algo que o diff não mostra

A mudança adicionou uma coluna e começou a escrever nela no mesmo deploy. Tudo bem na máquina do desenvolvedor, onde a migração e o código sobem juntos. Em produção o código chegou a três instâncias antes de a migração terminar, e por noventa segundos toda escrita falhou. Ou o inverso: a migração removeu uma coluna que o código antigo ainda lia, e o código antigo ainda estava rodando durante o rollout. O diff estava correto. A ordem não, e ordem é invisível num diff.

Serialização é a outra invisível. Um campo renomeado numa resposta de API. Uma data que era string agora é timestamp ISO. Um valor de enum escrito diferente. Um número que era inteiro agora é decimal. Os testes do backend passaram porque testam o backend. O app mobile lançado há três meses, que não pode ser atualizado em todo celular hoje à noite, interpretava o formato antigo. Esse é o mais silencioso, porque muitas vezes falha só para alguns clientes, e os erros aparecem do lado deles, não do seu.

Como reviso o que parece bem

Parei de confiar na minha sensação de que uma mudança é pequena. Em vez disso pergunto, mecanicamente, para todo pull request independentemente do tamanho: algum padrão mudou? Alguma coisa tocada aqui é importada de mais de um lugar? Alguma coisa foi removida, e a descrição diz por que era seguro? A ordem do deploy importa? Algum formato que sai do sistema mudou? Leva cinco minutos e é chato. Os pull requests que falham nessas perguntas são quase sempre os que teriam parecido bem.

Esses cinco minutos são toda a diferença entre uma revisão e uma aprovação. Uma aprovação diz que o diff é razoável. Uma revisão diz que o sistema ainda vai funcionar depois dele.