O recurso de arquivo de bloqueio no Bazel permite gravar versões ou dependências específicas de bibliotecas de software ou pacotes exigidos por um projeto. Para isso, ele armazena 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 há mudanças nas dependências do projeto. Além disso, o lockfile melhora a estabilidade ao evitar atualizações inesperadas ou mudanças interruptivas em bibliotecas externas, reduzindo assim 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. O lockfile
captura o estado atual do projeto, incluindo o arquivo MODULE, flags,
substituições e outras informações relevantes. É importante ressaltar que ele inclui apenas dependências que estão incluídas na invocação atual do build.
Quando ocorrem mudanças no projeto que afetam as dependências dele, 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 do arquivo 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 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 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
,flags
elocalOverrideHashes
, 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, além de 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 do arquivo do módulo
O moduleFileHash
representa o hash do conteúdo do arquivo MODULE.bazel
. Se houver mudanças no arquivo, o valor de hash será diferente.
Sinalizações
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
, esta 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 do 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 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 os arquivos .bzl transitivos. - O
generatedRepoSpecs
é o resultado da execução dessa extensão com a entrada atual.
Outro fator que pode afetar os resultados das extensões são os usos delas. 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 com eficiência o recurso de arquivo de bloqueio no Bazel, resultando em fluxos de trabalho de desenvolvimento de software mais eficientes, confiáveis e colaborativos.