ระบบบิลด์ที่อิงตามอาร์ติแฟกต์

วันที่ รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

หน้านี้มีเนื้อหาเกี่ยวกับระบบการสร้างที่ใช้สิ่งประดิษฐ์และปรัชญาที่อยู่เบื้องหลัง งานสร้างสรรค์ Bazel เป็นระบบการสร้างที่ใช้วัตถุเป็นหลัก ระหว่างบิลด์ตามงาน ระบบนี้ถือเป็นขั้นตอนที่ดี เหนือสคริปต์การสร้าง สคริปต์จะให้ประสิทธิภาพที่มากเกินไปสำหรับ วิศวกรแต่ละคนโดยให้ทีมมอบหมายงานของตัวเอง

ระบบบิลด์ที่อิงตามอาร์ติแฟกต์มีงานจำนวนหนึ่งที่ระบบกำหนด ที่วิศวกรสามารถกำหนดค่าได้อย่างจำกัด วิศวกรยังคงบอกระบบ อะไรที่ควรสร้าง แต่ระบบบิลด์จะเป็นตัวกำหนดวิธีการสร้าง เช่นเดียวกับ ระบบบิลด์ที่อิงตามงาน ระบบบิลด์ที่ใช้อาร์ติแฟกต์ เช่น Bazel มีไฟล์บิลด์ แต่เนื้อหาของไฟล์บิลด์เหล่านั้นแตกต่างกันมาก แทน มากกว่าการเป็นชุดคำสั่งที่จำเป็น ในภาษาสคริปต์ของทูร์ริง ที่อธิบายถึงวิธีสร้างเอาต์พุต ไฟล์บิลด์ใน Bazel เป็นสิ่งที่ ไฟล์ Manifest ที่อธิบายชุดอาร์ติแฟกต์ที่จะสร้าง ทรัพยากร Dependency และ ชุดตัวเลือกที่จำกัดซึ่งส่งผลต่อการสร้างแอป เมื่อวิศวกรเรียกใช้ bazel ในบรรทัดคำสั่ง พวกเขาจะระบุชุดเป้าหมายที่จะสร้าง (อะไร) และ Bazel รับหน้าที่ในการกำหนดค่า เรียกใช้ และกำหนดเวลาการคอมไพล์ ขั้นตอน (วิธีการ) เพราะตอนนี้ระบบการสร้างสามารถ ควบคุมสิ่งต่างๆ ได้อย่างเต็มที่ ใช้งานเมื่อใด วิธีนี้สามารถรับประกันได้ดีขึ้นมากว่าจะทำให้ มีประสิทธิภาพมากขึ้น ในขณะเดียวกันก็รับประกันความถูกต้อง

มุมมองเกี่ยวกับฟังก์ชันการทำงาน

คุณสามารถเปรียบเทียบระหว่างระบบบิลด์ที่ใช้อาร์ติแฟกต์กับฟังก์ชันการทำงานได้อย่างง่ายดาย การเขียนโปรแกรม ภาษาโปรแกรมดั้งเดิมที่จำเป็น (เช่น Java, C และ Python) ระบุรายการคำสั่งที่จะดำเนินการทีละรายการใน แบบเดียวกับที่ระบบสร้างแบบอิงตามงานช่วยให้โปรแกรมเมอร์กำหนดชุดขั้นตอนได้ ที่จะดำเนินการได้ ภาษาโปรแกรมที่ใช้งาน (เช่น Haskell และ ML) ใน มีโครงสร้างคล้ายกับชุดสมการทางคณิตศาสตร์ ใน โปรแกรมเมอร์จะอธิบายถึงการคำนวณที่จะนำมาใช้งาน แต่ มีรายละเอียดเกี่ยวกับเวลาและวิธีในการดำเนินการคำนวณนั้น คอมไพเลอร์

