Esta página aborda a hermética, os benefícios de usar builds herméticos e estratégias para identificar comportamentos não herméticos nas suas builds.
Visão geral
Quando recebe o mesmo código-fonte de entrada e configuração de produto, um sistema de build hermético sempre retorna a mesma saída, isolando o build das mudanças no sistema host.
Para isolar a versão, as versões herméticas são insensíveis a bibliotecas e outros softwares instalados na máquina host local ou remota. Eles dependem de versões específicas das ferramentas de build, como compiladores, e de dependências, como bibliotecas. Isso torna o processo de build autossuficiente, já que ele não depende de serviços externos ao ambiente de build.
Os dois aspectos importantes da hermética são:
- Isolamento: os sistemas de build herméticos tratam as ferramentas como código-fonte. Eles fazem o download de cópias de ferramentas, gerenciam o armazenamento e o uso dentro de árvores de arquivos gerenciadas. Isso cria um isolamento entre a máquina host e o usuário local, incluindo as versões instaladas dos idiomas.
- Identidade da origem: os sistemas de build herméticos tentam garantir a semelhança 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. Os sistemas de build herméticos usam esse hash para identificar mudanças na entrada do build.
Vantagens
Os principais benefícios das construções herméticas 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 determinadas entradas e saídas, 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, calcula um gráfico de ações e gera hash nas entradas para pesquisar no cache.
- Várias versões: é possível criar várias versões herméticas na mesma máquina, cada compilação usando diferentes ferramentas e versões.
- Reprodutibilidade: builds herméticos são bons para solução de problemas porque você sabe as condições exatas que produziram o build.
Como identificar a não hermética
Se você está se preparando para mudar para o Bazel, a migração será mais fácil se você melhorar a hermética das builds atuais com antecedência. Algumas fontes comuns de não hermética em builds são:
- Processamento arbitrário em arquivos
.mk
- Ações ou ferramentas que criam arquivos de forma não determinista, geralmente envolvendo IDs de build ou carimbos de data/hora.
- Binários do sistema que diferem entre hosts (como binários
/usr/bin
, caminhos absolutos, compiladores C++ do sistema para configuração automática de regras C++ nativas). - Gravar na árvore de origem durante a compilação. Isso evita que a mesma árvore de origem seja usada para outro destino. O primeiro build grava na árvore de origem, corrigindo a árvore de origem do destino A. Então, tentar criar o destino B pode falhar.
Como solucionar problemas de builds não herméticos
Começando com a execução local, os problemas que afetam as ocorrências em cache local revelam ações não herméticas.
- Garanta builds sequenciais nulos: se você executar
make
e receber um build bem-sucedido, a execução do build novamente não vai recriar nenhum destino. Se você executar cada etapa do build duas vezes ou em sistemas diferentes, comparar um hash do conteúdo do arquivo e receber resultados diferentes, a versão não será reproduzível. - Execute as etapas para depurar ocorrências em cache local de várias máquinas clientes em potencial para garantir a detecção de casos de vazamento no ambiente do cliente para as ações.
- Execute uma versão 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 de host. As falhas de build e as mensagens de erro vão capturar dependências implícitas do sistema.
- Descubra e corrija problemas de hermeticidade usando regras de execução remota.
- Ative o sandbox estrito no nível por ação, já que as ações em um build podem ter estado e afetar a versão 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 avançadas o suficiente para permitir que o processamento arbitrário ocorra no processo. É possível
gerar um registro de algumas ações potencialmente não herméticas nas regras de espaço de trabalho do Bazel
adicionando a flag
--experimental_workspace_rules_log_file=PATH
ao comando do Bazel.
Hermeticidade com o Bazel
Para saber mais sobre como outros projetos tiveram sucesso usando builds herméticos com o Bazel, confira estas conversas da BazelCon:
- Como criar sistemas em tempo real com o Bazel (SpaceX)
- Bazel Remote Execution e armazenamento em cache remoto (Uber e TwoSigma)
- Compilações mais rápidas com execução remota e armazenamento em cache
- Fusão do Bazel: builds incrementais mais rápidos
- Execução remota vs. execução local
- Aprimoramento da usabilidade do armazenamento em cache remoto (IBM)
- Como construir carros autônomos com o Bazel (BMW)
- Como construir carros autoguiados com Bazel + perguntas e respostas (GM Cruise)