Bazel लॉकफ़ाइल

Bazel में लॉकफ़ाइल की सुविधा की मदद से, किसी प्रोजेक्ट के लिए ज़रूरी सॉफ़्टवेयर लाइब्रेरी या पैकेज के खास वर्शन या डिपेंडेंसी रिकॉर्ड की जा सकती हैं. यह सुविधा, मॉड्यूल रिज़ॉल्यूशन और एक्सटेंशन के आकलन के नतीजे को सेव करके काम करती है. लॉकफ़ाइल की मदद से, एक जैसे बिल्ड तैयार किए जा सकते हैं. इससे, डेवलपमेंट के एनवायरमेंट में एकरूपता बनी रहती है. इसके अलावा, लॉकफ़ाइल की मदद से, बिल्ड की क्षमता बढ़ती है. ऐसा इसलिए, क्योंकि प्रोजेक्ट की डिपेंडेंसी में कोई बदलाव न होने पर, Bazel रिज़ॉल्यूशन की प्रोसेस को छोड़ सकता है. साथ ही, लॉकफ़ाइल की मदद से, स्थिरता बेहतर होती है. ऐसा इसलिए, क्योंकि यह बाहरी लाइब्रेरी में अनचाहे अपडेट या बड़े बदलावों को रोकती है. इससे, गड़बड़ियां होने का खतरा कम हो जाता है.

लॉकफ़ाइल जनरेट करना

लॉकफ़ाइल, वर्कस्पेस के रूट में MODULE.bazel.lock नाम से जनरेट होती है. यह बिल्ड की प्रोसेस के दौरान बनाई या अपडेट की जाती है. खास तौर पर, मॉड्यूल रिज़ॉल्यूशन और एक्सटेंशन के आकलन के बाद. लॉकफ़ाइल में प्रोजेक्ट की मौजूदा स्थिति की जानकारी होती है. इसमें MODULE फ़ाइल, फ़्लैग, ओवरराइड, और काम की अन्य जानकारी शामिल होती है. अहम बात यह है कि इसमें सिर्फ़ वे डिपेंडेंसी शामिल होती हैं जो बिल्ड के मौजूदा इनवोकेशन में शामिल हैं.

प्रोजेक्ट में ऐसे बदलाव होने पर जो उसकी डिपेंडेंसी पर असर डालते हैं, लॉकफ़ाइल अपने-आप अपडेट हो जाती है, ताकि नई स्थिति दिख सके. इससे यह पक्का होता है कि लॉकफ़ाइल, मौजूदा बिल्ड के लिए ज़रूरी डिपेंडेंसी के खास सेट पर फ़ोकस रहे. साथ ही, प्रोजेक्ट की हल की गई डिपेंडेंसी की सटीक जानकारी मिलती रहे.

लॉकफ़ाइल का इस्तेमाल करना

लॉकफ़ाइल को फ़्लैग --lockfile_mode से कंट्रोल किया जा सकता है. इससे, प्रोजेक्ट की स्थिति लॉकफ़ाइल से अलग होने पर, Bazel के व्यवहार को पसंद के मुताबिक बनाया जा सकता है. ये मोड उपलब्ध हैं:

  • update (डिफ़ॉल्ट): अगर प्रोजेक्ट की स्थिति लॉकफ़ाइल से मेल खाती है, तो रिज़ॉल्यूशन का नतीजा तुरंत लॉकफ़ाइल से मिलता है. अगर ऐसा नहीं होता है, तो रिज़ॉल्यूशन की प्रोसेस पूरी की जाती है और लॉकफ़ाइल को मौजूदा स्थिति के हिसाब से अपडेट किया जाता है.
  • error: अगर प्रोजेक्ट की स्थिति लॉकफ़ाइल से मेल खाती है, तो रिज़ॉल्यूशन का नतीजा लॉकफ़ाइल से मिलता है. अगर ऐसा नहीं होता है, तो Bazel एक गड़बड़ी दिखाता है. इससे, प्रोजेक्ट और लॉकफ़ाइल के बीच के अंतर का पता चलता है. यह मोड खास तौर पर तब काम आता है, जब आपको यह पक्का करना हो कि आपके प्रोजेक्ट की डिपेंडेंसी में कोई बदलाव न हो और किसी भी अंतर को गड़बड़ी के तौर पर माना जाए.
  • off: लॉकफ़ाइल की जांच नहीं की जाती.

