Governança de IA · · 13 min de leitura
Produção nunca constrói: o PR como único caminho do código com IA
Se existe um jeito de mudar produção sem passar pelo repositório, ele será usado no dia em que a IA sugerir um atalho. Deploy é um pull request que troca a versão, e rollback também. Produção nunca compila: só roda o que já foi construído, testado e aprovado. Um validador recusa no PR o que a casa não aceita.
Por que “um caminho só” é a regra mais importante?
Porque todo caminho alternativo vai ser usado no dia de pressa, e a IA encontra o atalho antes de qualquer pessoa. Se a produção pode mudar por um acesso direto ao servidor, por um botão num painel, por um comando rodado à mão ou por um arquivo editado no lugar, os controles do pull request protegem só quem escolheu usá-los. O caminho estreito deixa de ser estreito no primeiro desvio.
Com IA isso fica mais agudo. Peça a um assistente com acesso ao terminal para "corrigir o erro em produção" e ele vai procurar o caminho mais curto até o objetivo: entrar no servidor, editar o arquivo, reiniciar o contêiner, rodar a migração na mão. Não é má-fé; é o que foi pedido. E o time que programa com IA produz mais mudanças do que antes, com o mesmo número de pessoas para revisar, como mostramos no texto que abre esta série. Um caminho só é o que impede que a revisão seja pulada justamente quando o volume cresce.
A regra vale igual para pessoa e máquina. O caminho não pergunta quem escreveu o código. Uma pessoa, um assistente de IA e um robô de atualização de dependências passam pelo mesmo pull request, com os mesmos checks e a mesma exigência de aprovação. E não existe lista de exceção: a regra que protege o ramo principal vale também para o administrador. No GitHub, as regras de repositório permitem deixar vazia a lista de quem pode contorná-las e, em nível de organização, aplicar a mesma proteção a vários repositórios de uma vez. Vazia é o valor certo.
O desenho fecha os atalhos um por um. A produção não tem porta de entrada aberta. A chave que o servidor usa para ler o repositório não tem permissão de escrita. Quem acompanha os deploys pode disparar um deploy, mas não alterar o servidor. E qualquer recurso criado ou alterado fora de um PR dispara alerta, porque no desenho isso só acontece por PR. Como vimos no texto sobre regra escrita, "só mude produção pelo PR" escrito num documento é pedido. Fechar os outros caminhos é mecanismo.
O erro comum é manter uma porta dos fundos "para emergências". Para amanhã: liste todos os jeitos pelos quais a sua produção muda hoje.
O que significa “produção nunca constrói”?
Significa que o servidor de produção não compila código, não instala dependências e não monta imagem. Ele só baixa uma imagem que a CI já construiu, testou e publicou, identificada por uma referência imutável, e a coloca para rodar.
Há três motivos, e o primeiro basta. O que roda passa a ser o que foi testado. Construir no servidor é um segundo build, do mesmo código, em outra hora, com outras versões de dependência. O artefato que passou pelos testes não é o que está em produção. A produção fica menor. Sem build, ela não precisa de compilador, de acesso a repositórios de pacotes nem de segredos de build: é superfície a menos. Some uma classe inteira de armadilhas. Um exemplo com o Docker: o comando que sobe os serviços de um arquivo de composição não reconstrói uma imagem que já existe. O serviço configurado para ser construído no servidor sobe na primeira vez e nunca mais recebe código novo, enquanto o registro do deploy diz que a versão nova entrou.
O SLSA, o padrão aberto de integridade da cadeia de software, organiza a mesma ideia em níveis de build. A partir do segundo nível, o build roda numa plataforma dedicada, não na máquina de alguém, e a origem do artefato fica registrada e assinada. Produção que compila é, por definição, um build fora da plataforma de build. O SSDF do NIST pede o mesmo por outro ângulo: proteger todas as formas de código contra acesso não autorizado e adulteração, e dar um meio de verificar a integridade do que se publica.
O fluxo, de ponta a ponta, tem cinco passos.
- O PR da aplicação passa pelos oito checks obrigatórios: lint, tipos, testes, segredos, análise estática, dependências, imagem e validador de deploy.
- Depois do merge, a CI constrói a imagem e a publica num repositório de imagens privado, marcada com o identificador do commit.
- Um PR no repositório de infraestrutura troca a versão daquela aplicação, no arquivo de produção, pela referência imutável da imagem nova.
- Um dono de código revisa, os checks passam e o PR é integrado.
- O servidor percebe a mudança, baixa a imagem e sobe o serviço, sem ler uma linha do código da aplicação.
A produção recebe imagem, não código.
E a versão é sempre exata. Nunca "latest", nunca imagem sem número. "Latest" quer dizer "o que foi publicado por último", e com ela o mesmo arquivo sobe coisas diferentes em dias diferentes, sem PR nenhum entre uma e outra. O erro comum é construir no servidor "porque é mais simples" e deixar para depois. Para amanhã: veja se os seus servidores de produção têm compilador, gerenciador de pacotes da linguagem ou clone do código das aplicações. Cada um é um sinal de que a produção constrói.
Como se faz rollback sem sair do Git?
Com outro pull request, que devolve a versão anterior da imagem no repositório de infraestrutura. Rollback fora do Git não existe.
O rollback é o momento mais perigoso da operação. Há pressão, há incidente, há alguém com acesso e vontade de resolver. Um rollback feito à mão no servidor, voltando o clone para um commit antigo ou subindo uma imagem velha direto, deixa o repositório dizendo uma coisa e a produção rodando outra. O deploy seguinte desfaz o rollback em silêncio ou reaplica o defeito. E ninguém sabe ao certo que versão está no ar, que é a primeira pergunta de qualquer incidente.
O PR de rollback é pequeno. Uma linha muda, a referência da imagem, e a revisão é rápida: esta é a versão que estava antes, com os checks verdes? A imagem anterior continua no repositório de imagens, então não há build no caminho da volta. E a volta deixa o mesmo rastro que a ida: quem pediu, quem aprovou, quando entrou.
Dado não volta com a imagem. Se a versão nova alterou a estrutura do banco, a versão anterior precisa continuar funcionando com a estrutura nova, e isso se resolve antes, desenhando migrações que acrescentam primeiro e removem só depois, quando nada mais depende do que sai. Rollback de imagem é PR; rollback de dado é desenho.
O erro comum é o "caminho de emergência" que pula a revisão: se ele for mais rápido que o normal, vira o normal. O que resolve é deixar rápida a volta pelo caminho de sempre, com reversão a um clique e um segundo dono de código disponível.
O que um validador de deploy recusa?
Recusa, ainda no PR, o que a casa não aceita em produção, antes de alguém precisar lembrar. São seis regras, no mínimo, e cada uma tem um motivo que cabe numa linha.
| O validador recusa | Por quê |
|---|---|
| Porta publicada no host | Reabre uma porta de entrada. A produção só é alcançada pelo proxy, e o proxy só pelo túnel de saída. |
| Contêiner privilegiado, com a rede ou os processos do host | Equivale a dar ao contêiner o controle da máquina. |
| Acesso ao Docker do host | Quem fala com o serviço do Docker é, na prática, administrador do host. |
| Versão "latest" ou imagem sem número | O mesmo arquivo sobe coisas diferentes em dias diferentes. |
| Segredo escrito no arquivo | Segredo que chegou ao Git está vazado, e o histórico não esquece. |
| Limite de memória ausente | Um vazamento de memória derruba o serviço vizinho, não o culpado. |
O validador é um script compartilhado, que mora no repositório de infraestrutura e é chamado pela CI de todos os repositórios de aplicação. O efeito vale o desenho inteiro: uma regra nova da casa chega a toda a CI da empresa sem um PR em cada repositório. E cada regra tem um caso de teste que precisa falhar. O validador também é testado, porque um validador que parou de recusar é pior do que nenhum: o time continua achando que está protegido.
Os detalhes contam. O limite de memória precisa ser um valor escrito, não uma variável, porque uma variável vazia no servidor vira "sem limite", e zero também. A exceção, quando existe, fica escrita na regra, com o motivo, e não num comentário que alguém pode apagar. E cada erro diz qual regra falhou e por quê. Isso importa duas vezes quando quem lê o vermelho é um assistente de IA: com uma mensagem clara, ele corrige o arquivo dentro do caminho, em vez de procurar um jeito de contorná-lo.
O validador só barra o que tem regra. Se a casa quer exigir uma proteção que ele ainda não confere, a regra entra por PR, com o teste dela. É uma lista de decisões que cresce com o tempo, não um produto pronto. Para amanhã: escreva as seis regras como script, com um teste para cada, no caminho de todo PR que mexe em produção.
Quem aprova, e por que dois donos de código e não um?
Aprova um dono de código que não é o autor do PR. Com dois nomes no arquivo de donos, o PR de um é aprovado pelo outro. Com um nome só, todo PR dessa pessoa fica parado, e a reação previsível é alguém tirar a exigência.
No GitHub, o arquivo de donos de código liga cada pasta do repositório às pessoas que precisam revisar mudanças nela. Com a regra de exigir aprovação de dono de código, um PR que toca aquela pasta só é integrado com a aprovação de um deles. E o autor não pode aprovar o próprio PR. Numa empresa pequena, com um administrador só, o segundo nome costuma ser quem responde pelo sistema do lado do negócio, com permissão de escrita no repositório e o compromisso de revisar. Os dois nomes são donos de tudo que muda servidor ou pipeline.
Duas regras completam a aprovação. Aprovação antiga cai quando chega um commit novo, o que importa muito com IA, que continua empurrando ajustes depois da aprovação. E o PR só é integrado com o ramo atualizado e todos os checks obrigatórios verdes. O ramo principal não aceita push direto, nem reescrita de histórico, nem exclusão.
O que o revisor olha muda com o tipo de PR. No PR de deploy, a diferença é uma linha, e a pergunta é se aquela imagem corresponde a um merge com checks verdes. No PR que muda servidor, proxy ou pipeline, a revisão é inteira, porque é ali que se abre ou se fecha um caminho.
Quando um assistente escreveu o PR a pedido de alguém, essa pessoa conta como autora, e a aprovação vem de outro dono. Quem pediu e quem aprova nunca são a mesma mão.
E o servidor que puxa a mudança?
O servidor puxa; ninguém empurra para dentro dele. Um script fixo, no próprio servidor, pergunta de tempos em tempos ao repositório se o ramo principal mudou. Se mudou, confere que a cópia local está limpa, baixa a mudança e sobe os serviços. Se a cópia estiver suja, aborta e alerta.
Puxar é consequência de não ter porta de entrada: se nada de fora alcança a produção, quem inicia a conversa é sempre o servidor. Um orquestrador de deploy acionado por aviso do repositório também serve, desde que o aviso passe por dois controles com donos diferentes: a rede só aceita os endereços do provedor do Git, e o orquestrador recusa o aviso cuja assinatura não confere. O que não serve é instalar no servidor de produção a máquina que executa a CI, porque ela precisaria de acesso ao Docker, e acesso ao Docker é administrador do host. Direito de merge viraria direito de rodar qualquer comando como administrador. É tema de um texto adiante.
Árvore suja é controle, não higiene. A conta que é dona da cópia do repositório no servidor não consegue, sozinha, subir contêiner nenhum. Mas consegue plantar um arquivo de composição modificado e esperar que o próximo deploy o execute com mais poder do que ela tem. Uma árvore suja é a assinatura exata disso. Abortar ali transforma o deploy automático em detecção de adulteração, em vez de veículo dela. Quando o deploy aborta, a pergunta não é "como limpo isto". É "quem escreveu isto".
O script não roda de dentro do repositório. Se o agendador executasse o script a partir da cópia do repositório, bastaria comprometer a conta dona da cópia para editar o script e ganhar execução privilegiada no ciclo seguinte. A cópia instalada pertence ao administrador do servidor, e atualizá-la é um ato deliberado: PR, merge e reinstalação à mão. A lista do que é implantado automaticamente mora dentro do script pelo mesmo motivo. O atrito é o ponto.
O script de deploy não testa nada. É entrega, não CI. O merge é o portão, e o servidor só materializa o que já foi aprovado. A consequência precisa estar clara para todos: com o ramo principal desprotegido, qualquer push direto vai para produção sozinho. A proteção do ramo deixa de ser formalidade e passa a ser o único controle entre um commit e o servidor.
Por onde começar?
A ordem abaixo fecha primeiro os atalhos e só depois automatiza.
- Liste todos os jeitos pelos quais a produção muda hoje, inclusive os que "ninguém usa".
- Proteja o ramo principal: PR obrigatório, aprovação de um de dois donos de código, sem push direto e sem lista de exceção.
- Mova o build para a CI e publique imagem com versão exata.
- Crie o repositório de infraestrutura e faça do deploy um PR que troca a versão, e do rollback também.
- Escreva o validador com as seis regras e um teste para cada.
- Faça o servidor puxar, com script fixo fora do repositório e aborto em árvore suja.
Cada peça responde às três perguntas da série: o que barra, como se prova que barra e o que acontece quando falha. A prova é um punhado de PRs de teste. Um PR que publica uma porta precisa ficar vermelho. Um PR limpo precisa publicar a imagem só depois do merge. Um push direto no ramo principal precisa ser recusado. E um arquivo editado à mão na cópia do servidor precisa fazer o próximo deploy abortar e avisar alguém.
Dados de produção, a IA só lê. Código, ela escreve, e agora ele só chega à produção por um caminho. Mas o caminho vale o que valem os checks que o guardam. O próximo texto trata deles, e de por que um check que só alerta ensina o time a ignorar o vermelho.
Perguntas frequentes
Deploy por pull request não deixa tudo mais lento?
Deixa a primeira vez mais lenta e todas as outras mais rápidas. O PR de deploy tem uma linha, a versão nova, e a revisão pesada já aconteceu no PR da aplicação. O que se ganha é saber, a qualquer momento, o que está rodando, quem aprovou e como voltar. O que se perde é o atalho, e o atalho é exatamente o que precisava sumir.
E numa emergência, quando não dá para esperar revisão?
A emergência mais comum é voltar atrás, e voltar atrás também é um PR de uma linha, com a imagem anterior ainda no repositório de imagens. O que resolve a emergência é deixar esse caminho rápido: reversão a um clique, segundo dono de código disponível, procedimento escrito. Um atalho de emergência mais rápido que o caminho normal vira o caminho normal em poucas semanas.
Por que a produção não pode compilar a partir do código?
Porque o que roda deixa de ser o que foi testado. Compilar no servidor é um segundo build, em outra hora, com outras versões de dependência. Também obriga a produção a ter compilador, acesso a repositórios de pacotes e segredos de build. E abre armadilhas, como o serviço que nunca recebe código novo porque a imagem antiga não é reconstruída.
Por que dois donos de código se o time tem um administrador só?
Porque a aprovação tem de vir de um dono que não é o autor, e o GitHub não deixa o autor aprovar o próprio PR. Com um nome só no arquivo de donos, todo PR dessa pessoa fica parado, e a reação previsível é alguém tirar a exigência. O segundo nome pode ser quem responde pelo sistema do lado do negócio, com permissão de escrita.
O validador de deploy substitui a revisão humana?
Não. Ele tira da revisão o que não depende de julgamento: porta exposta, contêiner privilegiado, versão sem número, segredo escrito, limite de memória ausente. Assim o revisor gasta atenção no que só uma pessoa avalia, como o efeito da mudança e o risco aceito. E o validador só barra o que tem regra escrita; regra nova entra por PR.
A IA pode abrir o PR de deploy?
Pode, e é um bom uso. Um robô ou um assistente abre o PR que troca a versão, os mesmos checks rodam e a aprovação vem de um dono de código que não é o autor. Quando o assistente escreveu a mudança a pedido de alguém, essa pessoa conta como autora. O caminho não distingue quem escreveu; distingue o que foi revisado.
Fontes
- SLSA v1.0 is now final! · SLSA (OpenSSF) ·
- GitHub Repository Rules are now generally available · GitHub Blog ·
- Introducing code owners · GitHub Blog ·
- Secure Software Development Framework (SSDF) Version 1.1 (NIST SP 800-218) · NIST ·
Leia também
- Governança de IA no código: o caminho estreito até produção
- A IA lê, não escreve: dados de produção ao alcance do assistente
- Regra escrita não é regra: por que a política de IA virou mecanismo
- O que o time não desliga: configuração gerenciada de IA
Por Victor Freitas · Consultor em governança de tecnologia e IA · Franklin Freitas Consultoria
Conduz diagnósticos e implantações de governança de tecnologia e IA em pequenas e médias empresas, com experiência acumulada em provedores de internet.