Este artigo é um artigo espelhado de tradução automática, por favor clique aqui para ir para o artigo original.

Vista: 1081|Resposta: 1

Uma breve introdução ao Reproducible Build

[Copiar link]
Postado em 30-04-2025 às 10:09:27 | | | |
O que é uma build repetível?

Build determinística ou build reproduzível são um pouco diferentes, mas podem ser entendidos como a mesma coisa deste artigo.

Builds Reprodutíveis referem-se aoMúltiplas execuções do processo de build com a mesma entrada e ambiente de build podem produzir exatamente os mesmos resultados。 Essa tecnologia é importante para o desenvolvimento, distribuição e validação de segurança de software.

Uma build é reproduzível se fornecer exatamente a mesma saída, independentemente de quando e onde é executada. Não importa em qual computador você esteja rodando, que horário do dia ou quais serviços externos você acessa pela rede, compilações reproduzíveis produzem a mesma saída byte a byte. Isso é ótimo tanto para desenvolvimento (porque builds reproduzíveis são fáceis de compartilhar entre diferentes dispositivos de desenvolvedor) quanto para produção (porque é fácil garantir que os resultados das builds reproduzíveis não foram alterados – basta rodar a build novamente na sua própria máquina e verificar se os resultados são consistentes!). são muito úteis.



Os três pilares das construções repetíveis

Pilar 1: Builds repetíveis

Repetibilidade da build refere-se ao que acontece com a própria máquina de build. Assumindo que nossas entradas de build estejam disponíveis e nada mude no mundo ao nosso redor, nossa build produz a mesma saída quando repetida?

Plano de instalação determinístico

O primeiro, mais simples e mais óbvio requisito em uma build repetível é um plano de instalação de dependência determinística.

Na maioria dos idiomas, é tão simples quanto conferir um arquivo bloqueado. Ferramentas modernas de build frequentemente permitem que projetos expressem requisitos diretos de dependência como restrições e, em seguida, resolvam essas restrições para gerar um plano de instalação (uma lista de nomes de dependências e pares de versões para instalar). Muitas dessas ferramentas também geram arquivos de bloqueio para planos de instalação serializados. Os desenvolvedores podem submeter esses arquivos de bloqueio para controle de versões, para que futuras versões usem os mesmos nomes e versões de dependências.

Note que também precisamos de determinístico na própria build de dependência (não apenas na seleção de versões), e um plano de instalação determinístico não permite isso!

Construção determinística

Uma vez que sabemos o que construir, nossa própria build (incluindo nosso próprio código e a construção do código de dependência) deve ser realmente determinística.

Isso pode não ser um problema para projetos sem uma etapa de compilação! Por exemplo, um projeto Node com todas as dependências é JavaScript puro, e nenhum trabalho adicional é necessário para alcançar deterministicidade efetiva.

Para projetos que incluem etapas de compilação ou tradução (compilação de fonte a fonte), garantir o determinismo é, de longe, a parte mais difícil da construção de uma build reproduzível. O processo de compilação pode introduzir implicitamente o não-determinismo de várias maneiras, incluindo:

  • Scripts de build de programas Turing-complete podem alterar a saída compilada à vontade.
  • Scripts pós-instalação que dependem de consultas executáveis ao sistema de arquivos ou chamadas de rede.
  • A vinculação C a um pacote instalado pelo sistema, onde ligações em diferentes sistemas com cabeçalhos diferentes podem produzir saídas diferentes.
  • Passos para construir um arquivo que seja lido fora do controle de versão.
  • Crie etapas para gerar carimbos de tempo usando o tempo do sistema.
  • Etapas para construir dependências que não são expressas no plano de instalação de download da rede (por exemplo, baixar uma dependência NPM do GitHub para uma build binária em cache que seja vinculada a C).
  • Mude o comportamento com base na variável de ambiente atualmente definida, mas não envie uma build com a configuração da variável de ambiente.


Nem todos esses comportamentos necessariamente introduzem incerteza quando configurados corretamente, mas configurar corretamente o processo de construção pode ser complexo e difícil. Por exemplo, você pode ler este post no blog sobre incerteza em builds de Chromium. Muitos desses problemas podem ser mitigados controlando o ambiente local de construção, o que discutiremos na próxima seção.

Pilar 2: Ambiente imutável

Mesmo com builds repetíveis, precisamos garantir que as entradas de build não mudem. Frequentemente, isso significa que queremos garantir que construimos sobre um instantâneo imutável do nosso entorno.

Ambiente local imutável

Como discutimos acima, uma fonte comum de incerteza na build é depender de "dependências" que não são capturadas pela ferramenta de build. Bibliotecas de sistema encadernadas em C são os exemplos mais comuns, mas outros fatores ambientais locais, como configurações de variáveis de ambiente e arquivos fora do escopo do controle de versões, também podem afetar a compilação.

