マクロを使ってカスタム動詞を作成する

<ph type="x-smartling-placeholder"></ph> 問題を報告する ソースを表示 夜間 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel との日常的なやり取りは、主にいくつかのコマンドによって行われます。 buildtestrun。しかし、時には限界を感じることもあります。 パッケージをリポジトリに push する、エンドユーザー向けのドキュメントを公開する、 Kubernetes でアプリケーションをデプロイします。しかし、Bazel には publishdeploy コマンド – これらのアクションの位置付け

bazel run コマンド

Bazel は密閉性、再現性、インクリメンタリティを重視しているため、 build コマンドと test コマンドは、上記のタスクには役立ちません。これらのアクション ネットワーク アクセスが制限されたサンドボックスで実行されることがあり、セキュリティ リスクが bazel build ごとに再実行します。

代わりに、実行するタスクの主力である bazel run に頼ってください。 防ぐことができます。Bazel ユーザーが、実行可能ファイルを作成するルールに慣れている ルール作成者は、共通のパターン セットに従って、ルールを "custom verbs"。

実際の環境: rules_k8s

たとえば rules_k8s について考えてみましょう。 Bazel に関する Kubernetes のルールです。次のようなターゲットがあるとします。

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

k8s_object ルールは、 stagingbazel build が使用されている場合の標準の 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 マクロ 2 つのターゲットが生成されます。1 つ目は標準の 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 とマクロで別の行を作成 ターゲットにし、準備ができたらユーザーが公開できるようにします。次の点を考慮してください。 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 ファイルで、プライマリを作成するだけの場合と同様にマクロを使用します。 target:

sphinx_site(
    name = "docs",
    srcs = ["index.md", "providers.md"],
)

この例では、"docs"マクロが元のコマンドで 単一の Bazel ルールを適用します。ビルド時に、このルールによりいくつかの構成が生成されます。 Sphinx を実行して、手動検査が可能な HTML サイトを生成します。ただし、 追加の「docs.publish」作成されると、このファイルを使用して、 サイトを公開しています。プライマリ ターゲットの出力を確認したら、 以下と同様に、bazel run :docs.publish を使用して一般公開用に公開します。 架空の bazel publish コマンド。

_sphinx_publisher の実装が何であるかは、すぐにはわかりません。 見てみましょう。多くの場合、このようなアクションではランチャー シェル スクリプトを作成します。 この方法では、通常、 ctx.actions.expand_template 非常にシンプルなシェル スクリプトを作成します。この例では、Publisher バイナリを呼び出します。 プライマリ ターゲットの出力へのパスに置き換えます。これによりパブリッシャーは 汎用的な実装にできますが、_sphinx_site ルールによって生成されるのは この小さなスクリプトだけで、この 2 つの 説明します。

rules_k8s では、実際に .apply はこのように動作します。 expand_template 基礎となる非常にシンプルな Bash スクリプトを apply.sh.tpl, プライマリ ターゲットの出力を使用して kubectl を実行します。このスクリプトは、 bazel run :staging.apply を指定してビルドおよび実行することで、 k8s_object ターゲットに対する k8s-apply コマンド。