使用巨集建立自訂動詞

回報問題 查看來源 夜間 7.2 7.1 7.0 6.5 6.4

與 Bazel 的日常互動主要是透過幾個指令進行: buildtestrun。然而,您可能會遇到以下問題: 您可能會想將套件推送至存放區、為使用者發布說明文件 運用 Kubernetes 部署應用程式但 Bazel 沒有 publish deploy 指令 – 這些動作的顯示位置為何?

bazel run 指令

Bazel 著重在遺傳性、可重現性和成效增幅 buildtest 指令對上述工作沒有幫助。這些動作 可以在網路存取有限的沙箱中執行, 每次 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",
)

k8s_object 規則會建構 staging 上使用 bazel build 時的標準 Kubernetes YAML 檔案 目標。不過,k8s_object 也會建立其他目標 巨集,例如 staging.apply:staging.delete 等名稱。這些版本 指令碼執行這些動作;當使用 bazel run staging.apply 執行時,這些動作的行為就像我們專屬的 bazel k8s-applybazel 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 目標,而不是比較 互相對抗實際上,相同的測試指令碼可以直接在「verify」中執行 或「接受」並自動切換模式。也遵循相同的模式 您已瞭解:沒有原生 bazel test-accept 指令,但 也能達到相同效果 bazel run //etc/api:angular_devkit_core_api.accept

這個模式的功能可能非常強大 辨識出來的方法

自行調整規則

巨集是這個模式的核心。巨集的用途類似 但可以建立多個指定目標他們通常會建立 目標為指定名稱,執行主要建構動作:或許 容器則會建構一般二進位檔、Docker 映像檔或原始碼封存檔於 因此會建立其他目標 例如發布主要目標的輸出內容 二進位檔,或更新預期的測試輸出內容。

為了方便說明,請包裝一個能產生一個網站的虛構規則, 將 Sphinx 與巨集搭配使用,以建立額外的 讓使用者在準備就緒時即可發布影片請考量下列要點 使用 Sphinx 產生網站的現有規則:

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

在這個範例中,「文件」就如同 標準、單一 Bazel 規則規則會在建構完成後產生一些設定 並執行 Sphinx 製作 HTML 網站以手動檢查。不過 額外的「docs.publish」也會建立相應的指令碼 或是發布網站檢查主要目標的輸出內容後 使用 bazel run :docs.publish 發布資訊供大眾使用,就像 虛構的 bazel publish 指令

如何立即瞭解 _sphinx_publisher 的實作方式 看起來會像這樣這類動作通常會編寫啟動器殼層指令碼。 這種方法通常需要使用 ctx.actions.expand_template 編寫非常簡單的 shell 指令碼,本例是叫用發布商二進位檔 其中包含主要目標的輸出內容路徑如此一來 實作可以保持一般性,_sphinx_site 規則只需產生 若要結合這兩種程式碼 。

rules_k8s 中,這就是 .apply 的功用: expand_template敬上 編寫非常簡單的 Bash 指令碼 apply.sh.tpl, 這會以主要目標的輸出內容執行 kubectl。這個指令碼可以 然後透過 bazel run :staging.apply 建構及執行,有效提供 k8s_object 目標的 k8s-apply 指令。