Uma maneira fácil de mitigar esse problema é rodar a build em um container conhecido e imutável. Por exemplo, um tempo de execução de container como o Docker ajuda a garantir que todos usem as mesmas dependências do sistema, as mesmas variáveis de ambiente e rodem no mesmo sistema de arquivos. Além disso, é fácil verificar se o conteúdo do contêiner corresponde a um contêiner de construção conhecida e, se necessário, o contêiner pode ser facilmente removido completamente da imagem conhecida e recriado.

Note que somos muito claros sobre contêineres conhecidos ou imagens de contêineres conhecidos. Não basta enviar um Dockerfile! Por que? Porque o próprio Dockerfile não descreve um processo de compilação totalmente reproduzível para imagens Docker, pois elas não rodam em um ambiente global imutável.

Ambiente global imutável

Sistemas de build frequentemente interagem com serviços externos para completar tarefas como resolução de versões e downloads de dependências. Mas os serviços externos mudam com frequência.

Rodar o apt install nodejs hoje vai te dar resultados diferentes do ano passado, e provavelmente no ano que vem também terá resultados diferentes. É por isso que os próprios Dockerfiles não conseguem descrever builds reproduzíveis – rodar o mesmo Dockerfile em diferentes momentos gera resultados de build diferentes!

A mitigação simples aqui é configurar a build sempre que possível, especificando uma versão exata (idealmente, um hash de conteúdo exato também) para que futuras builds usem a mesma versão da versão atual. Mas serviços externos também podem mudar seu comportamento inesperadamente – uma build verdadeiramente pessimista e reproduzível roda uma imagem interna com o maior número possível de recursos de rede.

Pilar 3: Disponibilidade de recursos

Digamos que nossa construção seja repetível e o mundo sob nossos pés não mude. Tudo o que precisamos agora é de acesso ao input de build. Parece simples, né? Poço......

O registro às vezes falha

A maioria dos desenvolvedores Node já experimentou pelo menos uma queda de NPM, durante a qual o pipeline de build sem cache ou espelhamento de pacotes NPM é interrompido. Muitos desenvolvedores da Node também passaram por remoções de left-pad e faker, que prejudicaram severamente o ecossistema NPM e efetivamente resultaram em uma queda de energia.

A única maneira confiável de mitigar essas falhas de build é rodar seu próprio espelho do registro de pacotes. Quando serviços externos não estão disponíveis, a imagem pode permanecer online; Quando o registro oficial exclui o pacote antigo, o espelho pode continuar a fornecer serviços. O mesmo princípio se aplica a outros serviços remotos: a menos que você execute sua própria imagem, a disponibilidade de um pipeline de build só é comparável à disponibilidade de seus serviços.

Escolher rodar uma imagem de serviço é sempre uma troca delicada. Por um lado, registros como o NPM possuem equipes dedicadas de engenharia e operações que possuem a expertise para manter esses sistemas online. Por outro lado, é muito mais fácil rodar uma imagem pequena para um conjunto pequeno de dependências do que rodar todas as imagens NPM. Você deve tomar decisões espelhadas com base nos detalhes de cada serviço, levando em conta a confiabilidade dos serviços externos históricos e as necessidades de disponibilidade de construção e pessoal da sua equipe.

Os fornecedores garantem a máxima disponibilidade

Uma maneira fácil de garantir a máxima disponibilidade das dependências do seu projeto é adicioná-las ao seu fornecedor. A maioria dos gerenciadores de pacotes suporta algum tipo de "vendoring", o que significa que, em vez de depender de downloads de serviços externos, armazenamos o código-fonte da dependência no controle de versão, coexistindo com nosso código-fonte. Por exemplo, no Node, isso pode parecer comprometer node_modules com controle de versão.

Embora essa solução não seja perfeita (dependendo de como seu fornecedor e projeto estão configurados, o que pode colocar muita pressão no controle de versões), geralmente é a solução mais simples e fácil para máxima disponibilidade.

Referência:

O login do hiperlink está visível.
O login do hiperlink está visível.




Anterior:.NET/C# Use o UnsafeAccessor para modificar o conteúdo do campo somente leitura
Próximo:Angular 18 Series (32) ControlValueAccessor controles personalizados de forma
 Senhorio| Postado em 30-04-2025 às 10:10:23 |
Sobre o uso de builds repetíveis ao construir pacotes NuGet em C#:

O login do hiperlink está visível.
O login do hiperlink está visível.
Disclaimer:
Todo software, material de programação ou artigos publicados pela Code Farmer Network são apenas para fins de aprendizado e pesquisa; O conteúdo acima não deve ser usado para fins comerciais ou ilegais, caso contrário, os usuários terão todas as consequências. As informações deste site vêm da Internet, e disputas de direitos autorais não têm nada a ver com este site. Você deve deletar completamente o conteúdo acima do seu computador em até 24 horas após o download. Se você gosta do programa, por favor, apoie um software genuíno, compre o registro e obtenha serviços genuínos melhores. Se houver qualquer infração, por favor, entre em contato conosco por e-mail.

Mail To:help@itsvse.com