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

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

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

फ़ंक्शनल नज़रिया

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

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

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

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

यहां बताया गया है कि 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 पर MyBinary की डिपेंडेंसी) या फिर एक ही सोर्स हैरारकी में किसी दूसरे पैकेज पर लागू हो सकती है (जैसे, //java/com/example/common पर mylib की डिपेंडेंसी).

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

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

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

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

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

बेज़ल की अन्य मज़ेदार तरकीबें

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

डिपेंडेंसी के तौर पर टूल

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

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

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

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

बिल्ड सिस्टम को बढ़ाया जा रहा है

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

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

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

पर्यावरण को अलग करना

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

बाहरी डिपेंडेंसी को सारणिक बनाना

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

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

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

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

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

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