ไฟล์ Bazel Lock

รายงานปัญหา ดูแหล่งที่มา

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

การสร้าง Lockfile

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

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

การใช้งาน Lockfile

แฟล็ก --lockfile_mode จะควบคุมไฟล์ล็อกไฟล์เหล่านั้นได้เพื่อปรับแต่งลักษณะการทำงานของ Bazel เมื่อสถานะของโปรเจ็กต์ต่างจากไฟล์ล็อก โหมดที่ใช้ได้มีดังนี้

  • update (ค่าเริ่มต้น): หากสถานะของโปรเจ็กต์ตรงกับ Lockfile ระบบจะแสดงผลการแก้ปัญหาจาก Lockfile ทันที มิเช่นนั้น ระบบจะดำเนินการแก้ปัญหาและอัปเดตไฟล์ล็อกเพื่อแสดงสถานะปัจจุบัน
  • error: หากสถานะของโปรเจ็กต์ตรงกับ Lockfile ระบบจะแสดงผลการแก้ปัญหาจาก Lockfile ไม่เช่นนั้น Bazel จะแสดงข้อผิดพลาดที่ระบุความแตกต่างระหว่างโปรเจ็กต์และไฟล์ Lock โหมดนี้จะมีประโยชน์อย่างยิ่งเมื่อคุณต้องการตรวจสอบว่าทรัพยากร Dependency ของโปรเจ็กต์ไม่มีการเปลี่ยนแปลง และระบบจะถือว่าความแตกต่างทั้งหมดเป็นข้อผิดพลาด
  • off: ไม่ตรวจสอบ Lockfile เลย

ประโยชน์ของ Lockfile

Lockfile มีประโยชน์หลายอย่างและสามารถใช้ได้หลากหลายวิธี ดังนี้

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

  • การข้ามการแก้ปัญหาที่มีประสิทธิภาพ Lockfile ช่วยให้ Bazel ข้ามกระบวนการแก้ปัญหาหากไม่มีการเปลี่ยนแปลงทรัพยากร Dependency ของโปรเจ็กต์ตั้งแต่บิลด์ครั้งล่าสุด วิธีนี้ช่วยปรับปรุงประสิทธิภาพของการสร้างได้อย่างมาก โดยเฉพาะอย่างยิ่งในสถานการณ์ที่การแก้ปัญหาใช้เวลานาน

  • ความเสถียรและการลดความเสี่ยง Lockfile ช่วยรักษาความเสถียรโดยการป้องกันการอัปเดตที่ไม่คาดคิดหรือทำให้การเปลี่ยนแปลงในไลบรารีภายนอกเสียหาย การล็อกทรัพยากร Dependency เฉพาะเวอร์ชันที่เฉพาะเจาะจง ความเสี่ยงของการเกิดข้อบกพร่องเนื่องจากการอัปเดตที่ใช้ร่วมกันไม่ได้หรือยังไม่ได้ทดสอบจะลดลง

เนื้อหาของ Lockfile

Lockfile มีข้อมูลที่จำเป็นทั้งหมดในการตรวจสอบว่าสถานะของโปรเจ็กต์มีการเปลี่ยนแปลงหรือไม่ และยังรวมถึงผลของการสร้างโปรเจ็กต์ในสถานะปัจจุบันด้วย Lockfile ประกอบด้วยส่วนหลัก 2 ส่วน ได้แก่

  1. อินพุตของความละเอียดโมดูล เช่น moduleFileHash, flags และ localOverrideHashes รวมทั้งเอาต์พุตของความละเอียด ซึ่งก็คือ moduleDepGraph
  2. สำหรับส่วนขยายโมดูลแต่ละรายการ Lockfile จะมีอินพุตที่ได้รับผลกระทบ ซึ่งจะแสดงโดย transitiveDigest และเอาต์พุตของการเรียกใช้ส่วนขยายดังกล่าวที่เรียกว่า generatedRepoSpecs

นี่คือตัวอย่างที่แสดงให้เห็นโครงสร้างของ Lockfile พร้อมคำอธิบายสำหรับแต่ละส่วน

{
  "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": {
      "general": {
        "transitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    },
    "//:extension.bzl%lockfile_ext2": {
      "os:macos": {
        "transitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      },
      "os:linux": {
        "transitiveDigest": "eWDzxG/aLsyY3Ubrto....+Jp4maQvEPxn0pLK=",
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    }
  }
}

แฮชไฟล์โมดูล

moduleFileHash แสดงแฮชของเนื้อหาไฟล์ MODULE.bazel หากมีการเปลี่ยนแปลงในไฟล์นี้ ค่าแฮชจะแตกต่างไป

ธง

ออบเจ็กต์ Flags จะจัดเก็บแฟล็กทั้งหมดที่อาจส่งผลต่อผลลัพธ์ความละเอียด

แฮชการลบล้างในเครื่อง

หากโมดูลรูทมี local_path_overrides ส่วนนี้จะจัดเก็บแฮชของไฟล์ MODULE.bazel ไว้ในที่เก็บในเครื่อง ช่วยให้ติดตามการเปลี่ยนแปลง ในทรัพยากร Dependency นี้

กราฟการอ้างอิงโมดูล

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

ส่วนขยายโมดูล

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

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

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

  1. transitiveDigest ข้อมูลสรุปเกี่ยวกับการใช้งานส่วนขยายและไฟล์ .bzl แบบผกผัน
  2. generatedRepoSpecs ผลลัพธ์ของการเรียกใช้ส่วนขยายนั้นด้วยอินพุตปัจจุบัน

ปัจจัยเพิ่มเติมที่อาจส่งผลต่อผลลัพธ์ของส่วนขยายคือการใช้งานของส่วนขยาย แม้ว่าจะไม่มีการจัดเก็บไว้ใน Lockfile แต่จะมีการพิจารณาการใช้งานเมื่อเปรียบเทียบสถานะปัจจุบันของส่วนขยายกับไฟล์ใน Lockfile

แนวทางปฏิบัติแนะนำ

ลองทําตามแนวทางปฏิบัติแนะนําต่อไปนี้เพื่อให้ได้รับประโยชน์สูงสุดจากฟีเจอร์ Lockfile

  • อัปเดต Lockfile เป็นประจำเพื่อแสดงการเปลี่ยนแปลงในทรัพยากร Dependency หรือการกำหนดค่าของโปรเจ็กต์ วิธีนี้ช่วยให้มั่นใจว่าบิลด์ต่อๆ มาจะอิงตามชุดทรัพยากร Dependency ที่เป็นปัจจุบันและถูกต้องที่สุด

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

  • ใช้ bazelisk เพื่อเรียกใช้ Bazel และใส่ไฟล์ .bazelversion ในการควบคุมเวอร์ชันที่ระบุเวอร์ชัน Bazel ที่ตรงกับไฟล์ล็อก เนื่องจากตัว Bazel เป็นทรัพยากร Dependency ของบิลด์ ไฟล์ Lockfile จึงมีไว้สำหรับเวอร์ชัน Bazel เท่านั้นและจะเปลี่ยนแปลงแม้กระทั่งระหว่างรุ่น Bazel ที่เข้ากันได้แบบย้อนหลัง การใช้ bazelisk จะช่วยให้มั่นใจว่านักพัฒนาซอฟต์แวร์ทั้งหมดใช้เวอร์ชัน Bazel ที่ตรงกับ Lockfile

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