कस्टम क्रिया बनाने के लिए मैक्रो का उपयोग करना

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.
किसी समस्या की शिकायत करें स्रोत देखें

बज़ेल के साथ हर दिन होने वाले इंटरैक्शन मुख्य रूप से कुछ निर्देशों के ज़रिए होते हैं: build, test, और run. हालांकि, कभी-कभी ये सीमित लग सकते हैं: हो सकता है कि आप पैकेज को डेटा स्टोर करने की जगह पर भेजना चाहें, असली उपयोगकर्ताओं के लिए दस्तावेज़ प्रकाशित करना चाहें या Kubernetes पर ऐप्लिकेशन को डिप्लॉय करना चाहें. हालांकि, Bazel के पास publish या deploy निर्देश नहीं होता है – ये कार्रवाइयां कहां फ़िट हो सकती हैं?

बेज़ल रन कमांड

बेज़ल की खासियत, रीप्रॉड्यूसिबिलिटी, और इंक्रीमेंटलिटी पर फ़ोकस करने का मतलब है कि build और test कमांड ऊपर दिए गए टास्क के लिए काम के नहीं हैं. ये काम सैंडबॉक्स में चलाए जा सकते हैं, जिनमें नेटवर्क का सीमित ऐक्सेस होता है. साथ ही, यह ज़रूरी नहीं है कि हर bazel build के साथ इन्हें फिर से चलाया जाए.

इसके बजाय, bazel run पर भरोसा करें: ऐसे टास्क के लिए वर्कहॉर्स जिसके आप इस्तेमाल करना चाहते हैं. Bazel उपयोगकर्ताओं को एक्ज़ीक्यूटेबल बनाने के नियमों का पालन करना होता है. साथ ही, नियम बनाने वाले लोग "कस्टम वर्ब" तक इसे बढ़ाने के लिए, पैटर्न के सामान्य सेट को फ़ॉलो कर सकते हैं.

जंगल में: नियम_k8

उदाहरण के लिए, rules_k8s, Bezel के लिए Kubernetes नियम. मान लें कि आपका टारगेट यह है:

# BUILD file in //application/k8s
k8s_object(
    name = "staging",
    kind = "deployment",
    cluster = "testing",
    template = "deployment.yaml",
)

जब staging टारगेट पर bazel build का इस्तेमाल किया जाता है, तो k8s_object नियम एक मानक Kubernetes YAML फ़ाइल बनाता है. हालांकि, staging.apply और :staging.delete जैसे नामों वाले k8s_objectमैक्रो भी अतिरिक्त टारगेट बनाते हैं. ये कार्रवाइयां करने के लिए स्क्रिप्ट बनाती हैं. जब bazel run staging.apply के साथ काम करती हैं, तो ये हमारे bazel k8s-apply या bazel k8s-delete निर्देशों की तरह काम करती हैं.

एक और उदाहरण: ts_api_Guardian_test

इस पैटर्न को ऐंगुलर प्रोजेक्ट में भी देखा जा सकता है. 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 का इस्तेमाल करके, ऐसा किया जा सकता है.

यह पैटर्न काफ़ी कारगर साबित हो सकता है. इसे पहचानने के बाद, यह तरीका काफ़ी सामान्य हो जाता है.

अपने नियम खुद के मुताबिक अपनाना

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

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

_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"],
)

इस उदाहरण में, "मैक्स" टारगेट बनाया गया है, जिस तरह मैक्रो मानक, सिंगल बेज़ल नियम होता है. नियम बनाए जाने पर, नियम कुछ कॉन्फ़िगरेशन जनरेट करता है और स्फ़िंक्स को एचटीएमएल साइट बनाने के लिए चलाता है. यह साइट मैन्युअल जांच के लिए तैयार होती है. हालांकि, एक नया "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 निर्देश दिया जा सकता है.