有选择地部署 Bazel 构建的项目



>我通过bazel build生成工件。我只想在它们发生变化时才部署它们。

检测工件是否更改的最佳方法是什么?

。有没有办法获取构建目标的摘要?理想情况下不需要构建它?

这里的方法在很大程度上取决于所有细节。

一种方法是使用构建事件协议设置一些东西: https://docs.bazel.build/versions/master/build-event-protocol.html

这可能比您想要处理的设置更多。

另一种方法是使用genrules或类似的方式来哈希您感兴趣的所有工件(我不知道有一种方法可以让 bazel 输出其工件哈希(。然后创建一个二进制文件(sh_binary或其他东西(,它将您感兴趣的所有工件及其哈希值作为输入,并将这些哈希值与已部署内容的哈希值进行比较,然后部署更改的内容。

另一种方法是创建一个 Starlark 规则,该规则为您有兴趣部署的每个内容注册一个"部署操作"。Bazel 将仅对每次运行部署目标时已更改的那些项目运行部署操作。这可能看起来像这样:

defs.bzl

def _deploy_impl(ctx):
deploy_results = []
for deployable in ctx.attr.deployables:
deploy_result = ctx.actions.declare_file(
ctx.label.name + "_" + deployable.label.name + "_deploy_result")
deploy_results.append(deploy_result)
deploy_args = ctx.actions.args()
deploy_args.add(deploy_result)
deploy_args.add(ctx.attr.destination)
deploy_args.add_all(deployable.files)
ctx.actions.run(
executable = ctx.attr._deploy_tool.files_to_run,
inputs = deployable.files,
outputs = [deploy_result],
arguments = [deploy_args],
execution_requirements = {
"no-sandbox": "1",
"local": "1",
"no-cache": "1",
"no-remote-cache": "1",
"no-remote": "1",
})
return [DefaultInfo(files = depset(deploy_results))]
deploy = rule(
implementation = _deploy_impl,
attrs = {
"deployables": attr.label_list(),
"destination": attr.string(mandatory=True),
"_deploy_tool": attr.label(default = "//:deploy_tool", cfg = "host"),
}
)

deploy_tool.sh

result_file_path="$1"
shift
destination="$1"
shift
echo "deploying $@ to $destination"
cp -f --target-directory "$destination" $@
touch "$result_file_path"

BUILD


load(":defs.bzl", "deploy")
genrule(
name = "gen_a",
srcs = ["a"],
outs = ["a.out"],
cmd = "cp $< $@",
)
genrule(
name = "gen_b",
srcs = ["b"],
outs = ["b.out"],
cmd = "cp $< $@",
)
genrule(
name = "gen_c",
srcs = ["c"],
outs = ["c.out"],
cmd = "cp $< $@",
)
deploy(
name = "deploy",
deployables = [
":gen_a",
":gen_b",
":gen_c",
],
destination = "/tmp",
)
sh_binary(
name = "deploy_tool",
srcs = ["deploy_tool.sh"],
)

用法:

$ bazel build deploy
INFO: Analyzed target //:deploy (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
INFO: From Action deploy_gen_a_deploy_result:
deploying bazel-out/k8-fastbuild/bin/a.out to /tmp
INFO: From Action deploy_gen_c_deploy_result:
deploying bazel-out/k8-fastbuild/bin/c.out to /tmp
INFO: From Action deploy_gen_b_deploy_result:
deploying bazel-out/k8-fastbuild/bin/b.out to /tmp
Target //:deploy up-to-date:
bazel-bin/deploy_gen_a_deploy_result
bazel-bin/deploy_gen_b_deploy_result
bazel-bin/deploy_gen_c_deploy_result
INFO: Elapsed time: 0.146s, Critical Path: 0.02s
INFO: 3 processes: 3 local.
INFO: Build completed successfully, 5 total actions

一些注意事项:

  1. "部署操作"本质上是非常非密封的,这通常被认为是不好的,但在这里很好。特别是,查看操作的所有"execution_requirements"。

  2. Bazel 将尝试并行运行所有部署操作,这可能是好事,也可能是坏事。

  3. deploy规则可以设置为可执行规则,以便它可以与bazel run一起使用,这听起来可能更好。

  4. 如果你真的需要,这个例子也可能使用宏来完成,但它会创建很多"人工"目标。

最新更新