ฟีเจอร์ไฟล์ล็อกใน Bazel ทำให้สามารถบันทึกเวอร์ชันที่เจาะจงหรือทรัพยากร Dependency ของไลบรารีหรือแพ็กเกจซอฟต์แวร์ที่โปรเจ็กต์จำเป็นต้องใช้ โดยจัดเก็บผลลัพธ์ของการแก้ไขโมดูลและการประเมินส่วนขยาย ไฟล์ล็อกจะส่งเสริมการสร้างที่ทําซ้ำได้ ซึ่งช่วยให้มั่นใจได้ว่าสภาพแวดล้อมการพัฒนาจะสอดคล้องกัน นอกจากนี้ ยังช่วยเพิ่มประสิทธิภาพการสร้างโดยอนุญาตให้ Bazel ข้ามส่วนของกระบวนการแก้ไขที่ไม่ได้รับผลกระทบจากการเปลี่ยนแปลงในข้อกำหนดของโปรเจ็กต์ นอกจากนี้ ไฟล์ล็อกยังมีความเสถียรมากขึ้นด้วยการป้องกันการอัปเดตที่ไม่คาดคิดหรือทำลายการเปลี่ยนแปลงในคลังภายนอก จึงช่วยลดความเสี่ยงในการเกิดข้อบกพร่อง
การสร้างไฟล์ล็อก
ไฟล์ล็อกจะสร้างขึ้นภายใต้รูทของพื้นที่ทำงานโดยใช้ชื่อ MODULE.bazel.lock
ไฟล์นี้สร้างขึ้นหรืออัปเดตระหว่างกระบวนการบิลด์ โดยเฉพาะอย่างยิ่งหลังจากการแก้ไขข้อผิดพลาดของข้อบังคับและการประเมินส่วนขยาย ที่สำคัญคือ จะรวมเฉพาะข้อมูลที่ต้องพึ่งพาซึ่งรวมอยู่ในการเรียกใช้ปัจจุบันของบิลด์เท่านั้น
เมื่อเกิดการเปลี่ยนแปลงในโปรเจ็กต์ที่ส่งผลต่อทรัพยากร ไฟล์ล็อกจะอัปเดตโดยอัตโนมัติเพื่อแสดงสถานะใหม่ วิธีนี้ช่วยให้มั่นใจว่าไฟล์ล็อกจะยังคงโฟกัสที่ชุดทรัพยากร Dependency ที่เฉพาะเจาะจงซึ่งจำเป็นสำหรับบิลด์ปัจจุบัน โดยแสดงการขึ้นต่อกันที่ถูกต้องของโปรเจ็กต์
การใช้งานไฟล์ล็อก
คุณควบคุมไฟล์ล็อกได้ด้วย Flag --lockfile_mode
เพื่อปรับแต่งลักษณะการทํางานของ Bazel เมื่อสถานะโปรเจ็กต์แตกต่างจากไฟล์ล็อก โหมดที่ใช้ได้มีดังนี้
update
(ค่าเริ่มต้น): ใช้ข้อมูลที่มีอยู่ในไฟล์ล็อกเพื่อข้ามการดาวน์โหลดไฟล์รีจิสทรีที่รู้จัก และเพื่อหลีกเลี่ยงการประเมินส่วนขยายอีกครั้งซึ่งผลลัพธ์ยังคงเป็นปัจจุบัน หากข้อมูลขาดหายไป ระบบจะเพิ่มข้อมูลดังกล่าวลงในไฟล์ล็อก ในโหมดนี้ Bazel จะหลีกเลี่ยงการรีเฟรชข้อมูลที่เปลี่ยนแปลงได้ เช่น เวอร์ชันที่แยกออก สำหรับทรัพยากร Dependency ที่ไม่มีการเปลี่ยนแปลงrefresh
: เหมือนกับupdate
แต่ระบบจะรีเฟรชข้อมูลที่เปลี่ยนแปลงได้ทุกครั้งเมื่อเปลี่ยนไปใช้โหมดนี้ และทุกๆ ชั่วโมงโดยประมาณขณะอยู่ในโหมดนี้error
: เช่นเดียวกับupdate
แต่หากมีข้อมูลใดขาดหายไปหรือล้าสมัย Bazel จะทำงานล้มเหลวโดยมีข้อผิดพลาด โหมดนี้จะไม่เปลี่ยนแปลงไฟล์ล็อกหรือส่งคำขอเครือข่ายระหว่างการแก้ไข ส่วนขยายโมดูลที่ทำเครื่องหมายตัวเองเป็นreproducible
อาจยังส่งคำขอเครือข่ายได้ แต่คาดว่าจะให้ผลลัพธ์เดียวกันเสมอoff
: ไม่ได้ตรวจสอบหรืออัปเดตไฟล์ล็อก
ประโยชน์ของไฟล์ล็อก
ไฟล์ล็อกมีประโยชน์หลายประการและนำไปใช้ได้หลายวิธี ดังนี้
บิลด์ที่ทำซ้ำได้ การบันทึกเวอร์ชันหรือทรัพยากร Dependency ที่เจาะจงของไลบรารีซอฟต์แวร์จะทำให้ไฟล์ล็อกช่วยให้สร้างบิลด์ซ้ำได้ในทุกสภาพแวดล้อมและเมื่อเวลาผ่านไป นักพัฒนาซอฟต์แวร์สามารถพึ่งพาผลลัพธ์ที่สม่ำเสมอและคาดการณ์ได้เมื่อสร้างโปรเจ็กต์
การแก้ปัญหาที่รวดเร็วยิ่งขึ้น ไฟล์ล็อกช่วยให้ Bazel หลีกเลี่ยงการดาวน์โหลดไฟล์รีจิสทรีที่ใช้ในบิลด์ก่อนหน้าได้ ซึ่งจะช่วยปรับปรุงประสิทธิภาพของการสร้างได้อย่างมาก โดยเฉพาะในสถานการณ์ที่การแก้ปัญหาอาจใช้เวลานาน
ความเสถียรและการลดความเสี่ยง ล็อกไฟล์จะช่วยรักษาความเสถียรโดยป้องกันการอัปเดตที่ไม่คาดคิดหรือทำให้การเปลี่ยนแปลงในไลบรารีภายนอกเสียหาย การล็อกทรัพยากร Dependency ให้เป็นเวอร์ชันที่เฉพาะเจาะจงจะช่วยลดความเสี่ยงในการเกิดข้อบกพร่องเนื่องจากการอัปเดตที่เข้ากันไม่ได้หรือไม่ผ่านการทดสอบ
เนื้อหาไฟล์ล็อก
ไฟล์ล็อกมีข้อมูลที่จำเป็นทั้งหมดเพื่อพิจารณาว่าสถานะของโปรเจ็กต์มีการเปลี่ยนแปลงหรือไม่ รวมถึงผลลัพธ์ของการสร้างโปรเจ็กต์ในสถานะปัจจุบันด้วย ไฟล์ล็อกประกอบด้วย 2 ส่วนหลัก ได้แก่
- แฮชของไฟล์ระยะไกลทั้งหมดที่เป็นอินพุตในการแก้ไขข้อผิดพลาดของโมดูล
- สำหรับส่วนขยายโมดูลแต่ละรายการ ไฟล์ล็อกจะมีอินพุตที่ได้รับผลกระทบ ซึ่งแสดงเป็น
bzlTransitiveDigest
,usagesDigest
และช่องอื่นๆ รวมถึงเอาต์พุตของการเรียกใช้ส่วนขยายดังกล่าว ซึ่งเรียกว่าgeneratedRepoSpecs
ต่อไปนี้คือตัวอย่างที่แสดงโครงสร้างของไฟล์ล็อก พร้อมคำอธิบายของแต่ละส่วน
{
"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",
...
}
}
}
}
}
}
แฮชไฟล์รีจิสทรี
ส่วน registryFileHashes
มีแฮชของไฟล์ทั้งหมดจากรีจิสทรีระยะไกลที่เข้าถึงระหว่างการแก้ไขข้อขัดข้องของโมดูล เนื่องจากอัลกอริทึมความละเอียดจะกำหนดไว้อย่างสมบูรณ์เมื่อให้อินพุตเดียวกันและอินพุตระยะไกลทั้งหมดมีการแฮช วิธีนี้จึงทำให้ผลลัพธ์ของการแก้ปัญหาซึ่งทำซ้ำได้อย่างสมบูรณ์และหลีกเลี่ยงการทำซ้ำข้อมูลระยะไกลในไฟล์ล็อกมากเกินไป โปรดทราบว่าการดำเนินการนี้ยังกำหนดให้บันทึกด้วยเมื่อรีจิสทรีหนึ่งๆ ไม่มีโมดูลหนึ่งๆ แต่รีจิสทรีที่มีลําดับความสำคัญต่ำกว่ามี (ดูรายการ "ไม่พบ" ในตัวอย่าง) ข้อมูลที่มีการเปลี่ยนแปลงได้อยู่แล้วนี้สามารถอัปเดตได้ผ่าน
bazel mod deps --lockfile_mode=refresh
Bazel ใช้แฮชจากไฟล์ล็อกเพื่อค้นหาไฟล์รีจิสทรีในแคชที่เก็บก่อนที่จะดาวน์โหลด ซึ่งจะช่วยเพิ่มความเร็วในการแก้ไขในภายหลัง
เวอร์ชัน Yanked ที่เลือก
ส่วน selectedYankedVersions
มีโมดูลเวอร์ชันที่ดึงออกซึ่งเลือกตามความละเอียดของโมดูล เนื่องจากการดำเนินการนี้มักจะทำให้เกิดข้อผิดพลาดเมื่อพยายามสร้าง ส่วนนี้จึงจะไม่ว่างเปล่าก็ต่อเมื่อมีการอนุญาตเวอร์ชันที่ดึงออกอย่างชัดเจนผ่าน --allow_yanked_versions
หรือ BZLMOD_ALLOW_YANKED_VERSIONS
ช่องนี้เป็นสิ่งจำเป็นเนื่องจากเมื่อเทียบกับไฟล์โมดูลแล้ว ข้อมูลเวอร์ชันที่ถูกย้ายจะเปลี่ยนแปลงไม่ได้อยู่แล้ว จึงอ้างอิงด้วยแฮชไม่ได้ คุณอัปเดตข้อมูลนี้ได้ผ่าน bazel mod deps --lockfile_mode=refresh
ส่วนขยายโมดูล
ส่วน moduleExtensions
คือแผนที่ที่มีเฉพาะส่วนขยายที่ใช้ในการเรียกใช้ปัจจุบันหรือเรียกใช้ก่อนหน้านี้ โดยไม่รวมส่วนขยายที่ไม่ได้ใช้งานแล้ว กล่าวคือ หากไม่มีการใช้ส่วนขยายในกราฟความเกี่ยวข้องอีกต่อไป ระบบจะนำส่วนขยายนั้นออกจากmoduleExtensions
แผนภูมิ
หากส่วนขยายไม่เกี่ยวข้องกับระบบปฏิบัติการหรือประเภทสถาปัตยกรรม ส่วนนี้จะแสดงรายการ "ทั่วไป" เพียงรายการเดียวเท่านั้น หรือจะรวมหลายรายการโดยตั้งชื่อตามระบบปฏิบัติการ สถาปัตยกรรม หรือทั้ง 2 อย่างก็ได้ โดยแต่ละรายการจะสอดคล้องกับผลการประเมินส่วนขยายในรายละเอียดเหล่านั้น
รายการแต่ละรายการในการแมปส่วนขยายจะสอดคล้องกับส่วนขยายที่ใช้และจะระบุด้วยไฟล์และชื่อที่รวมอยู่ ค่าที่สอดคล้องกันของรายการแต่ละรายการจะมีข้อมูลที่เกี่ยวข้องซึ่งเชื่อมโยงกับชิ้นงานนั้นๆ ดังนี้
bzlTransitiveDigest
เป็นสรุปของการติดตั้งใช้งานส่วนขยายและไฟล์ .bzl ที่โหลดแบบสับเปลี่ยนusagesDigest
คือสรุปข้อมูลการใช้งานของส่วนขยายในกราฟการขึ้นต่อกัน ซึ่งมีแท็กทั้งหมด- ฟิลด์อื่นๆ ที่ไม่ได้ระบุซึ่งติดตามอินพุตอื่นๆ ไปยังส่วนขยาย เช่น เนื้อหาของไฟล์หรือไดเรกทอรีที่อ่าน หรือตัวแปรสภาพแวดล้อมที่ใช้
generatedRepoSpecs
เข้ารหัสที่เก็บที่สร้างโดยส่วนขยายด้วยอินพุตปัจจุบัน- ช่อง
moduleExtensionMetadata
(ไม่บังคับ) มีข้อมูลเมตาที่ส่วนขยายระบุ เช่น โมดูลรูทควรนําเข้าที่เก็บข้อมูลบางรายการที่สร้างขึ้นผ่านuse_repo
หรือไม่ ข้อมูลนี้จะขับเคลื่อนคำสั่งbazel mod tidy
ส่วนขยายโมดูลสามารถเลือกไม่ใช้การรวมในไฟล์ล็อกได้โดยการตั้งค่าข้อมูลเมตาที่แสดงผลด้วย reproducible = True
วิธีการดังกล่าวทำให้ทีมสัญญาว่า
ตนจะสร้างที่เก็บเดียวกันเสมอเมื่อได้รับอินพุตเดียวกัน
แนวทางปฏิบัติแนะนำ
ลองทำตามแนวทางปฏิบัติแนะนำต่อไปนี้เพื่อรับประโยชน์สูงสุดจากฟีเจอร์ไฟล์ล็อก
อัปเดตไฟล์ล็อกเป็นประจำเพื่อให้สอดคล้องกับการเปลี่ยนแปลงในข้อกำหนดหรือการกำหนดค่าของโปรเจ็กต์ วิธีนี้ช่วยให้มั่นใจว่าบิลด์ต่อๆ มานั้นอิงตามชุดทรัพยากร Dependency ที่เป็นปัจจุบันและถูกต้องที่สุด หากต้องการล็อกส่วนขยายทั้งหมดพร้อมกัน ให้เรียกใช้
bazel mod deps --lockfile_mode=update
รวมไฟล์ล็อกไว้ในการควบคุมเวอร์ชันเพื่ออำนวยความสะดวกในการทำงานร่วมกันและตรวจสอบว่าสมาชิกทุกคนในทีมมีสิทธิ์เข้าถึงไฟล์ล็อกเดียวกัน ซึ่งจะช่วยส่งเสริมสภาพแวดล้อมการพัฒนาที่สอดคล้องกันทั่วทั้งโปรเจ็กต์
ใช้
bazelisk
เพื่อเรียกใช้ Bazel และรวมไฟล์.bazelversion
ในการควบคุมเวอร์ชันที่ระบุเวอร์ชัน Bazel ที่สอดคล้องกับไฟล์ล็อก เนื่องจาก Bazel เองต้องอาศัยบิลด์ของคุณ ไฟล์ล็อกจึงมีความเฉพาะเจาะจงกับเวอร์ชัน Bazel และจะมีการเปลี่ยนแปลงแม้อยู่ระหว่างรุ่นต่างๆ ของ Bazel ที่เข้ากันได้แบบย้อนหลัง การใช้bazelisk
ช่วยให้มั่นใจว่านักพัฒนาซอฟต์แวร์ทุกคนใช้ Bazel เวอร์ชันที่ตรงกับไฟล์ล็อก
เมื่อทำตามแนวทางปฏิบัติแนะนำเหล่านี้ คุณจะสามารถใช้ฟีเจอร์ไฟล์ล็อกใน Bazel ได้อย่างมีประสิทธิภาพ ซึ่งจะนำไปสู่เวิร์กโฟลว์การพัฒนาซอฟต์แวร์ที่มีประสิทธิภาพ เชื่อถือได้ และร่วมมือกันได้มากขึ้น
ความขัดแย้งในการรวม
รูปแบบล็อกไฟล์ได้รับการออกแบบมาเพื่อลดความขัดแย้งในการรวม แต่ก็อาจเกิดขึ้นได้
ความละเอียดอัตโนมัติ
Bazel มีไดรเวอร์การผสาน Git ที่กำหนดเองเพื่อช่วยแก้ไขความขัดแย้งเหล่านี้โดยอัตโนมัติ
ตั้งค่าไดรเวอร์โดยเพิ่มบรรทัดนี้ลงในไฟล์ .gitattributes
ที่รูทของที่เก็บ Git
# A custom merge driver for the Bazel lockfile.
# https://bazel.build/external/lockfile#automatic-resolution
MODULE.bazel.lock merge=bazel-lockfile-merge
จากนั้นนักพัฒนาแอปแต่ละรายที่ต้องการใช้ไดรเวอร์จะต้องลงทะเบียนไดรเวอร์ดังกล่าวเพียงครั้งเดียวโดยทำตามขั้นตอนต่อไปนี้
- ติดตั้ง jq (1.5 ขึ้นไป)
- เรียกใช้คำสั่งต่อไปนี้
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"
การแก้ไขด้วยตนเอง
ข้อขัดแย้งในการผสานที่ง่ายในช่อง registryFileHashes
และ selectedYankedVersions
สามารถแก้ไขได้อย่างปลอดภัยโดยเก็บรายการทั้งหมดจากทั้ง 2 ด้านของข้อขัดแย้งไว้
คุณไม่ควรแก้ไขข้อขัดแย้งในการผสานประเภทอื่นๆ ด้วยตนเอง ให้ดำเนินการต่อไปนี้แทน
- กู้คืนสถานะก่อนหน้าของไฟล์ล็อกผ่าน
git reset MODULE.bazel.lock && git checkout MODULE.bazel.lock
- แก้ไขความขัดแย้งในไฟล์
MODULE.bazel
- เรียกใช้
bazel mod deps
เพื่ออัปเดตไฟล์ล็อก