लॉकफ़ाइल के फ़ायदे

लॉकफ़ाइल के कई फ़ायदे हैं और इसका इस्तेमाल कई तरीकों से किया जा सकता है:

  • एक जैसे बिल्ड तैयार करना. सॉफ़्टवेयर लाइब्रेरी के खास वर्शन या डिपेंडेंसी को कैप्चर करके, लॉकफ़ाइल यह पक्का करती है कि अलग-अलग एनवायरमेंट और समय के साथ बिल्ड एक जैसे हों. डेवलपर, अपने प्रोजेक्ट को बनाते समय एक जैसे और अनुमान के मुताबिक नतीजे पा सकते हैं.

  • रिज़ॉल्यूशन की प्रोसेस को छोड़ना. लॉकफ़ाइल की मदद से, Bazel रिज़ॉल्यूशन की प्रोसेस को छोड़ सकता है. ऐसा तब होता है, जब पिछले बिल्ड के बाद से प्रोजेक्ट की डिपेंडेंसी में कोई बदलाव न हुआ हो. इससे, बिल्ड की क्षमता काफ़ी बेहतर होती है. खास तौर पर, उन स्थितियों में जहां रिज़ॉल्यूशन में ज़्यादा समय लग सकता है.

  • स्थिरता और जोखिम कम करना. लॉकफ़ाइल की मदद से, स्थिरता बनाए रखने में मदद मिलती है. ऐसा इसलिए, क्योंकि यह बाहरी लाइब्रेरी में अनचाहे अपडेट या बड़े बदलावों को रोकती है. डिपेंडेंसी को खास वर्शन पर लॉक करके, असंगत या बिना जांच किए गए अपडेट की वजह से गड़बड़ियां होने का खतरा कम हो जाता है.

लॉकफ़ाइल का कॉन्टेंट

लॉकफ़ाइल में, यह पता लगाने के लिए ज़रूरी सभी जानकारी होती है कि प्रोजेक्ट की स्थिति में बदलाव हुआ है या नहीं. इसमें, मौजूदा स्थिति में प्रोजेक्ट बनाने का नतीजा भी शामिल होता है. लॉकफ़ाइल के दो मुख्य हिस्से होते हैं:

  1. मॉड्यूल रिज़ॉल्यूशन के इनपुट, जैसे कि moduleFileHash, flags, और localOverrideHashes. साथ ही, रिज़ॉल्यूशन का आउटपुट, जो moduleDepGraph है.
  2. हर मॉड्यूल एक्सटेंशन के लिए, लॉकफ़ाइल में वे इनपुट शामिल होते हैं जो उस पर असर डालते हैं. इन्हें transitiveDigest से दिखाया जाता है. साथ ही, उस एक्सटेंशन को चलाने का आउटपुट, जिसे generatedRepoSpecs कहा जाता है

यहां एक उदाहरण दिया गया है. इसमें लॉकफ़ाइल का स्ट्रक्चर दिखाया गया है. साथ ही, हर सेक्शन के बारे में बताया गया है:

{
  "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",
          ...
        }
      }
    }
  }
}

मॉड्यूल फ़ाइल हैश

moduleFileHash, MODULE.bazel फ़ाइल के कॉन्टेंट का हैश दिखाता है. इस फ़ाइल में कोई भी बदलाव होने पर, हैश वैल्यू बदल जाती है.

फ़्लैग

Flags ऑब्जेक्ट में वे सभी फ़्लैग सेव होते हैं जो रिज़ॉल्यूशन के नतीजे पर असर डाल सकते हैं.

