2017-03-28 8 views
5

में चरण सत्यापित करें मैं go vet, gofmt, pylint, cppcheck जैसे बैज़ल में "चेक" या "सत्यापित" चरणों को चलाने के लिए एक अच्छी नुस्खा ढूंढ रहा हूं। ये चरण कोई आउटपुट फ़ाइल नहीं बनाते हैं। एकमात्र चीज जो मायने रखती है वह रिटर्न कोड है (एक परीक्षण की तरह)।बेज़ेल

अभी मैं निम्नलिखित नुस्खा उपयोग कर रहा हूँ:

sh_test(
    name = "verify-pylint", 
    srcs = ["verify-pylint.sh"], 
    data = ["//:all-srcs"], 
) 

और verify-pylint.sh इस तरह दिखता है:

find . -name '*.py' | xargs pylint 

यह दो समस्याएं हैं:

  • को सत्यापित तर्क विभाजित है खोल स्क्रिप्ट और BUILD फ़ाइल के बीच। आदर्श रूप में मैं दोनों एक ही स्थान पर (BUILD फ़ाइल में)
  • किसी भी समय स्रोत फ़ाइल में से कोई भी बदलता है (//:all-srcs में), bazel test verify-pylint प्रत्येक फ़ाइल पर pylint को फिर से चलाता है (और यह महंगा/धीमा हो सकता है) ।

इन चरणों को चलाने के लिए बेज़ेल में बेवकूफ तरीका क्या है?

उत्तर

3

एक से अधिक समाधान हैं।

बिल्ड समय पर सत्यापन करना सबसे साफ तरीका है: आप प्रत्येक फ़ाइल (या फाइलों का बैच) के लिए genrule बनाते हैं, और यदि सत्यापन सफल होता है, तो जनरेट कुछ विफल हो जाता है, अगर यह विफल हो जाता है, तो नियम कुछ भी आउटपुट नहीं करता है, जो स्वचालित रूप से बिल्ड को विफल करता है।

सत्यापन की सफलता फ़ाइल की सामग्री पर निर्भर करती है, और उसी इनपुट में एक ही आउटपुट उत्पन्न होना चाहिए, जेनरल को आउटपुट फ़ाइल का उत्पादन करना चाहिए जो इनपुट की सामग्री पर निर्भर है। सबसे सुविधाजनक बात यह है कि सत्यापन सफल होने पर आउटपुट में फ़ाइल के पाचन को लिखना है, और सत्यापन विफल होने पर कोई आउटपुट नहीं है।

सत्यापनकर्ता पुन: प्रयोज्य बनाने के लिए, आप Skylark macro बना सकते हैं और अपने सभी संकुलों में इसका उपयोग कर सकते हैं।

यह सब एक साथ रखने के लिए, आप निम्न की तरह कुछ लिखेंगे। //tools:py_verify_test.bzl का

सामग्री:

def py_verify_test(name, srcs, visibility = None): 
    rules = {"%s-file%d" % (name, hash(s)): s for s in srcs} 
    for rulename, src in rules.items(): 
     native.genrule(
      name = rulename, 
      srcs = [s], 
      outs = ["%s.md5" % rulename], 
      cmd = "$(location //tools:py_verifier) $< && md5sum $< > [email protected]", 
      tools = ["//tools:py_verifier"], 
      visibility = ["//visibility:private"], 
     ) 

    native.sh_test(
     name = name, 
     srcs = ["//tools:build_test.sh"], 
     data = rules.keys(), 
     visibility = visibility, 
    ) 

//tools:build_test.sh की सामग्री:

#!/bin/true 
# If the test rule's dependencies could be built, 
# then all files were successfully verified at 
# build time, so this test can merely return true. 

//tools:BUILD की सामग्री:

# I just use sh_binary as an example, this could 
# be a more complicated rule of course. 
sh_binary(
    name = "py_verifier", 
    srcs = ["py_verifier.sh"], 
    visibility = ["//visibility:public"], 
) 

किसी भी पैकेज फ़ाइलों सत्यापित करना चाहती है कि की सामग्री:

load("//tools:py_verify_test.bzl", "py_verify_test") 

py_verify_test(
    name = "verify", 
    srcs = glob(["**/*.py"]), 
) 
1

एक साधारण समाधान।

अपने निर्माण फ़ाइल में:

load(":gofmt.bzl", "gofmt_test") 

gofmt_test(
    name = "format_test", 
    srcs = glob(["*.go"]), 
) 

gofmt.bzl में:

def gofmt_test(name, srcs): 
    cmd = """ 
    export TMPDIR=. 
    out=$$(gofmt -d $(SRCS)) 

    if [ -n "$$out" ]; then 
     echo "gmfmt failed:" 
     echo "$$out" 
     exit 1 
    fi 
    touch [email protected] 
    """ 
    native.genrule(
     name = name, 
     cmd = cmd, 
     srcs = srcs, 
     outs = [name + ".out"], 
     tools = ["gofmt.sh"], 
) 

कुछ टिप्पणियों:

  • अपने आवरण स्क्रिप्ट बढ़ता है, तो आप इसे एक अलग .sh में क्या रखना चाहिए फ़ाइल।
  • genrule आदेश में, हम कारण से बचने के लिए $$ बजाय $ जरूरत है (documentation देखें)
  • gofmt_test वास्तव में एक परीक्षण नहीं है और bazel build :all के साथ चलेंगे। यदि आपको वास्तव में एक परीक्षण की आवश्यकता है, तो Laszlo का उदाहरण देखें और sh_test पर कॉल करें।
  • मैं फ़ाइल बनाने के लिए touch पर कॉल करता हूं क्योंकि genrule को आउटपुट सफल होने की आवश्यकता होती है।
  • export TMPDIR=. की आवश्यकता है क्योंकि डिफ़ॉल्ट रूप से सैंडबॉक्स अन्य निर्देशिकाओं में लेखन को रोकता है।

प्रत्येक फ़ाइल के लिए परिणाम कैश करने के लिए (और एक फ़ाइल को फिर से जांचने से बचने के लिए), आपको कई क्रियाएं बनाने की आवश्यकता होगी। Laszlo के for पाश देखें।

कोड को सरल बनाने के लिए, हम एक सामान्य नियम प्रदान कर सकते हैं। शायद यह एक मानक पुस्तकालय में हमें कुछ देना चाहिए।