आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम

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

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

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

फ़ंक्शन के नज़रिए से

आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम और फ़ंक्शनल प्रोग्रामिंग के बीच अंतर बनाना आसान है. पारंपरिक इंपीरिटिव प्रोग्रामिंग लैंग्वेज (जैसे कि Java, C, और Python) एक के बाद एक लागू करने के लिए स्टेटमेंट की सूचियां तय करती हैं, उसी तरह से टास्क-आधारित बिल्ड सिस्टम प्रोग्राम करने वाले प्रोग्रामर को चरणों की एक सीरीज़ तय करने देते हैं. इसके ठीक उलट, फ़ंक्शनल प्रोग्रामिंग लैंग्वेज (जैसे कि Haskell और ML) को गणितीय समीकरणों की सीरीज़ के जैसा बनाया गया है. फ़ंक्शनल लैंग्वेज में, प्रोग्रामर कंप्यूटेशन पूरा करने के लिए कंप्यूटिंग के बारे में बताता है, लेकिन कंपाइलर को कंप्यूट किए जाने के समय और तरीके की जानकारी देता है.

यह आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम में मेनिफ़ेस्ट का एलान करने और सिस्टम को बिल्ड को लागू करने का तरीका बताने के लिए, इसे मैप करता है. फ़ंक्शनल प्रोग्रामिंग का इस्तेमाल करके, कई समस्याओं को आसानी से ज़ाहिर नहीं किया जा सकता है. हालांकि, जिन समस्याओं का सबसे ज़्यादा फ़ायदा होता है उनसे जुड़ी भाषा, अक्सर इन प्रोग्राम को एक साथ लाती है. साथ ही, वे इस बात की गारंटी देते हैं कि उनकी दी गई जानकारी सही नहीं होगी. फ़ंक्शनल प्रोग्रामिंग का इस्तेमाल करके, आसानी से बताई जाने वाली समस्याओं का हल निकाला जाता है. इनमें, कुछ नियमों या फ़ंक्शन का इस्तेमाल करके, डेटा के एक हिस्से को दूसरे में बदलना होता है. बिल्ड सिस्टम यही काम करता है: पूरा सिस्टम एक गणित का फ़ंक्शन है. इसमें सोर्स फ़ाइलें और कंपाइलर जैसे टूल, इनपुट के तौर पर बाइनरी प्रोसेस करते हैं. इसमें कोई हैरानी की बात नहीं है कि फ़ंक्शनल प्रोग्रामिंग के नियमों के आधार पर ही बिल्ड सिस्टम बनाया जाता है.

आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम को समझना

Google का बिल्ड सिस्टम, Blaze, पहला आर्टफ़ैक्ट-आधारित बिल्ड सिस्टम था. Bazel, Blaze का एक ओपन सोर्स वर्शन है.

यहां Bazel में बिल्डफ़ाइल (आम तौर पर, जिसका नाम BUILD है) कुछ इस तरह दिखती है:

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 फ़ाइलें टारगेट तय करती हैं—java_binary और java_library, दो तरह के टारगेट हैं. हर टारगेट एक आर्टफ़ैक्ट के मुताबिक होता है: हर टारगेट में ये शामिल हैं:

  • name: टारगेट लाइन का रेफ़रंस, कमांड लाइन और दूसरे टारगेट के बारे में कैसे दिया जाता है
  • srcs: टारगेट के लिए आर्टफ़ैक्ट बनाने के लिए, इकट्ठा की जाने वाली सोर्स फ़ाइलें
  • deps: इस टारगेट से पहले बनाए जाने वाले और इसमें लिंक किए गए अन्य टारगेट

