Esta página aborda a hermeticidade, os benefícios de usar builds herméticos e estratégias para identificar comportamentos não herméticos nos seus builds.
Visão geral
Quando recebem o mesmo código-fonte de entrada e a mesma configuração de produto, um sistema de build hermético sempre retorna a mesma saída, isolando o build de mudanças no sistema host.
Para isolar o build, os builds herméticos não são sensíveis a bibliotecas e outros softwares instalados na máquina host local ou remota. Eles dependem de versões específicas de ferramentas de build, como compiladores, e dependências, como bibliotecas. Isso torna o processo de build independente, já que não depende de serviços externos ao ambiente de build.
Os dois aspectos importantes da hermeticidade são:
- Isolamento: sistemas de build herméticos tratam ferramentas como código-fonte. Eles baixam cópias de ferramentas e gerenciam o armazenamento e o uso em árvores de arquivos gerenciadas. Isso cria isolamento entre a máquina host e o usuário local, incluindo versões instaladas de linguagens.
- Identidade de origem: os sistemas de build herméticos tentam garantir a igualdade das entradas. Os repositórios de código, como o Git, identificam conjuntos de mutações de código com um código hash exclusivo. Sistemas de build herméticos usam esse hash para identificar mudanças na entrada do build.
Vantagens
Os principais benefícios dos builds herméticos são:
- Velocidade: a saída de uma ação pode ser armazenada em cache, e a ação não precisa ser executada novamente, a menos que as entradas mudem.
- Execução paralela: para uma determinada entrada e saída, o sistema de build pode construir um gráfico de todas as ações para calcular a execução eficiente e paralela. O sistema de build carrega as regras e calcula um gráfico de ações e entradas de hash para pesquisar no cache.
- Várias builds: é possível criar várias builds herméticas na mesma máquina, cada uma usando ferramentas e versões diferentes.
- Reprodutibilidade: os builds herméticos são bons para a solução de problemas porque você conhece as condições exatas que produziram o build.
Identificação de não hermeticidade
Se você estiver se preparando para mudar para o Bazel, a migração será mais fácil se você melhorar a hermeticidade dos builds atuais com antecedência. Confira algumas fontes comuns de não hermeticidade em builds:
- Processamento arbitrário em arquivos
.mk
- Ações ou ferramentas que criam arquivos de forma não determinística, geralmente envolvendo IDs de build ou carimbos de data/hora
- Binários do sistema que variam entre hosts (como binários
/usr/bin
, caminhos absolutos, compiladores C++ do sistema para autoconfiguração de regras C++ nativas) - Gravar na árvore de origem durante o build. Isso impede que a mesma árvore de origem seja usada para outro destino. O primeiro build grava na árvore de origem, corrigindo-a para o destino A. Então, tentar criar o destino B pode falhar.
Como resolver problemas de builds não herméticos
Começando com a execução local, os problemas que afetam os acertos de cache local revelam ações não herméticas.
- Verifique se há builds sequenciais nulos: se você executar
make
e receber um build bem-sucedido, executar o build novamente não vai reconstruir nenhum destino. Se você executar cada etapa de build duas vezes ou em sistemas diferentes, compare um hash do conteúdo do arquivo e receba resultados diferentes, o build não será reproduzível. - Siga as etapas para depurar acertos de cache local de várias máquinas clientes em potencial para garantir que você detecte qualquer caso de vazamento do ambiente do cliente nas ações.
- Execute uma build em um contêiner do Docker que não contenha nada além da árvore de origem verificada e da lista explícita de ferramentas do host. As falhas de build e as mensagens de erro vão detectar dependências implícitas do sistema.
- Descubra e corrija problemas de hermeticidade usando regras de execução remota.
- Ative o sandboxing estrito no nível de cada ação, já que as ações em um build podem ter estado e afetar o build ou a saída.
- As regras do espaço de trabalho
permitem que os desenvolvedores adicionem dependências a espaços de trabalho externos, mas são
suficientes para permitir que o processamento arbitrário aconteça no processo. Para receber um registro de algumas ações potencialmente não herméticas nas regras do espaço de trabalho do Bazel, adicione a flag
--experimental_workspace_rules_log_file=PATH
ao comando do Bazel.
Hermeticidade com o Bazel
Para mais informações sobre como outros projetos tiveram sucesso usando builds herméticos com o Bazel, assista estas palestras da BazelCon:
- Como criar sistemas em tempo real com o Bazel (SpaceX)
- Execução remota e armazenamento em cache remoto do Bazel (Uber e TwoSigma)
- Builds mais rápidos com execução remota e armazenamento em cache
- Fusão do Bazel: builds incrementais mais rápidos
- Execução remota x execução local
- Melhorar a usabilidade do armazenamento em cache remoto (IBM, em inglês)
- Como criar carros autônomos com o Bazel (BMW)
- Como criar carros autônomos com o Bazel + perguntas e respostas (GM Cruise)