ส่วนนี้สอดคล้องกับแนวคิดในการประกาศไฟล์ Manifest ในระบบบิลด์ที่ใช้อาร์ติแฟกต์ และปล่อยให้ระบบหาวิธีดำเนินการกับบิลด์ หลายโจทย์ทำไม่ได้ แสดงออกได้อย่างง่ายดายโดยใช้การเขียนโปรแกรมที่ใช้งานได้ ได้เป็นอย่างดี: ภาษามักจะสามารถ คู่ขนานกันเพียงเล็กน้อย และรับประกันความถูกต้องของโปรแกรมดังกล่าวอย่างเข้มงวด ซึ่งเป็นไปไม่ได้ในภาษาที่จำเป็นต้องใช้ โจทย์ง่ายๆ ในการแสดงออกโดยใช้ การเขียนโปรแกรมด้านฟังก์ชันการทำงานคือด้านที่มีการเปลี่ยนรูปแบบเพียงส่วนเดียว ของข้อมูลลงในอีกส่วนหนึ่งโดยใช้ชุดกฎหรือฟังก์ชัน ซึ่งแน่นอนว่า ระบบบิลด์คืออะไร: ทั้งระบบเป็นฟังก์ชันทางคณิตศาสตร์ที่มีประสิทธิภาพ ที่นำไฟล์ต้นฉบับ (และเครื่องมืออย่างคอมไพเลอร์) เป็นอินพุตและสร้าง ไบนารีเป็นเอาต์พุต จึงไม่น่าแปลกใจที่โมเดลนี้สามารถวางรากฐานให้กับงานสร้างได้ดี ระบบพื้นฐานเกี่ยวกับหลักการของการเขียนโปรแกรมเชิงฟังก์ชันการทำงาน

ทำความเข้าใจระบบบิลด์ที่ใช้อาร์ติแฟกต์

ระบบสร้างของ Google ที่ชื่อว่า Blaze เป็นระบบการสร้างที่ใช้วัตถุเป็นหลักระบบแรก บาเซล คือ Blaze เวอร์ชันโอเพนซอร์ส

ต่อไปนี้คือลักษณะของไฟล์บิลด์ (โดยทั่วไปชื่อ BUILD) ใน Bazel

java_binary(
    name = "MyBinary",
    srcs = ["MyBinary.java"],
    deps = [
        ":mylib",
    ],
)
java_library(
    name = "mylib",
    srcs = ["MyLibrary.java", "MyHelper.java"],
    visibility = ["//java/com/example/myproduct:__subpackages__"],
    deps = [
        "//java/com/example/common",
        "//java/com/example/myproduct/otherlib",
    ],
)

ใน Bazel ไฟล์ BUILD ไฟล์จะกำหนดเป้าหมาย เป้าหมาย 2 ประเภทที่นี่คือ java_binary และ java_library ทุกเป้าหมายสอดคล้องกับอาร์ติแฟกต์ที่ ที่ระบบสามารถสร้างได้: เป้าหมายไบนารีจะสร้างไบนารีที่สามารถ ดำเนินการโดยตรง และเป้าหมายไลบรารีจะสร้างไลบรารีที่สามารถใช้งานได้โดย ไบนารีหรือไลบรารีอื่นๆ ทุกเป้าหมายมี:

  • name: วิธีอ้างอิงเป้าหมายในบรรทัดคำสั่งและโดยบุคคลอื่น เป้าหมาย
  • srcs: ไฟล์ต้นฉบับที่จะรวบรวมเพื่อสร้างอาร์ติแฟกต์สำหรับเป้าหมาย
  • deps: เป้าหมายอื่นๆ ที่ต้องสร้างขึ้นก่อนเป้าหมายนี้และลิงก์กับ รายการดังกล่าว