डिपेंडेंसी एक ही पैकेज में हो सकती है (जैसे कि :mylib पर निर्भरता) या उसी सोर्स हैरारकी में किसी दूसरे पैकेज पर (जैसे कि //java/com/example/common पर mylib की डिपेंडेंसी).

बिल्ड-आधारित बिल्ड सिस्टम की तरह ही, आप Bazel के कमांड-लाइन टूल का इस्तेमाल करके भी बिल्ड परफ़ॉर्म करते हैं. MyBinary टारगेट बनाने के लिए, आप bazel build :MyBinary चलाते हैं. किसी साफ़ डेटा संग्रह स्थान में पहली बार वह कमांड डालने के बाद, Bazel:

  1. फ़ाइल फ़ोल्डर में मौजूद डिपेंडेंसी का ग्राफ़ बनाने के लिए, फ़ाइल फ़ोल्डर में BUILD फ़ाइल को पार्स करता है.
  2. ग्राफ़ का इस्तेमाल, MyBinary की ट्रांज़िटल डिपेंडेंसी तय करने के लिए किया जाता है. इसका मतलब है कि हर टारगेट, MyBinary पर निर्भर करता है. साथ ही, यह टारगेट उन टारगेट पर निर्भर करता है जिन पर ये बार-बार निर्भर करते हैं.
  3. उन सभी डिपेंडेंसी को क्रम में बनाता है. बैजल हर उस टारगेट को बनाने से शुरू होता है, जिस पर कोई अन्य डिपेंडेंसी नहीं होती. साथ ही, यह नज़र रखता है कि किस टारगेट के लिए कौनसी डिपेंडेंसी बनाई जानी चाहिए. जैसे ही किसी टारगेट की सभी डिपेंडेंसी तैयार होती हैं, Bazel उस टारगेट को बनाना शुरू कर देता है. यह प्रोसेस तब तक जारी रहती है, जब तक MyBinary की हर ट्रांज़िशनल डिपेंडेंसी बन नहीं जाती है.
  4. MyBinary बनाता है और एक्ज़ीक्यूटेबल ऐसी बाइनरी फ़ाइल बनाता है जो तीसरे चरण में बनाई गई सभी डिपेंडेंसी को लिंक करती है.

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

हालांकि, साथ मिलकर काम करने के फ़ायदे भी दूसरे तरीकों से भी मिलते हैं. अगली बार जब डेवलपर कोई बदलाव किए बिना bazel build :MyBinary दूसरी बार टाइप करता है, तो हमें यह साफ़ तौर पर पता चल जाता है. हालांकि, बेज़ल सेकंड से कम समय में बाहर निकल जाता है. इस मैसेज में लिखा होता है कि टारगेट अप-टू-डेट है. फ़ंक्शनल प्रोग्रामिंग मॉडल की वजह से ऐसा हो सकता है. शुरुआत में हमने बातल की बात की. बज़ल जानते हैं कि हर टारगेट सिर्फ़ Java कंपाइलर चलाने का नतीजा होता है और यह जानते हैं कि Java कंपाइलर से मिला आउटपुट सिर्फ़ इसके इनपुट पर निर्भर करता है. इसलिए, इनपुट में कोई बदलाव न होने पर आउटपुट को फिर से इस्तेमाल किया जा सकता है. यह विश्लेषण हर लेवल पर काम करता है. अगर MyBinary.java बदलता है, तो बेज़ल को MyBinary को फिर से बनाने के बारे में पता होगा, लेकिन वह mylib का फिर से इस्तेमाल करेगा. अगर //java/com/example/common के लिए सोर्स फ़ाइल में बदलाव होता है, तो बेज़ल को उस लाइब्रेरी, mylib, और MyBinary को फिर से बनाना होगा. हालांकि, वे //java/com/example/myproduct/otherlib का फिर से इस्तेमाल करेंगे. हालांकि, बेज़ल को हर कदम पर चलने वाले टूल की विशेषताओं के बारे में पता है. इसलिए, वे हर बार आर्टफ़ैक्ट के कम से कम सेट को फिर से बना सकती हैं. हालांकि, यह गारंटी देती है कि पुराने सिस्टम के लिए कोई टूल नहीं बनाया जाएगा.

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

अन्य उपयोगी बेज़ल तरकीबें

आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम बुनियादी तौर पर, साथ-साथ काम करने वाली समस्याओं को हल करते हैं और काम पर आधारित बिल्ड सिस्टम में होते हैं. हालांकि, अब भी कुछ ऐसी समस्याएं हैं जिन्हें पहले ठीक नहीं किया गया है. बैज़ल के पास ऐसी समस्याओं को हल करने का तरीका है. इसलिए, आगे बढ़ने से पहले, हमें इन पर चर्चा करनी चाहिए.

डिपेंडेंसी के तौर पर काम करने वाले टूल

पहले हम एक समस्या का सामना कर रहे थे कि बिल्ड हमारी मशीन पर इंस्टॉल किए गए टूल पर निर्भर थे और टूल के अलग-अलग वर्शन या जगहों की वजह से बिल्ड को सिस्टम में फिर से बनाना मुश्किल हो सकता था. यह समस्या तब और भी मुश्किल हो जाती है, जब आपके प्रोजेक्ट में ऐसी भाषाओं का इस्तेमाल होता है जिनके लिए अलग-अलग टूल बनाने होते हैं, जैसे कि Windows बनाम Linux. साथ ही, इनमें से हर प्लैटफ़ॉर्म को एक ही तरह के काम करने के लिए, अलग-अलग तरह के टूल की ज़रूरत होती है.

बेज़ल टूल इस समस्या के पहले हिस्से को हल करते हैं. इसके लिए, टूल हर डिपेंडेंसी को डिपेंडेंसी के तौर पर इस्तेमाल करते हैं. फ़ाइल फ़ोल्डर का हर java_library इंप्लिसिट तरीके से Java कंपाइलर पर निर्भर करता है. यह एक मशहूर कंपाइलर को डिफ़ॉल्ट तौर पर सेट करता है. जब भी बेज़ल java_library बनाता है, तो यह पक्का करता है कि बताया गया कंपाइलर किसी मशहूर जगह पर उपलब्ध हो. किसी भी अन्य डिपेंडेंसी की तरह, अगर Java कंपाइलर बदलता है, तो उस पर निर्भर हर आर्टफ़ैक्ट फिर से बनता है.

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

  • होस्ट कॉन्फ़िगरेशन: बिल्ड के दौरान चलने वाले टूल बनाना
  • टारगेट कॉन्फ़िगरेशन: वह बाइनरी बनाना जिसके लिए आपने अनुरोध किया था

बिल्ड सिस्टम को बढ़ाना

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

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

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

पर्यावरण को सुरक्षित रखना

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

एक्सटर्नल डिपेंडेंसी तय करना

हालांकि, अब भी एक समस्या बाकी है: बिल्ड सिस्टम को सीधे तौर पर बनाने के बजाय, डिपेंडेंसी डाउनलोड करना ज़रूरी होता है. भले ही, वे बाहरी टूल हों या उनके टूल. इस उदाहरण में, @com_google_common_guava_guava//jar डिपेंडेंसी को देखा जा सकता है, जो Maven से JAR फ़ाइल डाउनलोड करता है.

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

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

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

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

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