I'd like to migrate away from --define flags and to build settings per: https://docs.bazel.build/versions/5.0.0/skylark/config.html
Here's the rule to which I'd like to pass command line values.
- Can this be done in practice when using loaded rules?
- Can one access build setting values in rule fields of .bazel files, or are they only accessible to Starlark configurations?
- Is there a way to effectively "subclass" a loaded rule without having access to a published implementation? If
_implwere public, it seems like I might be able to wrap it with my own implementation that passes it the flags.
I'm somewhat new to Bazel and still figuring out the right way to conceptualize this stuff. Any guidance is appreciated!
Current Approach
backend/BUILD.bazel:
load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_push")
# container_image :run_server definition
container_push(
name = "push_server",
format = "Docker",
image = ":run_server",
registry = "gcr.io",
repository = "$(PROJECT_ID)/chat/server",
tag = "$(CONTAINER_TAG)",
)
Then I run:
bazel run \
--platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 \
--define PROJECT_ID=$(gcloud config get-value project) \
--define CONTAINER_TAG=some_feature_branch \
-- //backend:push_server
What I've Tried
A few variations of:
load("//backend:rules.bzl", "gcr_container_push")
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load("@io_bazel_rules_docker//container:container.bzl", "container_image")
string_flag(
name = "container_tag",
build_setting_default = "latest",
visibility = ["//visibility:public"],
)
string_flag(
name = "project_id",
build_setting_default = "",
visibility = ["//visibility:public"],
)
# container_image :run_server definition
gcr_container_push(
name = "push_server",
image = ":run_server",
path = "chat/server",
)
backend/rules.bzl:
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@io_bazel_rules_docker//container:container.bzl", "container_push")
def _gcr_container_push_impl(ctx):
project_id = ctx.attr._project_id[BuildSettingInfo].value
if len(project_id) == 0:
fail("Please provide a GCP project ID via --//backend:project_id=<PROJECT ID>.")
container_push(
name = ctx.label.name,
format = "Docker",
image = ctx.attr.image,
registry = "gcr.io",
repository = paths.join(project_id, ctx.attr.path),
tag = ctx.attr._container_tag[BuildSettingInfo].value,
)
_gcr_container_push_attrs = {
"image": attr.label(
allow_single_file = [".tar"],
mandatory = True,
doc = "The label of the image to push.",
),
"path": attr.string(
mandatory = True,
doc = "The name of the image within the repository. Ex. gcr.io/project_id/<PATH>:tag.",
),
"_container_tag": attr.label(default = Label("//backend:container_tag")),
"_project_id": attr.label(default = Label("//backend:project_id")),
}
gcr_container_push = rule(
implementation = _gcr_container_push_impl,
attrs = _gcr_container_push_attrs,
executable = True,
)
Then I run:
bazel run \
--platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 \
--//backend:project_id=ggx-prototype \
-- //backend:push_server
Which returns:
Error in container_push_: 'container_push_' can only be called during the loading phase
rules_dockerhas attrs likerepository_fileandtag_filefor exactly this kind of thing. You can generate those files however you want, including a custom rule that uses your user-defined flags. I'd do it like this:Your attempt is mixing a rule and a macro. Rules have attrs and an _impl vs macros can use other rules. My approach uses custom rules to generate the files, and a macro to tie those rules to
container_push.The general answer to your question is that this requires modifying the rule to perform new kinds of substitutions based on a user-defined flag. I can see some kind of
--@rules_docker//flags:docker_info=MY_PROJECT=fooconfigured withallow_multiple = Truethat would get substituted, but it definitely requires rule modifications. Wrapping the _impl is going to be tricky, because you have to reach in and change some of the actions.