ทรัพยากร Dependency อาจอยู่ในแพ็กเกจเดียวกันก็ได้ (เช่น ของ MyBinary ขึ้นอยู่กับ :mylib) หรือแพ็กเกจอื่นในลำดับชั้นของแหล่งที่มาเดียวกัน (เช่น ทรัพยากร Dependency ของ mylib ใน //java/com/example/common)

คุณจะสร้างบิลด์โดยใช้บรรทัดคำสั่งของ Bazel ได้เช่นเดียวกับระบบบิลด์ตามงาน ของ Google หากต้องการสร้างเป้าหมาย MyBinary ให้เรียกใช้ bazel build :MyBinary หลัง ป้อนคำสั่งนั้นเป็นครั้งแรกในที่เก็บเปล่า Bazel ทำดังนี้

  1. แยกวิเคราะห์ไฟล์ BUILD ทุกไฟล์ในพื้นที่ทำงานเพื่อสร้างกราฟของทรัพยากร Dependency ท่ามกลางอาร์ติแฟกต์ได้อีกด้วย
  2. ใช้กราฟเพื่อระบุทรัพยากร Dependency แบบทรานซิทีฟของ MyBinary นั่น คือ ทุกเป้าหมายที่ MyBinary พึ่งพาและทุกเป้าหมายที่ ขึ้นอยู่กับการเกิดซ้ำ
  3. สร้างทรัพยากร Dependency แต่ละรายการตามลำดับ Bazel เริ่มต้นด้วยการสร้าง เป้าหมายที่ไม่มีทรัพยากร Dependency อื่นๆ และติดตามทรัพยากร Dependency ใด คุณยังต้องสร้างสำหรับแต่ละเป้าหมาย ทันทีที่ทุกเป้าหมาย มีการสร้างทรัพยากร Dependency แล้ว Bazel เริ่มสร้างเป้าหมายดังกล่าว กระบวนการนี้ จะดำเนินต่อไปจนกว่าทรัพยากร Dependency แบบทรานซิทีฟของ MyBinary ทุกรายการ ที่สร้างขึ้น
  4. สร้าง MyBinary เพื่อสร้างไบนารีที่ดำเนินการได้ขั้นสุดท้ายซึ่งลิงก์อยู่ใน ทรัพยากร Dependency ที่สร้างไว้ในขั้นตอนที่ 3

โดยพื้นฐานแล้ว อาจดูเหมือนว่า สิ่งที่เกิดขึ้นที่นี่ไม่ง่ายนัก แตกต่างจากสิ่งที่เกิดขึ้นเมื่อใช้ระบบบิลด์ตามงาน ที่จริงแล้ว ผลลัพธ์สุดท้ายจะเป็นไบนารีเดียวกัน และมีกระบวนการในการสร้างผลลัพธ์ที่เกี่ยวข้อง วิเคราะห์ขั้นตอนจำนวนมากเพื่อค้นหาทรัพยากร Dependency ต่างๆ แล้วจึงเรียกใช้ ขั้นตอนเหล่านี้ตามลำดับ แต่มีความแตกต่างที่สำคัญมาก ข้อความแรกปรากฏขึ้น ในขั้นตอนที่ 3: เนื่องจาก Bazel รู้ว่าแต่ละเป้าหมายสร้างเฉพาะไลบรารี Java รู้ว่าสิ่งที่ต้องทำคือการเรียกใช้คอมไพเลอร์ Java แทนที่จะทำงานด้วยตนเอง สคริปต์ที่กำหนดโดยผู้ใช้ จึงทราบว่าสามารถเรียกใช้ขั้นตอนเหล่านี้ควบคู่กันไปได้อย่างปลอดภัย ทำให้ประสิทธิภาพเพิ่มขึ้นตามลำดับในการสร้าง กำหนดเป้าหมายทีละเครื่องในเครื่องแบบหลายแกน และเป็นไปได้เนื่องจาก แนวทางที่ใช้อาร์ติแฟกต์จะทำให้ระบบบิลด์มีหน้าที่รับผิดชอบการดำเนินงานของตนเอง เพื่อให้ระบบรับประกันความสอดคล้องกัน ได้ดียิ่งขึ้น

แต่ประโยชน์ที่ได้มากกว่าการทำงานพร้อมกัน สิ่งต่อไปที่ วิธีการนี้ช่วยให้เราเห็นได้ชัดเมื่อนักพัฒนาแอปพิมพ์ bazel build :MyBinary เป็นครั้งที่ 2 โดยไม่ทำการเปลี่ยนแปลงใดๆ นั่นคือ Bazel จะออกในเวลาน้อยลง หนึ่งวินาทีพร้อมข้อความที่ระบุว่าเป้าหมายเป็นปัจจุบันแล้ว นี่คือ ได้เพราะกระบวนทัศน์การเขียนโปรแกรมเชิงฟังก์ชันการทำงานที่เราพูดถึง ก่อนหน้านี้ Bazel รู้ว่าแต่ละเป้าหมายเป็นผลลัพธ์จากการเรียกใช้ Java เพียงอย่างเดียว และรู้ว่าเอาต์พุตจากคอมไพเลอร์ Java ขึ้นอยู่กับ อินพุต ตราบใดที่อินพุตไม่มีการเปลี่ยนแปลง เอาต์พุตก็จะใช้ซ้ำได้ และการวิเคราะห์นี้ใช้งานได้ในทุกระดับ หาก MyBinary.java เปลี่ยนแปลง Bazel รู้ ในการสร้าง MyBinary ใหม่ แต่ใช้ mylib ซ้ำ หากไฟล์ต้นฉบับสำหรับ การเปลี่ยนแปลง //java/com/example/common รายการ Bazel รู้ว่าจะสร้างไลบรารีนั้นใหม่ mylib และ MyBinary แต่ใช้ //java/com/example/myproduct/otherlib ซ้ำ เนื่องจาก Bazel รู้คุณสมบัติของเครื่องมือที่ทำงานในทุกขั้นตอน ก็สามารถสร้างเฉพาะ ชุดอาร์ติแฟกต์ขั้นต่ำได้ในแต่ละครั้ง เพื่อรับประกันว่าโมเดลจะ ไม่สร้างสิ่งใหม่ๆ ที่ไม่อัปเดต

การกำหนดกรอบใหม่ของกระบวนการบิลด์ในแง่ของอาร์ติแฟกต์แทนที่จะเป็นงานนั้นเป็นสิ่งที่ซับซ้อน แต่เปี่ยมประสิทธิภาพ ด้วยการลดความยืดหยุ่นที่แสดงต่อโปรแกรมเมอร์ การสร้าง ทำให้ระบบรู้มากขึ้นว่า เรากำลังทำอะไรในทุกขั้นตอนของการสร้าง ช่วย ใช้ความรู้นี้เพื่อทำให้งานสร้างมีประสิทธิภาพขึ้นมากเช่นกัน ประมวลผลและนำผลลัพธ์เหล่านั้นมาใช้ซ้ำ แต่นี่เป็นเพียงขั้นตอนแรก องค์ประกอบสำคัญของการทำงานพร้อมกันเหล่านี้ และนำกลับมาใช้ซ้ำเป็นรากฐานสำหรับการกระจาย และระบบสร้างที่รองรับการปรับขนาดได้สูง

เคล็ดลับเด็ดอื่นๆ ของ Bazel

ระบบการสร้างที่ใช้วัตถุเป็นหลักจะช่วยแก้ปัญหาการทำงานควบคู่กันไป และการใช้งานซ้ำในระบบบิลด์ที่อิงตามงาน แต่ยังคงมี มีปัญหา 2-3 ข้อก่อนหน้านี้ซึ่งเรายังไม่ได้จัดการ Bazel ฉลาด วิธีแก้ปัญหาแต่ละแบบ และเราควรหารือกันก่อนที่จะดำเนินการต่อ

เครื่องมือที่เป็นทรัพยากร Dependency

ปัญหาหนึ่งที่เราเจอก่อนหน้านี้คือเวอร์ชันต่างๆ ขึ้นอยู่กับเครื่องมือที่ติดตั้งไว้ บนเครื่องของเรา และการสร้างบิลด์ซ้ำทั่วทั้งระบบก็อาจเป็นเรื่องยากเนื่องจาก เวอร์ชันเครื่องมือหรือตำแหน่งต่างๆ ปัญหายิ่งยากขึ้นเรื่อยๆ เมื่อโปรเจ็กต์ของคุณใช้ภาษาที่ต้องใช้เครื่องมือที่แตกต่างกันตาม ที่สร้างขึ้นหรือคอมไพล์ (เช่น Windows กับ Linux) และแต่ละแพลตฟอร์มเหล่านั้น ต้องใช้ชุดเครื่องมือที่ต่างกันเล็กน้อยในการดำเนินการ งานเดียวกัน

Bazel แก้ปัญหาส่วนแรกของโจทย์นี้โดยถือว่าเครื่องมือเป็นทรัพยากร Dependency ของ แต่ละเป้าหมาย java_library ทุกรายการในพื้นที่ทำงานอิงตาม Java โดยปริยาย ซึ่งมีค่าเริ่มต้นเป็นคอมไพเลอร์ที่รู้จัก เมื่อใดก็ตามที่ Bazel สร้าง java_library ระบบ ให้ตรวจสอบว่าคอมไพเลอร์ที่ระบุพร้อมใช้งาน ในตำแหน่งที่รู้จัก เช่นเดียวกับการขึ้นต่อกันอื่นๆ หากคอมไพเลอร์ Java ระบบจะสร้างอาร์ติแฟกต์ทุกรายการที่ต้องใช้ทรัพยากรนั้นใหม่

Bazel แก้ปัญหาในส่วนที่ 2 ซึ่งก็คือความเป็นอิสระของแพลตฟอร์ม สร้างการกำหนดค่า ไม่ใช่ กำหนดเป้าหมายโดยตรงจะขึ้นอยู่กับเครื่องมือของตน ทั้งนี้ขึ้นอยู่กับประเภทของการกำหนดค่า:

  • การกำหนดค่าโฮสต์: เครื่องมือสร้างที่ทำงานระหว่างบิลด์
  • การกำหนดค่าเป้าหมาย: การสร้างไบนารีที่คุณร้องขอในท้ายที่สุด

การขยายระบบบิลด์

Bazel มีเป้าหมายสำหรับภาษาโปรแกรมยอดนิยมหลายภาษา แต่วิศวกรจะอยากทำมากกว่านี้เสมอ ซึ่งเป็นข้อดีของการใช้ ความยืดหยุ่นในการสนับสนุนกระบวนการสร้างได้ทุกรูปแบบ และ คงจะดีกว่าหากจะไม่ใช้ระบบการสร้างที่ใช้อาร์ติแฟกต์เป็นหลัก โชคดีที่ Bazel อนุญาตให้ขยายประเภทเป้าหมายที่รองรับ การเพิ่มกฎที่กำหนดเอง

ในการกำหนดกฎใน Bazel ผู้สร้างกฎจะประกาศอินพุตที่กฎ ต้องการ (ในรูปแบบของแอตทริบิวต์ที่ส่งในไฟล์ BUILD) และแท็กคงที่ ชุดของเอาต์พุตที่กฎสร้างขึ้น และผู้เขียนยังกำหนดการดำเนินการ สร้างขึ้นโดยกฎนั้น โดยการดำเนินการแต่ละอย่างจะประกาศอินพุตและเอาต์พุต เรียกใช้ไฟล์ปฏิบัติการเฉพาะ หรือเขียนสตริงเฉพาะลงในไฟล์ และสามารถ เชื่อมต่อกับการทำงานอื่นๆ ผ่านอินพุตและเอาต์พุต ซึ่งหมายความว่าการดำเนินการต่างๆ คือหน่วยที่ประกอบกันได้ระดับล่างสุดในระบบบิลด์ ซึ่งการดำเนินการทำได้ ทุกอย่างที่ต้องการ ตราบใดที่ใช้เฉพาะอินพุตและเอาต์พุตที่ประกาศไว้ และ Bazel ดูแลเรื่องการตั้งเวลาการดำเนินการและแคชผลลัพธ์ตามความเหมาะสม

ระบบไม่ได้เด็ดขาดเพราะไม่มีวิธีหยุดนักพัฒนาแอปการดำเนินการ จากการดำเนินการบางอย่าง เช่น การนำกระบวนการที่ไม่เจาะจงซึ่งเป็นส่วนหนึ่งของ การกระทำของพวกเขา แต่วิธีนี้ไม่ได้เกิดขึ้นบ่อยนัก และการผลักดันให้ ความเป็นไปได้ของการละเมิดไปจนถึงระดับการดำเนินการลดลงอย่างมาก โอกาสเกิดข้อผิดพลาด กฎที่รองรับภาษาและเครื่องมือที่ใช้กันทั่วไปจำนวนมากมีดังนี้ ออนไลน์อย่างแพร่หลาย และโครงการส่วนใหญ่ไม่จำเป็นต้องกำหนด กฎ แม้แต่สำหรับกฎที่กำหนดไว้ ก็ต้องกำหนดคำจำกัดความของกฎไว้ใน ส่วนกลางในที่เก็บ ซึ่งหมายความว่าวิศวกรส่วนใหญ่จะสามารถใช้ กฎเหล่านั้นได้โดยไม่ต้องกังวลเรื่องการนำไปใช้

แยกสภาพแวดล้อม

การดำเนินการต่างๆ อาจดูเหมือนพบปัญหาเดียวกันกับงานอื่นๆ เป็นไปไม่ได้ใช่ไหมที่จะเขียนการทำงานที่ทั้ง 2 อย่างนี้เขียนเหมือนกัน แล้วเกิดการขัดแย้งกันได้อย่างไร ที่จริงแล้ว Bazel สร้าง ความขัดแย้ง ซึ่งจะเป็นไปไม่ได้โดยใช้แซนด์บ็อกซ์ รองรับใน การดำเนินการทุกอย่างจะแยกออกจากการดำเนินการอื่นๆ ทั้งหมดผ่านระบบไฟล์ แซนด์บ็อกซ์ การดำเนินการแต่ละรายการจะดูได้เฉพาะมุมมองที่จำกัดของ ระบบไฟล์ที่มีอินพุตที่ประกาศและเอาต์พุตที่มี การผลิต ซึ่งมีการบังคับใช้โดยระบบต่างๆ เช่น LXC บน Linux ซึ่งเป็นเทคโนโลยีเดียวกัน อยู่หลัง Docker ซึ่งจะไม่สามารถดำเนินการใดๆ ได้ อีกไฟล์หนึ่ง เนื่องจากไม่สามารถอ่านไฟล์ที่ไม่มีการแจ้ง และ ไฟล์ที่เขียนแต่ไม่ได้ประกาศจะถูกตัดทิ้งเมื่อการดำเนินการ เสร็จสิ้น นอกจากนี้ Bazel ยังใช้แซนด์บ็อกซ์เพื่อจำกัดการทำงานจากการสื่อสารผ่านทาง เครือข่าย

การกำหนดทรัพยากร Dependency ภายนอก

ยังเหลืออีกหนึ่งปัญหา: ระบบมักจะต้องดาวน์โหลด ทรัพยากร Dependency (ไม่ว่าจะเป็นเครื่องมือหรือไลบรารี) จากแหล่งที่มาภายนอกมากกว่า สร้างชิ้นงานเหล่านั้นโดยตรง ซึ่งสามารถดูได้ในตัวอย่างผ่านทาง ทรัพยากร Dependency @com_google_common_guava_guava//jar ซึ่งดาวน์โหลดไฟล์ JAR จาก Maven

ทั้งนี้ขึ้นอยู่กับไฟล์ที่อยู่นอกพื้นที่ทำงานปัจจุบัน ไฟล์เหล่านี้อาจ เปลี่ยนแปลงได้ตลอดเวลา ซึ่งอาจทำให้ระบบบิลด์ต้องตรวจสอบ ไม่ว่าจะเป็นข้อมูลใหม่ๆ หากไฟล์ระยะไกลมีการเปลี่ยนแปลงโดยไม่มีการเปลี่ยนแปลงที่สอดคล้องกัน ในซอร์สโค้ดของพื้นที่ทำงาน ก็อาจทำให้มีบิลด์ที่ไม่สามารถทำซ้ำได้ ซึ่งเป็นบิลด์ อาจทำงานได้วันหนึ่ง และล้มเหลวในวันถัดไปโดยไม่มีสาเหตุที่แน่ชัดเนื่องจากไม่มีใคร การเปลี่ยนการขึ้นต่อกัน สุดท้าย ทรัพยากร Dependency ภายนอกจะ เพิ่มความปลอดภัยได้อย่างมาก ความเสี่ยงเมื่อบุคคลที่สามเป็นเจ้าของ: หากผู้โจมตีสามารถแฝงตัว เซิร์ฟเวอร์ของบุคคลที่สามดังกล่าว จะสามารถแทนที่ไฟล์ Dependency ด้วยองค์ประกอบ ออกแบบได้เอง ซึ่งอาจทำให้ผู้ใช้ ควบคุมงานสร้างของคุณได้อย่างเต็มที่ และเอาต์พุตของสภาพแวดล้อม

ปัญหาพื้นฐานคือเราอยากให้ระบบบิลด์ตระหนักถึงสิ่งเหล่านี้ ไฟล์โดยไม่ต้องตรวจสอบในการควบคุมแหล่งที่มา กำลังอัปเดตทรัพยากร Dependency ควรเป็นสิ่งที่มีสติ แต่การตัดสินใจนั้นควรเกิดขึ้นเพียงครั้งเดียว แทนที่จะจัดการโดยวิศวกรเป็นรายบุคคลหรือโดยอัตโนมัติโดย ระบบ นั่นเป็นเพราะถึงแม้ว่าจะมีโมเดล "Live at Head" แล้ว เราก็ยังต้องการสิ่งที่สร้าง ที่จะตัดสินใจ ซึ่งก็หมายความว่าหากคุณตรวจสอบการคอมมิตจาก คุณควรเห็นทรัพยากร Dependency ตามที่เป็น ณ ขณะนั้น ไม่ใช่ กันเลย

Bazel และระบบบิลด์อื่นๆ ช่วยแก้ปัญหานี้โดยกำหนดให้ ไฟล์ Manifest ของทั้งพื้นที่ทํางานที่แสดงแฮชแบบเข้ารหัสสําหรับภายนอกทั้งหมด ทรัพยากร Dependency ในพื้นที่ทำงาน แฮชจึงเป็นวิธีที่สั้นกระชับในการแสดงถึง ไฟล์โดยไม่ต้องตรวจสอบทั้งไฟล์ลงในการควบคุมแหล่งที่มา เมื่อใดก็ตามที่มี ระบบจะอ้างอิงทรัพยากร Dependency ภายนอกจากพื้นที่ทำงาน ซึ่งแฮชของทรัพยากร Dependency นั้น เพิ่มลงในไฟล์ Manifest ไม่ว่าจะเพิ่มด้วยตนเองหรือโดยอัตโนมัติ เมื่อ Bazel เรียกใช้ โมเดลดังกล่าวจะตรวจสอบแฮชจริงของทรัพยากร Dependency ที่แคชไว้กับรายการที่คาดไว้ แฮชที่กำหนดไว้ในไฟล์ Manifest และดาวน์โหลดไฟล์อีกครั้งเฉพาะเมื่อแฮชแตกต่างกันเท่านั้น

หากอาร์ติแฟกต์ที่เราดาวน์โหลดมีแฮชต่างจากที่ประกาศใน ไฟล์ Manifest การสร้างจะล้มเหลวเว้นแต่จะมีการอัปเดตแฮชในไฟล์ Manifest ช่วงเวลานี้ สามารถดำเนินการได้โดยอัตโนมัติ แต่การเปลี่ยนแปลงดังกล่าวต้องได้รับการอนุมัติและเช็คอิน การควบคุมแหล่งที่มาก่อนบิลด์จะยอมรับทรัพยากร Dependency ใหม่ ซึ่งหมายความว่า มีบันทึกว่าทรัพยากร Dependency ได้รับการอัปเดตเมื่อใดเสมอ ไม่สามารถเปลี่ยนทรัพยากร Dependency ได้หากไม่มีการเปลี่ยนแปลงที่สอดคล้องกันในแหล่งที่มาของพื้นที่ทำงาน และยังหมายความว่า เมื่อคุณดูซอร์สโค้ดรุ่นเก่า รหัส ได้รับการรับประกันว่าบิลด์จะใช้ทรัพยากร Dependency เดียวกันกับที่บิลด์นั้นใช้อยู่ เมื่อเช็คอินเวอร์ชันนั้นแล้ว (ไม่เช่นนั้นก็จะล้มเหลวหากทรัพยากร Dependency เหล่านี้ ไม่มีให้บริการอีกต่อไป)

แน่นอนว่าอาจยังคงเป็นปัญหาหากเซิร์ฟเวอร์ระยะไกลไม่พร้อมใช้งาน หรือ เริ่มแสดงข้อมูลที่เสียหาย ซึ่งอาจทำให้บิลด์ทั้งหมดเริ่มล้มเหลว หากไม่มีสำเนาของทรัพยากร Dependency อื่น เพื่อหลีกเลี่ยงปัญหานี้ ขอแนะนำว่า สำหรับทุกโครงการที่ไม่สำคัญ ทรัพยากร Dependency ในเซิร์ฟเวอร์หรือบริการที่คุณเชื่อถือและควบคุม มิฉะนั้น จะต้องขอความช่วยเหลือจากบุคคลที่สามสำหรับระบบบิลด์ของคุณ ความพร้อมใช้งาน แม้ว่าแฮชเช็คอินจะรับประกันความปลอดภัยก็ตาม