Arquivo de bloqueio do Bazel

Informar um problema Mostrar fonte Por noite · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

O recurso de bloqueio de arquivos do Bazel permite a gravação de versões ou dependências de bibliotecas ou pacotes de software exigidos por um projeto. Ela faz isso armazenando o resultado da resolução do módulo e da extensão e avaliação de desempenho. O lockfile promove builds reproduzíveis, garantindo ambientes de desenvolvimento de software. Além disso, ela melhora a eficiência do build, permitindo O Bazel para pular as partes do processo de resolução que não são afetadas pelas mudanças. nas dependências do projeto. Além disso, o lockfile melhora a estabilidade evitar atualizações inesperadas ou alterações interruptivas em bibliotecas externas, o que permite reduzindo o risco de introduzir bugs.

Geração de arquivo de bloqueio

O arquivo de bloqueio é gerado na raiz do espaço de trabalho com o nome MODULE.bazel.lock: Ele é criado ou atualizado durante o processo de build especificamente após a resolução do módulo e a avaliação da extensão. É importante ressaltar que inclui apenas as dependências incluídas na invocação atual do ser construído.

Quando ocorrem alterações no projeto que afetam suas dependências, o arquivo de bloqueio é atualizado automaticamente para refletir o novo estado. Isso garante que o arquivo de bloqueio permanece focado no conjunto específico de dependências necessárias para o criar, fornecendo uma representação precisa das questões resolvidas dependências.

Uso do arquivo de bloqueio

O lockfile pode ser controlado pela sinalização --lockfile_mode para personalizar o comportamento do Bazel quando o estado do projeto é diferente do o arquivo de bloqueio. Os modos disponíveis são:

  • update (padrão): use as informações presentes no arquivo de bloqueio para pular downloads de arquivos de registro conhecidos e evitar a reavaliação das extensões com resultados ainda atualizados. Se faltar alguma informação, ela que será adicionado ao arquivo de bloqueio. Neste modo, o Bazel também evita atualizar informações mutáveis, como versões puxadas, para dependências que não mudou.
  • refresh: semelhante a update, mas as informações mutáveis são sempre atualizadas quando alternando para esse modo e aproximadamente a cada hora enquanto estiver nesse modo.
  • error: semelhante a update, mas se alguma informação estiver ausente ou desatualizada; O Bazel falha com um erro. Esse modo nunca altera o arquivo de bloqueio ou executa solicitações de rede durante a resolução. As extensões do módulo que marcaram porque reproducible ainda pode executar solicitações de rede, mas se espera sempre produzir o mesmo resultado.
  • off: o arquivo de bloqueio não é verificado nem atualizado.

Benefícios do Lockfile

O lockfile oferece vários benefícios e pode ser usado de várias maneiras:

  • Builds reproduzíveis. Capturando as versões ou dependências específicas de bibliotecas de software, o arquivo de bloqueio garante que os builds sejam reproduzíveis em diferentes ambientes e ao longo do tempo. Os desenvolvedores podem confiar resultados consistentes e previsíveis ao criar seus projetos.

  • Resoluções incrementais rápidas. O arquivo de bloqueio permite que o Bazel evite o download de arquivos de registro que já eram usados em um build anterior. Isso melhora significativamente a eficiência do build, especialmente em cenários em que e resolução pode ser demorado.

  • Estabilidade e redução de riscos. O arquivo de bloqueio ajuda a manter a estabilidade evitar atualizações inesperadas ou alterações interruptivas em bibliotecas externas. De o bloqueio das dependências a versões específicas, o risco de introduzir bugs devido a atualizações incompatíveis ou não testadas é reduzida.

Conteúdo do arquivo de bloqueio

O arquivo de bloqueio contém todas as informações necessárias para determinar se o o estado do projeto mudou. Também inclui o resultado da criação do projeto no estado atual. O arquivo de bloqueio consiste em duas partes principais:

  1. Hashes de todos os arquivos remotos que são entradas para a resolução do módulo.
  2. Para cada extensão de módulo, o arquivo de bloqueio inclui entradas que o afetam, representados por bzlTransitiveDigest, usagesDigest e outros campos, como além da saída da execução dessa extensão, chamada de generatedRepoSpecs

