Baज़ल के साथ हर दिन होने वाला इंटरैक्शन, मुख्य रूप से कुछ कमांड के ज़रिए होता है:
build
, test
, और run
. हालांकि, कभी-कभी ये सीमित लग सकते हैं: हो सकता है कि आपको किसी रिपॉज़िटरी में पैकेज पुश करने हों, असली उपयोगकर्ताओं के लिए दस्तावेज़ पब्लिश करने हों या Kubernetes की मदद से कोई ऐप्लिकेशन डिप्लॉय करना हो. हालांकि, Basel के पास publish
या
deploy
का निर्देश नहीं है – ये कार्रवाइयां कहां की जा सकती हैं?
बेज़ल रन कमांड
बेज़ल हरमैटिटी, रीप्रॉड्यूसिबिलिटी, और बढ़ोतरी पर ध्यान देने का मतलब है कि build
और test
निर्देश ऊपर दिए गए कामों के लिए मददगार नहीं हैं. ये कार्रवाइयां, सीमित नेटवर्क ऐक्सेस वाले सैंडबॉक्स में चल सकती हैं. साथ ही, यह गारंटी नहीं है कि हर bazel build
के साथ इन्हें फिर से चलाया जाएगा.
इसके बजाय, bazel run
का इस्तेमाल करें: उन टास्क के लिए मेहनत का घोड़ा, जिन्हें आपको ठीक करना है और जिनसे आपको परेशानी हो. Bazel के उपयोगकर्ता, ऐसे नियमों का इस्तेमाल करते हैं जिनसे प्रोग्राम चलाने लायक फ़ाइलें बनती हैं. साथ ही, नियम बनाने वाले लोग, "कस्टम वर्ब" तक इसे बढ़ाने के लिए, पैटर्न के एक सामान्य सेट का पालन कर सकते हैं.
नियमों के बारे में जानकारी: rules_k8s
उदाहरण के लिए, rules_k8s
,
Bazel के लिए Kubernetes के नियम. मान लें कि आपके पास यह टारगेट है:
# BUILD file in //application/k8s
k8s_object(
name = "staging",
kind = "deployment",
cluster = "testing",
template = "deployment.yaml",
)
staging
टारगेट पर bazel build
का इस्तेमाल करने पर, k8s_object
नियम एक स्टैंडर्ड Kubernetes YAML फ़ाइल बनाता है. हालांकि, अन्य टारगेट भी k8s_object
मैक्रो की मदद से बनाए जाते हैं. इन मैक्रो के नाम staging.apply
और :staging.delete
जैसे होते हैं. ये कार्रवाइयां करने के लिए स्क्रिप्ट बनाई जाती हैं. bazel run
staging.apply
के साथ इस्तेमाल करने पर, ये स्क्रिप्ट हमारे bazel k8s-apply
या bazel
k8s-delete
निर्देशों की तरह काम करती हैं.
दूसरा उदाहरण: ts_api_guardian_test
इस पैटर्न को Angular प्रोजेक्ट में भी देखा जा सकता है. ts_api_guardian_test
मैक्रो दो टारगेट बनाता है. पहला, एक स्टैंडर्ड nodejs_test
टारगेट है, जो जनरेट किए गए कुछ आउटपुट की तुलना "गोल्डन" फ़ाइल से करता है. इसका मतलब है कि वह फ़ाइल जिसमें उम्मीद के मुताबिक आउटपुट होता है. इसे सामान्य bazel
test
कॉल के साथ बनाया और चलाया जा सकता है. angular-cli
में, bazel test //etc/api:angular_devkit_core_api
के साथ ऐसा एक टारगेट चलाया जा सकता है.
समय के साथ, सही वजहों से इस गोल्डन फ़ाइल को अपडेट करना पड़ सकता है.
इसे मैन्युअल तरीके से अपडेट करना मुश्किल और गड़बड़ी भरा होता है. इसलिए, यह मैक्रो एक nodejs_binary
टारगेट भी उपलब्ध कराता है, जो गोल्डन फ़ाइल की तुलना करने के बजाय उसे अपडेट करता है. एक ही टेस्ट स्क्रिप्ट को "पुष्टि करें" या "स्वीकार करें" मोड में चलाने के लिए लिखा जा सकता है. यह इस बात पर निर्भर करता है कि इसे कैसे शुरू किया गया है. यह उसी पैटर्न का पालन करता है जिसे आपने पहले ही सीख लिया है: इसमें कोई नेटिव bazel test-accept
कमांड नहीं है, लेकिन bazel run //etc/api:angular_devkit_core_api.accept
का इस्तेमाल करके वही असर पाया जा सकता है.
यह पैटर्न काफ़ी असरदार हो सकता है. इसे पहचानना सीखने के बाद यह काफ़ी आम हो जाता है.
अपने नियम खुद बनाना
इस पैटर्न में मैक्रो सबसे अहम होते हैं. मैक्रो का इस्तेमाल नियमों की तरह किया जाता है. हालांकि, ये कई टारगेट बना सकते हैं. आम तौर पर, वे बताए गए नाम के साथ एक टारगेट बनाएंगे, जो मुख्य बिल्ड ऐक्शन करता है: हो सकता है कि यह एक सामान्य बाइनरी, Docker इमेज या सोर्स कोड का संग्रह बनाता हो. इस पैटर्न में, मुख्य टारगेट के आउटपुट के आधार पर, स्क्रिप्ट पर खराब असर डालने वाली स्क्रिप्ट बनाने के लिए अतिरिक्त टारगेट बनाए जाते हैं. जैसे, बनने वाली बाइनरी को पब्लिश करना या टेस्ट आउटपुट को अपडेट करना.
इस बारे में बताने के लिए, एक ऐसा काल्पनिक नियम बनाएं जो Sphinx की मदद से वेबसाइट जनरेट करता हो. साथ ही, एक और टारगेट बनाने के लिए मैक्रो का इस्तेमाल करें. इससे उपयोगकर्ता, वेबसाइट तैयार होने पर उसे पब्लिश कर सकता है. Sprint की मदद से वेबसाइट जनरेट करने के लिए, इस मौजूदा नियम पर गौर करें:
_sphinx_site = rule(
implementation = _sphinx_impl,
attrs = {"srcs": attr.label_list(allow_files = [".rst"])},
)
इसके बाद, इस तरह के नियम पर विचार करें, जो एक स्क्रिप्ट बनाता है. इसे चलाने पर, जनरेट किए गए पेज पब्लिश हो जाते हैं:
_sphinx_publisher = rule(
implementation = _publish_impl,
attrs = {
"site": attr.label(),
"_publisher": attr.label(
default = "//internal/sphinx:publisher",
executable = True,
),
},
executable = True,
)
आखिर में, ऊपर दिए गए दोनों नियमों के लिए एक साथ टारगेट बनाने के लिए, यह मैक्रो तय करें:
def sphinx_site(name, srcs = [], **kwargs):
# This creates the primary target, producing the Sphinx-generated HTML.
_sphinx_site(name = name, srcs = srcs, **kwargs)
# This creates the secondary target, which produces a script for publishing
# the site generated above.
_sphinx_publisher(name = "%s.publish" % name, site = name, **kwargs)
BUILD
फ़ाइलों में, मैक्रो का इस्तेमाल इस तरह करें कि वह सिर्फ़ मुख्य टारगेट बनाता है:
sphinx_site(
name = "docs",
srcs = ["index.md", "providers.md"],
)
इस उदाहरण में, एक "दस्तावेज़" टारगेट बनाया गया है, जैसे कि मैक्रो एक स्टैंडर्ड, सिंगल बेज़ल नियम था. नियम बनाने पर, वह कुछ कॉन्फ़िगरेशन जनरेट करता है और एचटीएमएल साइट बनाने के लिए Sphinx को चलाता है. यह साइट, मैन्युअल जांच के लिए तैयार होती है. हालांकि, एक और "docs.publish" टारगेट भी बनाया जाता है, जो साइट को पब्लिश करने के लिए स्क्रिप्ट बनाता है. प्राइमरी टारगेट का आउटपुट देखने के बाद, bazel run :docs.publish
का इस्तेमाल करके इसे सार्वजनिक तौर पर पब्लिश किया जा सकता है. यह ठीक वैसा ही है जैसे किसी काल्पनिक bazel publish
कमांड का इस्तेमाल करना.
यह तुरंत पता नहीं चल पा रहा है कि _sphinx_publisher
नियम को लागू करने का क्या तरीका हो सकता है. अक्सर, इस तरह की कार्रवाइयां, लॉन्चर शेल स्क्रिप्ट लिखती हैं.
आम तौर पर, इस तरीके में एक बहुत आसान शेल स्क्रिप्ट लिखने के लिए ctx.actions.expand_template
का इस्तेमाल किया जाता है. इस मामले में, पब्लिशर बाइनरी को प्राइमरी टारगेट के आउटपुट के पाथ के साथ शुरू किया जाता है. इस तरह, पब्लिशर लागू करने की प्रोसेस सामान्य बनी रह सकती है, _sphinx_site
नियम सिर्फ़ एचटीएमएल जनरेट कर सकता है, और इन दोनों को एक साथ जोड़ने के लिए, यह छोटी स्क्रिप्ट ही ज़रूरी है.
rules_k8s
में, .apply
यह काम करता है:
expand_template
apply.sh.tpl
के आधार पर, एक बहुत आसान बैश स्क्रिप्ट लिखता है.
यह kubectl
, मुख्य टारगेट के आउटपुट के साथ चलती है. इसके बाद, इस स्क्रिप्ट को bazel run :staging.apply
के साथ बनाया और चलाया जा सकता है. इससे k8s_object
टारगेट के लिए, k8s-apply
निर्देश असरदार तरीके से मिलता है.