बेज़ेल में लॉकफ़ाइल सुविधा की मदद से, किसी प्रोजेक्ट के लिए ज़रूरी सॉफ़्टवेयर लाइब्रेरी या पैकेज के खास वर्शन या डिपेंडेंसी की रिकॉर्डिंग की जा सकती है. यह ऐसा, मॉड्यूल रिज़ॉल्यूशन और एक्सटेंशन के आकलन के नतीजे को सेव करके करता है. लॉकफ़ाइल, फिर से बनाए जा सकने वाले बिल्ड को बढ़ावा देती है. इससे, डेवलपमेंट के माहौल में एक जैसा बने रहने की गारंटी मिलती है. साथ ही, यह प्रोजेक्ट की डिपेंडेंसी में हुए बदलावों से, रिज़ॉल्यूशन प्रोसेस के उन हिस्सों को स्किप करने की अनुमति देकर, बिल्ड की परफ़ॉर्मेंस को बेहतर बनाता है जिन पर इन बदलावों का कोई असर नहीं पड़ता. इसके अलावा, लॉकफ़ाइल, बाहरी लाइब्रेरी में अचानक होने वाले अपडेट या बदलावों को रोककर, ऐप्लिकेशन को क्रैश या फ़्रीज़ होने से बचाती है. इससे, बग होने का जोखिम भी कम हो जाता है.
लॉकफ़ाइल जनरेट करना
Lockfile को फ़ाइल फ़ोल्डर के रूट में, MODULE.bazel.lock
नाम से जनरेट किया जाता है. इसे बिल्ड करने की प्रोसेस के दौरान बनाया या अपडेट किया जाता है. खास तौर पर, मॉड्यूल रिज़ॉल्यूशन और एक्सटेंशन के आकलन के बाद. अहम बात यह है कि इसमें सिर्फ़ वे डिपेंडेंसी शामिल होती हैं जो बिल्ड के मौजूदा अनुरोध में शामिल होती हैं.
जब प्रोजेक्ट में ऐसे बदलाव होते हैं जिनका असर उसकी डिपेंडेंसी पर पड़ता है, तो नई स्थिति दिखाने के लिए लॉकफ़ाइल अपने-आप अपडेट हो जाती है. इससे यह पक्का होता है कि लॉकफ़ाइल, मौजूदा बिल्ड के लिए ज़रूरी डिपेंडेंसी के खास सेट पर फ़ोकस करती है. इससे प्रोजेक्ट में रिज़ॉल्व की गई डिपेंडेंसी की सटीक जानकारी मिलती है.
Lockfile का इस्तेमाल
जब प्रोजेक्ट की स्थिति, लॉकफ़ाइल से अलग हो, तो Bazel के व्यवहार को पसंद के मुताबिक बनाने के लिए, लॉकफ़ाइल को फ़्लैग --lockfile_mode
से कंट्रोल किया जा सकता है. ये मोड उपलब्ध हैं:
update
(डिफ़ॉल्ट): लॉकफ़ाइल में मौजूद जानकारी का इस्तेमाल करके, पहले से मौजूद रजिस्ट्री फ़ाइलों को डाउनलोड करने से रोकें. साथ ही, उन एक्सटेंशन का फिर से आकलन करने से बचें जिनके नतीजे अब भी अप-टू-डेट हैं. अगर कोई जानकारी मौजूद नहीं है, तो उसे लॉकफ़ाइल में जोड़ दिया जाएगा. इस मोड में, Bazel उन डिपेंडेंसी के लिए बदली जा सकने वाली जानकारी को रीफ़्रेश करने से भी बचता है जिनमें कोई बदलाव नहीं हुआ है. जैसे, हटाए गए वर्शन.refresh
:update
की तरह, लेकिन इस मोड पर स्विच करते समय बदलाव की जा सकने वाली जानकारी हमेशा रीफ़्रेश की जाती है. साथ ही, इस मोड में होने पर करीब हर एक घंटे में बदली जा सकने वाली जानकारी रीफ़्रेश हो जाती है.error
:update
की तरह ही, लेकिन अगर कोई जानकारी मौजूद नहीं है या वह पुरानी है, तो Bazel गड़बड़ी के साथ काम नहीं करेगा. यह मोड, लॉकफ़ाइल में कभी बदलाव नहीं करता या रिज़ॉल्यूशन के दौरान नेटवर्क अनुरोध नहीं करता.reproducible
के तौर पर मार्क किए गए मॉड्यूल एक्सटेंशन, अब भी नेटवर्क अनुरोध कर सकते हैं. हालांकि, उनसे हमेशा एक ही नतीजा मिलने की उम्मीद की जाती है.off
: लॉकफ़ाइल की जांच नहीं की जाती और न ही उसे अपडेट किया जाता है.
लॉकफ़ाइल के फ़ायदे
लॉकफ़ाइल के कई फ़ायदे हैं और इसका इस्तेमाल कई तरीकों से किया जा सकता है:
फिर से बनाए जा सकने वाले बिल्ड. सॉफ़्टवेयर लाइब्रेरी के खास वर्शन या डिपेंडेंसी कैप्चर करके, लॉकफ़ाइल यह पक्का करती है कि अलग-अलग एनवायरमेंट में और समय के साथ, बिल्ड फिर से बनाए जा सकें. डेवलपर अपने प्रोजेक्ट बनाते समय, एक जैसे और अनुमानित नतीजों पर भरोसा कर सकते हैं.
तेज़ी से बढ़ने वाले रिज़ॉल्यूशन. लॉकफ़ाइल, Basel को उन रजिस्ट्री फ़ाइलों को डाउनलोड करने से रोकती है जिन्हें पिछले बिल्ड में इस्तेमाल किया जा चुका है. इससे बिल्ड की परफ़ॉर्मेंस काफ़ी बेहतर होती है. खास तौर पर, उन मामलों में जहां समस्या हल करने में ज़्यादा समय लग सकता है.
स्टैबिलिटी और जोखिम को कम करना. लॉकफ़ाइल, अचानक होने वाले अपडेट या बाहरी लाइब्रेरी में बदलावों को रोककर, ऐप्लिकेशन को स्थिर रखने में मदद करती है. डिपेंडेंसी को चुनिंदा वर्शन पर लॉक करने से, काम न करने वाले या टेस्ट नहीं हुए अपडेट की वजह से बग आने का जोखिम कम हो जाता है.
लॉकफ़ाइल का कॉन्टेंट
लॉकफ़ाइल में वह सारी ज़रूरी जानकारी होती है जिससे यह पता चलता है कि प्रोजेक्ट की स्थिति में बदलाव हुआ है या नहीं. इसमें मौजूदा स्थिति में प्रोजेक्ट को बिल्ड करने का नतीजा भी शामिल होता है. लॉकफ़ाइल में दो मुख्य हिस्से होते हैं:
- मॉड्यूल रिज़ॉल्यूशन के इनपुट के तौर पर इस्तेमाल होने वाली सभी रिमोट फ़ाइलों के हैश.
- हर मॉड्यूल एक्सटेंशन के लिए, लॉकफ़ाइल में ऐसे इनपुट शामिल होते हैं जो उस पर असर डालते हैं. इन्हें
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, लॉकफ़ाइल के हैश का इस्तेमाल करके, रिपॉज़िटरी कैश में मौजूद रजिस्ट्री फ़ाइलों को डाउनलोड करने से पहले उन्हें खोजता है. इससे, बाद में होने वाले रिज़ॉल्यूशन की प्रोसेस तेज़ हो जाती है.
हटाए गए चुनिंदा वर्शन
selectedYankedVersions
सेक्शन में, मॉड्यूल के उन वर्शन होते हैं जिन्हें मॉड्यूल रिज़ॉल्यूशन के हिसाब से चुना गया था. इससे आम तौर पर, बिल्ड बनाने की कोशिश करते समय गड़बड़ी हो जाती है. इसलिए, यह सेक्शन सिर्फ़ तब खाली होता है, जब जैंक किए गए वर्शन को --allow_yanked_versions
या BZLMOD_ALLOW_YANKED_VERSIONS
के ज़रिए साफ़ तौर पर अनुमति दी जाती है.
इस फ़ील्ड की ज़रूरत इसलिए है, क्योंकि मॉड्यूल फ़ाइलों की तुलना में, हटाए गए वर्शन की जानकारी में बदलाव किया जा सकता है. इसलिए, हैश का इस्तेमाल करके इसका रेफ़रंस नहीं दिया जा सकता. इस जानकारी को bazel mod deps --lockfile_mode=refresh
की मदद से अपडेट किया जा सकता है.
मॉड्यूल एक्सटेंशन
moduleExtensions
सेक्शन एक ऐसा मैप है जिसमें सिर्फ़ वे एक्सटेंशन शामिल होते हैं जिनका इस्तेमाल, मौजूदा या पहले किए गए अनुरोध में किया गया है. इसमें ऐसे एक्सटेंशन शामिल नहीं होते जिनका अब इस्तेमाल नहीं किया जा रहा है. दूसरे शब्दों में, अगर किसी एक्सटेंशन का इस्तेमाल अब डिपेंडेंसी ग्राफ़ में नहीं किया जा रहा है, तो उसे moduleExtensions
मैप से हटा दिया जाता है.
अगर कोई एक्सटेंशन, ऑपरेटिंग सिस्टम या आर्किटेक्चर टाइप पर निर्भर नहीं है, तो इस सेक्शन में सिर्फ़ एक "सामान्य" एंट्री होती है. ऐसा न होने पर, कई एंट्री शामिल की जाती हैं. इन एंट्री को ओएस, आर्किटेक्चर या दोनों के नाम पर रखा जाता है. हर एंट्री, उन खास बातों के आधार पर एक्सटेंशन के आकलन के नतीजे से जुड़ी होती है.
एक्सटेंशन मैप में मौजूद हर एंट्री, इस्तेमाल किए गए एक्सटेंशन से जुड़ी होती है. साथ ही, इसकी पहचान, उसमें मौजूद फ़ाइल और नाम से की जाती है. हर एंट्री की वैल्यू में, उस एक्सटेंशन से जुड़ी ज़रूरी जानकारी होती है:
bzlTransitiveDigest
, एक्सटेंशन लागू करने के डाइजेस्ट और उससे ट्रांज़िशन के तौर पर लोड की गई .bzl फ़ाइलों का डाइजेस्ट होता है.usagesDigest
, डिपेंडेंसी ग्राफ़ में एक्सटेंशन के इस्तेमाल का डाइजेस्ट होता है. इसमें सभी टैग शामिल होते हैं.- इसके अलावा, ऐसे फ़ील्ड जो एक्सटेंशन के लिए इस्तेमाल किए जाने वाले दूसरे इनपुट को ट्रैक करते हैं. जैसे, उन फ़ाइलों या डायरेक्ट्री का कॉन्टेंट जिन्हें वह पढ़ता है या एनवायरमेंट वैरिएबल का इस्तेमाल करता है.
generatedRepoSpecs
, मौजूदा इनपुट की मदद से एक्सटेंशन से बनाई गई रिपॉज़िटरी को एन्कोड करता है.- ज़रूरी नहीं
moduleExtensionMetadata
फ़ील्ड में, एक्सटेंशन से मिला मेटाडेटा होता है. जैसे, क्या इसके बनाए गए कुछ डेटा स्टोर को रूट मॉड्यूल केuse_repo
से इंपोर्ट किया जाना चाहिए. इस जानकारी की मदद से,bazel mod tidy
कमांड काम करता है.
मॉड्यूल एक्सटेंशन, वापस आने वाले मेटाडेटा को reproducible = True
की मदद से सेट करके, lockfile में शामिल किए जाने से ऑप्ट आउट कर सकते हैं. ऐसा करने से, वे यह वादा करते हैं कि एक जैसे इनपुट मिलने पर, वे हमेशा एक जैसे डेटा स्टोर बनाए रखेंगे.
सबसे सही तरीके
लॉकफ़ाइल की सुविधा का ज़्यादा से ज़्यादा फ़ायदा पाने के लिए, यहां दिए गए सबसे सही तरीकों को अपनाएं:
प्रोजेक्ट की डिपेंडेंसी या कॉन्फ़िगरेशन में हुए बदलावों को दिखाने के लिए, लॉकफ़ाइल को नियमित तौर पर अपडेट करें. इससे यह पक्का होता है कि बाद के बिल्ड, डिपेंडेंसी के सबसे अप-टू-डेट और सटीक सेट पर आधारित हैं. सभी एक्सटेंशन को एक साथ लॉक करने के लिए,
bazel mod deps --lockfile_mode=update
चलाएं.साथ मिलकर काम करने की सुविधा देने के लिए, वर्शन कंट्रोल में लॉकफ़ाइल शामिल करें. साथ ही, पक्का करें कि टीम के सभी सदस्यों के पास एक ही लॉकफ़ाइल का ऐक्सेस हो. इससे प्रोजेक्ट में एक जैसा डेवलपमेंट एनवायरमेंट बनता है.
Bazel को चलाने के लिए,
bazelisk
का इस्तेमाल करें. साथ ही, वर्शन कंट्रोल में.bazelversion
फ़ाइल शामिल करें. इससे, लॉकफ़ाइल से जुड़े Bazel वर्शन के बारे में पता चलता है. Baज़ल, आपके बिल्ड पर निर्भर करता है. इसलिए, Lockfile खास तौर पर Basel के वर्शन के हिसाब से होता है. साथ ही, वह पुराने सिस्टम के साथ काम करने वाले बैज की रिलीज़ के बीच में भी बदल सकता है.bazelisk
का इस्तेमाल करने से यह पक्का होता है कि सभी डेवलपर, लॉकफ़ाइल से मैच करने वाले Bazel वर्शन का इस्तेमाल कर रहे हैं.
इन सबसे सही तरीकों का पालन करके, Bazel में लॉकफ़ाइल की सुविधा का बेहतर तरीके से इस्तेमाल किया जा सकता है. इससे, सॉफ़्टवेयर डेवलपमेंट वर्कफ़्लो ज़्यादा असरदार, भरोसेमंद, और साथ मिलकर काम करने वाले बनते हैं.