Bazel लॉकफ़ाइल

समस्या की शिकायत करें सोर्स देखें

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

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

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

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

Lockfile का इस्तेमाल

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

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

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

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

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

  • तेज़ी से सेट किए गए समाधान. लॉकफ़ाइल, Basel को उन रजिस्ट्री फ़ाइलों को डाउनलोड करने से रोकती है जिन्हें पिछले बिल्ड में इस्तेमाल किया जा चुका है. इससे बिल्ड की परफ़ॉर्मेंस काफ़ी बेहतर होती है. खास तौर पर, उन स्थितियों में जब समस्या हल करने में ज़्यादा समय लगता है.

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

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

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

  1. सभी रिमोट फ़ाइलों के हैश, जो मॉड्यूल रिज़ॉल्यूशन के इनपुट हैं.
  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 सेक्शन में, मॉड्यूल रिज़ॉल्यूशन के दौरान ऐक्सेस की गई रिमोट रजिस्ट्री की सभी फ़ाइलों के हैश शामिल होते हैं. एक जैसे इनपुट और सभी रिमोट इनपुट हैश किए जाने पर, रिज़ॉल्यूशन एल्गोरिदम पूरी तरह से तय होता है. इससे, पूरी तरह से दोबारा जनरेट हो सकने वाले रिज़ॉल्यूशन के नतीजे को पक्का किया जा सकता है. साथ ही, Lockfile में रिमोट जानकारी को बार-बार दिखाने से बचा जा सकता है. ध्यान दें कि इसके लिए किसी खास रजिस्ट्री में कोई मॉड्यूल होने पर भी रिकॉर्डिंग की ज़रूरत होती है, लेकिन कम प्राथमिकता वाली रजिस्ट्री में ऐसा होता है (उदाहरण में, "नहीं मिला" एंट्री देखें). इस बदलाव की सुविधा वाली जानकारी को bazel mod deps --lockfile_mode=refresh की मदद से अपडेट किया जा सकता है.

Basel, रजिस्ट्री फ़ाइलों को डाउनलोड करने से पहले और उन्हें रिपॉज़िटरी की कैश मेमोरी में सेव करने के लिए, lockfile से हैश का इस्तेमाल करता है. इससे, बाद के रिज़ॉल्यूशन तेज़ी से बढ़ जाते हैं.

यान वाले वर्शन के चुने गए वर्शन

selectedYankedVersions सेक्शन में, मॉड्यूल के रिज़ॉल्यूशन के हिसाब से चुने गए मॉड्यूल के जैंक किए गए वर्शन शामिल होते हैं. इससे आम तौर पर, बिल्ड बनाने की कोशिश करते समय गड़बड़ी हो जाती है. इसलिए, यह सेक्शन सिर्फ़ तब खाली होता है, जब जैंक किए गए वर्शन को --allow_yanked_versions या BZLMOD_ALLOW_YANKED_VERSIONS के ज़रिए साफ़ तौर पर अनुमति दी जाती है.

इस फ़ील्ड की ज़रूरत इसलिए है, क्योंकि मॉड्यूल फ़ाइलों की तुलना में, येंक किए गए वर्शन की जानकारी पहले से ही बदली जा सकती है. इसलिए, हैश के ज़रिए इसका रेफ़रंस नहीं दिया जा सकता. यह जानकारी bazel mod deps --lockfile_mode=refresh की मदद से अपडेट की जा सकती है.

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

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

अगर कोई एक्सटेंशन ऑपरेटिंग सिस्टम या आर्किटेक्चर टाइप से अलग है, तो इस सेक्शन में सिर्फ़ एक "सामान्य" एंट्री दिखती है. अगर ऐसा नहीं है, तो ओएस, आर्किटेक्चर या दोनों के नाम पर कई एंट्री शामिल की जाती हैं. हर एंट्री को उन खास जानकारी पर एक्सटेंशन के आकलन के नतीजे के हिसाब से बनाया जाता है.

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

  1. bzlTransitiveDigest, एक्सटेंशन लागू करने का ब्यौरा होता है. साथ ही, इससे ट्रांज़िट में लोड की गई .bzl फ़ाइलों का भी पता चलता है.
  2. usagesDigest, डिपेंडेंसी ग्राफ़ में एक्सटेंशन के इस्तेमाल का डाइजेस्ट होता है, जिसमें सभी टैग शामिल होते हैं.
  3. इसके अलावा, ऐसे फ़ील्ड जो एक्सटेंशन के लिए इस्तेमाल किए जाने वाले दूसरे इनपुट को ट्रैक करते हैं. जैसे, उन फ़ाइलों या डायरेक्ट्री का कॉन्टेंट जिन्हें वह पढ़ता है या एनवायरमेंट वैरिएबल का इस्तेमाल करता है.
  4. generatedRepoSpecs, एक्सटेंशन से बनाए गए डेटा स्टोर करने की जगहों को, मौजूदा इनपुट के साथ एन्कोड करता है.
  5. वैकल्पिक moduleExtensionMetadata फ़ील्ड में एक्सटेंशन से मिला मेटाडेटा होता है, जैसे कि क्या बनाए गए कुछ डेटा स्टोर करने की जगहों को रूट मॉड्यूल से use_repo के ज़रिए इंपोर्ट किया जाना चाहिए या नहीं. यह जानकारी, bazel mod tidy कमांड को कंट्रोल करती है.

मॉड्यूल एक्सटेंशन, वापस आने वाले मेटाडेटा को reproducible = True की मदद से सेट करके, lockfile में शामिल किए जाने से ऑप्ट आउट कर सकते हैं. ऐसा करके, वे वादा करते हैं कि एक जैसे इनपुट दिए जाने पर वे हमेशा एक ही डेटा स्टोर करने की जगह बनाएंगे.

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

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

  • प्रोजेक्ट डिपेंडेंसी या कॉन्फ़िगरेशन में होने वाले बदलावों को दिखाने के लिए, lockfile को नियमित तौर पर अपडेट करें. इससे यह पक्का होता है कि आने वाले बिल्ड, डिपेंडेंसी के सबसे अप-टू-डेट और सटीक सेट पर आधारित हैं. सभी एक्सटेंशन एक साथ लॉक करने के लिए, bazel mod deps --lockfile_mode=update चलाएं.

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

  • Basel को चलाने के लिए, bazelisk का इस्तेमाल करें और वर्शन कंट्रोल में एक ऐसी .bazelversion फ़ाइल शामिल करें जो Lockfile से जुड़े Basel वर्शन की जानकारी देती हो. Baज़ल, आपके बिल्ड पर निर्भर करता है. इसलिए, Lockfile खास तौर पर Basel के वर्शन के हिसाब से होता है. साथ ही, Lockfile पुराने सिस्टम के साथ काम करने वाले बैज की रिलीज़ के बीच में भी बदल सकती है. bazelisk का इस्तेमाल करने से यह पक्का हो जाता है कि सभी डेवलपर ऐप्लिकेशन का ऐसा वर्शन इस्तेमाल कर रहे हैं जो lockfile से मेल खाता है.

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