Fitur lockfile di Bazel memungkinkan perekaman versi atau dependensi tertentu dari library atau paket software yang diperlukan oleh project. Fitur ini mencapainya dengan menyimpan hasil resolusi modul dan evaluasi ekstensi. Lockfile mempromosikan build yang dapat direproduksi, sehingga memastikan lingkungan pengembangan yang konsisten. Selain itu, lockfile meningkatkan efisiensi build dengan memungkinkan Bazel melewati bagian dari proses resolusi yang tidak terpengaruh oleh perubahan dalam dependensi project. Selain itu, lockfile meningkatkan stabilitas dengan mencegah update yang tidak terduga atau perubahan yang dapat menyebabkan gangguan pada library eksternal, sehingga mengurangi risiko munculnya bug.
Pembuatan Lockfile
Lockfile dibuat di bawah root ruang kerja dengan nama MODULE.bazel.lock. Lockfile dibuat atau diperbarui selama proses build, khususnya setelah resolusi modul dan evaluasi ekstensi. Yang penting, lockfile hanya menyertakan dependensi yang disertakan dalam pemanggilan build saat ini.
Saat terjadi perubahan dalam project yang memengaruhi dependensinya, lockfile akan otomatis diperbarui untuk mencerminkan status baru. Hal ini memastikan lockfile tetap berfokus pada kumpulan dependensi tertentu yang diperlukan untuk build saat ini, sehingga memberikan representasi yang akurat dari dependensi project yang telah diselesaikan.
Penggunaan Lockfile
Lockfile dapat dikontrol oleh flag
--lockfile_mode untuk
menyesuaikan perilaku Bazel saat status project berbeda dengan
lockfile. Mode yang tersedia adalah:
update(Default): Gunakan informasi yang ada di lockfile untuk melewati download file registry yang dikenal dan untuk menghindari evaluasi ulang ekstensi yang hasilnya masih terbaru. Jika informasi tidak ada, informasi tersebut akan ditambahkan ke lockfile. Dalam mode ini, Bazel juga menghindari pembaruan informasi yang dapat diubah, seperti versi yang ditarik, untuk dependensi yang tidak berubah.refresh: Sepertiupdate, tetapi informasi yang dapat diubah selalu diperbarui saat beralih ke mode ini dan kira-kira setiap jam saat dalam mode ini.error: Sepertiupdate, tetapi jika ada informasi yang tidak ada atau tidak berlaku, Bazel akan gagal dengan error. Mode ini tidak pernah mengubah lockfile atau melakukan permintaan jaringan selama resolusi. Ekstensi modul yang menandai dirinya sebagaireproduciblemungkin masih melakukan permintaan jaringan, tetapi diharapkan selalu menghasilkan hasil yang sama.off: Lockfile tidak diperiksa maupun diperbarui.
Manfaat Lockfile
Lockfile menawarkan beberapa manfaat dan dapat digunakan dengan berbagai cara:
Build yang dapat direproduksi. Dengan mengambil versi atau dependensi tertentu dari library software, lockfile memastikan bahwa build dapat direproduksi di berbagai lingkungan dan dari waktu ke waktu. Developer dapat mengandalkan hasil yang konsisten dan dapat diprediksi saat membuat project.
Resolusi inkremental yang cepat. Lockfile memungkinkan Bazel menghindari download file registry yang sudah digunakan dalam build sebelumnya. Hal ini meningkatkan efisiensi build secara signifikan, terutama dalam skenario ketika resolusi dapat memakan waktu.
Stabilitas dan pengurangan risiko. Lockfile membantu mempertahankan stabilitas dengan mencegah update yang tidak terduga atau perubahan yang dapat menyebabkan gangguan pada library eksternal. Dengan mengunci dependensi ke versi tertentu, risiko munculnya bug
karena update yang tidak kompatibel atau tidak diuji akan berkurang.
Lockfile tersembunyi
Bazel juga mempertahankan lockfile lain di
"$(bazel info output_base)"/MODULE.bazel.lock. Format dan konten lockfile ini tidak ditentukan secara eksplisit. Lockfile ini hanya digunakan sebagai pengoptimalan performa. Meskipun dapat dihapus bersama dengan output dasar melalui bazel clean --expunge, kebutuhan untuk melakukannya adalah bug di Bazel itu sendiri atau ekstensi modul.
Konten Lockfile
Lockfile berisi semua informasi yang diperlukan untuk menentukan apakah status project telah berubah. Lockfile juga menyertakan hasil pembuatan project dalam status saat ini. Lockfile terdiri dari dua bagian utama:
- Hash semua file jarak jauh yang merupakan input untuk resolusi modul.
- Untuk setiap ekstensi modul, lockfile menyertakan input yang memengaruhinya,
yang diwakili oleh
bzlTransitiveDigest,usagesDigestdan kolom lainnya, serta output dari menjalankan ekstensi tersebut, yang disebut sebagaigeneratedRepoSpecs
Berikut adalah contoh yang menunjukkan struktur lockfile, beserta penjelasan untuk setiap bagian:
{
"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",
...
}
}
}
}
}
}
Hash File Registry
Bagian registryFileHashes berisi hash semua file dari registry jarak jauh yang diakses selama resolusi modul. Karena algoritma resolusi sepenuhnya deterministik saat diberi input yang sama dan semua input jarak jauh di-hash, hal ini memastikan hasil resolusi yang sepenuhnya dapat direproduksi sekaligus menghindari duplikasi informasi jarak jauh yang berlebihan di lockfile. Perhatikan bahwa hal ini juga memerlukan perekaman saat registry tertentu tidak berisi modul tertentu, tetapi registry dengan prioritas lebih rendah berisi modul tersebut (lihat entri "tidak ditemukan" dalam contoh). Informasi yang secara inheren dapat diubah ini dapat diperbarui melalui bazel mod deps --lockfile_mode=refresh.
Bazel menggunakan hash dari lockfile untuk mencari file registry di cache repositori sebelum mendownloadnya, yang mempercepat resolusi berikutnya.
Versi yang Ditarik yang Dipilih
Bagian selectedYankedVersions berisi versi modul yang ditarik yang dipilih oleh resolusi modul. Karena hal ini biasanya menghasilkan error saat mencoba membuat, bagian ini hanya tidak kosong jika versi yang ditarik diizinkan secara eksplisit melalui --allow_yanked_versions atau BZLMOD_ALLOW_YANKED_VERSIONS.
Kolom ini diperlukan karena, dibandingkan dengan file modul, informasi versi yang ditarik secara inheren dapat diubah dan dengan demikian tidak dapat direferensikan oleh hash. Informasi ini dapat diperbarui melalui bazel mod deps --lockfile_mode=refresh.
Ekstensi Modul
Bagian moduleExtensions adalah peta yang hanya menyertakan ekstensi yang digunakan dalam pemanggilan saat ini atau sebelumnya, sekaligus mengecualikan ekstensi yang tidak lagi digunakan. Dengan kata lain, jika ekstensi tidak lagi digunakan di seluruh grafik dependensi, ekstensi tersebut akan dihapus dari peta moduleExtensions.
Jika ekstensi independen dari sistem operasi atau jenis arsitektur, bagian ini hanya menampilkan satu entri "umum". Jika tidak, beberapa entri akan disertakan, yang diberi nama sesuai dengan OS, arsitektur, atau keduanya, dengan masing-masing sesuai dengan hasil evaluasi ekstensi pada spesifikasi tersebut.
Setiap entri dalam peta ekstensi sesuai dengan ekstensi yang digunakan dan diidentifikasi berdasarkan file dan nama yang berisi ekstensi tersebut. Nilai yang sesuai untuk setiap entri berisi informasi relevan yang terkait dengan ekstensi tersebut:
bzlTransitiveDigestadalah ringkasan implementasi ekstensi dan file .bzl yang dimuat secara transitif olehnya.usagesDigestadalah ringkasan penggunaan ekstensi dalam grafik dependensi, yang mencakup semua tag.- Kolom lain yang tidak ditentukan yang melacak input lain ke ekstensi, seperti konten file atau direktori yang dibaca atau variabel lingkungan yang digunakan.
generatedRepoSpecsmengenkode repositori yang dibuat oleh ekstensi dengan input saat ini.- Kolom
moduleExtensionMetadataopsional berisi metadata yang disediakan oleh ekstensi, seperti apakah repositori tertentu yang dibuatnya harus diimpor melaluiuse_repooleh modul root. Informasi ini mendukung perintahbazel mod tidy.
Ekstensi modul dapat memilih untuk tidak disertakan dalam lockfile dengan menetapkan metadata yang ditampilkan dengan reproducible = True. Dengan melakukannya, ekstensi modul berjanji bahwa ekstensi tersebut akan selalu membuat repositori yang sama jika diberi input yang sama.
Praktik Terbaik
Untuk memaksimalkan manfaat fitur lockfile, pertimbangkan praktik terbaik berikut:
Perbarui lockfile secara rutin untuk mencerminkan perubahan dalam dependensi atau konfigurasi project. Hal ini memastikan bahwa build berikutnya didasarkan pada kumpulan dependensi yang paling baru dan akurat. Untuk mengunci semua ekstensi sekaligus, jalankan
bazel mod deps --lockfile_mode=update.Sertakan lockfile dalam kontrol versi untuk memfasilitasi kolaborasi dan memastikan bahwa semua anggota tim memiliki akses ke lockfile yang sama, sehingga mendorong lingkungan pengembangan yang konsisten di seluruh project.
Gunakan
bazeliskuntuk menjalankan Bazel, dan sertakan file.bazelversiondalam kontrol versi yang menentukan versi Bazel yang sesuai dengan lockfile. Karena Bazel itu sendiri adalah dependensi dari build Anda, lockfile khusus untuk versi Bazel, dan akan berubah bahkan di antara rilis Bazel yang kompatibel dengan versi sebelumnya. Menggunakanbazeliskmemastikan bahwa semua developer menggunakan versi Bazel yang cocok dengan lockfile.
Dengan mengikuti praktik terbaik ini, Anda dapat menggunakan fitur lockfile di Bazel secara efektif, sehingga menghasilkan alur kerja pengembangan software yang lebih efisien, andal, dan kolaboratif.
Konflik Penggabungan
Format lockfile dirancang untuk meminimalkan konflik penggabungan, tetapi konflik tersebut masih dapat terjadi.
Resolusi Otomatis
Bazel menyediakan driver penggabungan git kustom untuk membantu menyelesaikan konflik ini secara otomatis.
Siapkan driver dengan menambahkan baris ini ke file .gitattributes di root repositori git Anda:
# A custom merge driver for the Bazel lockfile.
# https://bazel.build/external/lockfile#automatic-resolution
MODULE.bazel.lock merge=bazel-lockfile-merge
Kemudian, setiap developer yang ingin menggunakan driver harus mendaftarkannya sekali dengan mengikuti langkah-langkah berikut:
- Instal jq (1.5 atau yang lebih baru).
- Jalankan perintah berikut:
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"
Resolusi Manual
Konflik penggabungan sederhana di kolom registryFileHashes dan selectedYankedVersions dapat diselesaikan dengan aman dengan menyimpan semua entri dari kedua sisi konflik.
Jenis konflik penggabungan lainnya tidak boleh diselesaikan secara manual. Sebagai gantinya:
- Pulihkan status lockfile sebelumnya
melalui
git reset MODULE.bazel.lock && git checkout MODULE.bazel.lock. - Selesaikan konflik apa pun dalam file
MODULE.bazel. - Jalankan
bazel mod depsuntuk memperbarui lockfile.