लोकल ओवरराइड हैश

अगर रूट मॉड्यूल में local_path_overrides शामिल हैं, तो इस सेक्शन में लोकल रिपॉज़िटरी में मौजूद MODULE.bazel फ़ाइल का हैश सेव होता है. इससे, इस डिपेंडेंसी में होने वाले बदलावों को ट्रैक किया जा सकता है.

मॉड्यूल डिपेंडेंसी ग्राफ़

moduleDepGraph, ऊपर बताए गए इनपुट का इस्तेमाल करके, रिज़ॉल्यूशन की प्रोसेस का नतीजा दिखाता है. इससे, प्रोजेक्ट को चलाने के लिए ज़रूरी सभी मॉड्यूल का डिपेंडेंसी ग्राफ़ बनता है.

मॉड्यूल एक्सटेंशन

moduleExtensions सेक्शन एक मैप है. इसमें सिर्फ़ वे एक्सटेंशन शामिल होते हैं जिनका इस्तेमाल मौजूदा इनवोकेशन में किया गया है या पहले किया गया था. इसमें, अब इस्तेमाल नहीं किए जा रहे एक्सटेंशन शामिल नहीं होते. दूसरे शब्दों में कहें, तो अगर किसी एक्सटेंशन का इस्तेमाल अब डिपेंडेंसी ग्राफ़ में नहीं किया जा रहा है, तो उसे moduleExtensions मैप से हटा दिया जाता है.

इस मैप में मौजूद हर एंट्री, इस्तेमाल किए गए एक्सटेंशन से जुड़ी होती है. इसकी पहचान, इसमें मौजूद फ़ाइल और नाम से होती है. हर एंट्री की वैल्यू में, उस एक्सटेंशन से जुड़ी काम की जानकारी होती है:

  1. transitiveDigest, एक्सटेंशन के लागू करने और उसकी ट्रांज़िटिव .bzl फ़ाइलों का डाइजेस्ट.
  2. generatedRepoSpecs, मौजूदा इनपुट के साथ उस एक्सटेंशन को चलाने का नतीजा.

एक्सटेंशन के नतीजों पर असर डालने वाला एक और फ़ैक्टर, उनका इस्तेमाल है. हालांकि, इस्तेमाल की जानकारी लॉकफ़ाइल में सेव नहीं होती, लेकिन एक्सटेंशन की मौजूदा स्थिति की तुलना लॉकफ़ाइल में मौजूद स्थिति से करते समय, इस्तेमाल की जानकारी को ध्यान में रखा जाता है.

सबसे सही तरीके

लॉकफ़ाइल की सुविधा के फ़ायदों को ज़्यादा से ज़्यादा पाने के लिए, यहां दिए गए सबसे सही तरीके अपनाएं:

  • प्रोजेक्ट की डिपेंडेंसी या कॉन्फ़िगरेशन में होने वाले बदलावों को दिखाने के लिए, लॉकफ़ाइल को समय-समय पर अपडेट करें. इससे यह पक्का होता है कि आने वाले बिल्ड, डिपेंडेंसी के सबसे अप-टू-डेट और सटीक सेट पर आधारित हों.

  • वर्शन कंट्रोल में लॉकफ़ाइल शामिल करें, ताकि साथ मिलकर काम किया जा सके. साथ ही, यह पक्का करें कि टीम के सभी सदस्यों के पास एक ही लॉकफ़ाइल का ऐक्सेस हो. इससे, प्रोजेक्ट में डेवलपमेंट के एनवायरमेंट में एकरूपता बनी रहती है.

इन सबसे सही तरीकों को अपनाकर, Bazel में लॉकफ़ाइल की सुविधा का असरदार तरीके से इस्तेमाल किया जा सकता है. इससे, सॉफ़्टवेयर डेवलपमेंट के वर्कफ़्लो ज़्यादा बेहतर, भरोसेमंद, और साथ मिलकर काम करने वाले बन सकते हैं.