O recurso de arquivo de bloqueio no Bazel permite a gravação de versões ou dependências específicas de bibliotecas de software ou pacotes exigidos por um projeto. Isso é feito armazenando o resultado da resolução do módulo e da avaliação da extensão. O arquivo de bloqueio promove builds reproduzíveis, garantindo ambientes de desenvolvimento consistentes. Além disso, ele melhora a eficiência do build, permitindo que o Bazel pule o processo de resolução quando não houver mudanças nas dependências do projeto. Além disso, o arquivo de bloqueio melhora a estabilidade, evitando atualizações inesperadas ou mudanças interruptivas em bibliotecas externas, reduzindo o risco de introduzir bugs.
Geração de arquivos 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. O arquivo de bloqueio captura o estado atual do projeto, incluindo o arquivo MODULE, flags, substituições e outras informações relevantes. É importante ressaltar que ele inclui apenas as dependências incluídas na invocação atual do build.
Quando ocorrem mudanças no projeto que afetam as dependências, o arquivo de bloqueio é atualizado automaticamente para refletir o novo estado. Isso garante que o arquivo de bloqueio permaneça focado no conjunto específico de dependências necessárias para o build atual, fornecendo uma representação precisa das dependências resolvidas do projeto.
Uso de arquivos de bloqueio
O arquivo de bloqueio pode ser controlado pela flag
--lockfile_mode para
personalizar o comportamento do Bazel quando o estado do projeto é diferente do
arquivo de bloqueio. Os modos disponíveis são:
update(padrão): se o estado do projeto corresponder ao arquivo de bloqueio, o resultado da resolução será retornado imediatamente do arquivo de bloqueio. Caso contrário, a resolução será executada e o arquivo de bloqueio será atualizado para refletir o estado atual.error: se o estado do projeto corresponder ao arquivo de bloqueio, o resultado da resolução será retornado do arquivo de bloqueio. Caso contrário, o Bazel vai gerar um erro indicando as variações entre o projeto e o arquivo de bloqueio. Esse modo é útil principalmente quando você quer garantir que as dependências do projeto permaneçam inalteradas e que todas as diferenças sejam tratadas como erros.off: o arquivo de bloqueio não é verificado.
Benefícios do arquivo de bloqueio
O arquivo de bloqueio oferece vários benefícios e pode ser usado de várias maneiras:
Builds reproduzíveis. Ao capturar 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 contar com resultados consistentes e previsíveis ao criar projetos.
Pular a resolução eficiente. O arquivo de bloqueio permite que o Bazel pule o processo de resolução se não houver mudanças nas dependências do projeto desde o último build. Isso melhora significativamente a eficiência do build, especialmente em cenários em que a resolução pode ser demorada.
Estabilidade e redução de riscos. O arquivo de bloqueio ajuda a manter a estabilidade, evitando atualizações inesperadas ou mudanças interruptivas em bibliotecas externas. Ao bloquear as dependências em versões específicas, o risco de introduzir bugs devido a atualizações incompatíveis ou não testadas é reduzido.
Conteúdo do arquivo de bloqueio
O arquivo de bloqueio contém todas as informações necessárias para determinar se o estado do projeto mudou. Ele também inclui o resultado da criação do projeto no estado atual. O arquivo de bloqueio consiste em duas partes principais:
- Entradas da resolução do módulo, como
moduleFileHash,flagselocalOverrideHashes, bem como a saída da resolução, que émoduleDepGraph. - Para cada extensão de módulo, o arquivo de bloqueio inclui entradas que a afetam, representadas por
transitiveDigest, e a saída da execução dessa extensão, chamada degeneratedRepoSpecs
Confira um exemplo que demonstra a estrutura do arquivo de bloqueio, com explicações para cada seção:
{
"lockFileVersion": 1,
"moduleFileHash": "b0f47b98a67ee15f9.......8dff8721c66b721e370",
"flags": {
"cmdRegistries": [
"https://bcr.bazel.build/"
],
"cmdModuleOverrides": {},
"allowedYankedVersions": [],
"envVarAllowedYankedVersions": "",
"ignoreDevDependency": false,
"directDependenciesMode": "WARNING",
"compatibilityMode": "ERROR"
},
"localOverrideHashes": {
"bazel_tools": "b5ae1fa37632140aff8.......15c6fe84a1231d6af9"
},
"moduleDepGraph": {
"<root>": {
"name": "",
"version": "",
"executionPlatformsToRegister": [],
"toolchainsToRegister": [],
"extensionUsages": [
{
"extensionBzlFile": "extension.bzl",
"extensionName": "lockfile_ext"
}
],
...
}
},
"moduleExtensions": {
"//:extension.bzl%lockfile_ext": {
"transitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
"generatedRepoSpecs": {
"hello": {
"bzlFile": "@@//:extension.bzl",
...
}
}
}
}
}
Hash de arquivo de módulo
O moduleFileHash representa o hash do conteúdo do arquivo MODULE.bazel. Se ocorrerem mudanças nesse arquivo, o valor de hash será diferente.
Flags
O objeto Flags armazena todas as flags que podem afetar o resultado da resolução.
Hashes de substituição local
Se o módulo raiz incluir local_path_overrides, essa seção vai armazenar o hash do arquivo MODULE.bazel no repositório local. Ele permite rastrear mudanças nessa dependência.
Gráfico de dependência de módulo
O moduleDepGraph representa o resultado do processo de resolução usando as entradas mencionadas acima. Ele forma o gráfico de dependência de todos os módulos necessários para executar o projeto.
Extensões de módulo
A seção moduleExtensions é um mapa que inclui apenas as extensões usadas na invocação atual ou invocadas anteriormente, excluindo as extensões que não são mais utilizadas. Em outras palavras, se uma extensão não estiver mais sendo usada no gráfico de dependência, ela será removida do mapa moduleExtensions.
Cada entrada nesse mapa corresponde a uma extensão usada e é identificada pelo arquivo e nome que a contém. O valor correspondente de cada entrada contém as informações relevantes associadas a essa extensão:
- O
transitiveDigesté o resumo da implementação da extensão e dos arquivos .bzl transitivos. - O
generatedRepoSpecsé o resultado da execução dessa extensão com a entrada atual.
Outro fator que pode afetar os resultados da extensão são os usos. Embora não sejam armazenados no arquivo de bloqueio, os usos são considerados ao comparar o estado atual da extensão com o do arquivo de bloqueio.
Práticas recomendadas
Para maximizar os benefícios do recurso de arquivo de bloqueio, considere as seguintes práticas recomendadas:
Atualize regularmente o arquivo de bloqueio para refletir mudanças nas dependências ou na configuração do projeto. Isso garante que os builds subsequentes sejam baseados no conjunto de dependências mais atualizado e preciso.
Inclua 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.
Ao seguir essas práticas recomendadas, você pode usar o recurso de arquivo de bloqueio no Bazel de maneira eficaz, levando a fluxos de trabalho de desenvolvimento de software mais eficientes, confiáveis e colaborativos.