Este é um exemplo que demonstra a estrutura do arquivo de bloqueio, junto com explicações para cada seção:

{
  "lockFileVersion": 10,
  "registryFileHashes": {
    "https://bcr.bazel.build/bazel_registry.json": "8a28e4af...5d5b3497",
    "https://bcr.bazel.build/modules/foo/1.0/MODULE.bazel": "7cd0312e...5c96ace2",
    "https://bcr.bazel.build/modules/foo/2.0/MODULE.bazel": "70390338... 9fc57589",
    "https://bcr.bazel.build/modules/foo/2.0/source.json": "7e3a9adf...170d94ad",
    "https://registry.mycorp.com/modules/foo/1.0/MODULE.bazel": "not found",
    ...
  },
  "selectedYankedVersions": {
    "foo@2.0": "Yanked for demo purposes"
  },
  "moduleExtensions": {
    "//:extension.bzl%lockfile_ext": {
      "general": {
        "bzlTransitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    },
    "//:extension.bzl%lockfile_ext2": {
      "os:macos": {
        "bzlTransitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "usagesDigest": "aLmqbvowmHkkBPve05y....yDNGN7oh7r3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      },
      "os:linux": {
        "bzlTransitiveDigest": "eWDzxG/aLsyY3Ubrto....+Jp4maQvEPxn0pLK=",
        "usagesDigest": "aLmqbvowmHkkBPve05y....yDNGN7oh7r3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    }
  }
}

Hashes de arquivo de registro

A seção registryFileHashes contém os hashes de todos os arquivos de registros remotos acessados durante a resolução do módulo. Como a resolução é totalmente determinista quando recebe as mesmas entradas entradas são criptografadas em hash, o que garante um resultado de resolução totalmente reproduzível evitando a duplicação excessiva de informações remotas no arquivo de bloqueio. Observe que isso também exige gravação quando um registro específico não contém um determinado , mas um registro com menor precedência teve (consulte a entrada "não encontrado" exemplo). Essas informações mutáveis podem ser atualizadas usando bazel mod deps --lockfile_mode=refresh:

O Bazel usa os hashes do lockfile para procurar arquivos de registro no do repositório antes do download, o que acelera o processamento e resoluções.

Versões selecionadas

A seção selectedYankedVersions contém as versões puxadas dos módulos. selecionados pela resolução do módulo. Como isso geralmente resulta em erro, ao tentar criar, esta seção só fica vazia quando versões puxadas são explicitamente permitido via --allow_yanked_versions ou BZLMOD_ALLOW_YANKED_VERSIONS.

Esse campo é necessário porque, em comparação com os arquivos do módulo, as informações de versão extraídas é inerentemente mutável e, portanto, não pode ser referenciado por um hash. Essa informação podem ser atualizadas via bazel mod deps --lockfile_mode=refresh.

Extensões do módulo

A seção moduleExtensions é um mapa que inclui apenas as extensões usadas na invocação atual ou invocadas anteriormente, excluindo qualquer extensão que não são mais utilizadas. Em outras palavras, se uma extensão não estiver sendo usada no gráfico de dependência, ele é removido do moduleExtensions mapa.

Se uma extensão for independente do sistema operacional ou do tipo de arquitetura, essa seção apresenta apenas um termo "geral" entrada. Caso contrário, várias são incluídas, nomeadas de acordo com o sistema operacional, a arquitetura ou ambos, com cada correspondente ao resultado da avaliação da extensão nesses detalhes.

Cada entrada no mapa de extensões corresponde a uma extensão usada e é identificado pelo arquivo e nome que o contém. O valor correspondente para cada entrada contém as informações relevantes associadas a essa extensão:

  1. O bzlTransitiveDigest é o resumo da implementação da extensão. e os arquivos .bzl carregados de modo transitivo.
  2. O usagesDigest é o resumo dos usos da extensão no gráfico de dependências, que inclui todas as tags.
  3. Outros campos não especificados que rastreiam outras entradas para a extensão, como o conteúdo de arquivos ou diretórios lidos ou variáveis que ele utiliza.
  4. O generatedRepoSpecs codifica os repositórios criados pelo com a entrada atual.
  5. O campo moduleExtensionMetadata opcional contém metadados fornecidos por extensão. Por exemplo, se determinados repositórios criados por ela deveriam ser importado via use_repo pelo módulo raiz. Essas informações alimentam bazel mod tidy.

As extensões de módulo podem desativar a inclusão no arquivo de bloqueio configurando o retornando metadados com reproducible = True. Ao fazer isso, eles prometem que elas sempre vão criar os mesmos repositórios quando receber as mesmas entradas.

Práticas recomendadas

Para maximizar os benefícios do recurso de bloqueio de arquivo, considere as seguintes práticas recomendadas:

  • Atualize regularmente o arquivo de bloqueio para refletir as alterações nas dependências do projeto ou configuração do Terraform. Isso garante que os próximos builds sejam baseados um conjunto atualizado e preciso de dependências. Para bloquear todas as extensões de uma só vez, execute bazel mod deps --lockfile_mode=update.

  • Incluir o arquivo de bloqueio no controle de versões para facilitar a colaboração e garantir que todos os membros da equipe tenham acesso ao mesmo arquivo de bloqueio, promovendo ambientes de desenvolvimento consistentes em todo o projeto.

  • Use bazelisk para executar o Bazel e inclua um Arquivo .bazelversion no controle de versões que especifica a versão do Bazel que correspondem ao arquivo de bloqueio. Como o próprio Bazel é uma dependência seu build, o arquivo de bloqueio é específico para a versão do Bazel e mudar até mesmo entre versões compatíveis com versões anteriores Lançamentos do Bazel. O uso de bazelisk garante que todos os desenvolvedores usem uma versão do Bazel que corresponde ao arquivo de bloqueio.

Seguindo estas práticas recomendadas, você pode utilizar o arquivo de bloqueio de forma eficaz recurso do Bazel, o que aumenta a eficiência, a confiabilidade e a colaboração fluxos de trabalho de desenvolvimento de software.

Conflitos de mesclagem

O formato de lockfile é projetado para minimizar conflitos de mesclagem, mas eles ainda podem acontecerem.

Resolução automática

O Bazel fornece um driver git merge para ajudar a resolver esses conflitos automaticamente.

Configure o driver adicionando esta linha a um arquivo .gitattributes na raiz do seu repositório Git:

# A custom merge driver for the Bazel lockfile.
# https://bazel.build/external/lockfile#automatic-resolution
MODULE.bazel.lock merge=bazel-lockfile-merge

Então, cada desenvolvedor que quiser usar o driver precisa registrá-lo uma vez até seguindo estas etapas:

  1. Instale o jq (1.5 ou superior).
  2. Execute os comandos a seguir:
jq_script=$(curl https://raw.githubusercontent.com/bazelbuild/bazel/master/scripts/bazel-lockfile-merge.jq)
printf '%s\n' "${jq_script}" | less # to optionally inspect the jq script
git config --global merge.bazel-lockfile-merge.name   "Merge driver for the Bazel lockfile (MODULE.bazel.lock)"
git config --global merge.bazel-lockfile-merge.driver "jq -s '${jq_script}' -- %O %A %B > %A.jq_tmp && mv %A.jq_tmp %A"

Resolução manual

Conflitos de mesclagem simples em registryFileHashes e selectedYankedVersions. podem ser resolvidos com segurança, mantendo todas as entradas de ambos os lados do conflitos.

Outros tipos de conflitos de mesclagem não devem ser resolvidos manualmente. Em vez disso, faça o seguinte:

  1. Restaurar o estado anterior do arquivo de bloqueio via git reset MODULE.bazel.lock && git checkout MODULE.bazel.lock.
  2. Resolva os conflitos no arquivo MODULE.bazel.
  3. Execute bazel mod deps para atualizar o arquivo de bloqueio.