Skip to content

Instantly share code, notes, and snippets.

@DeCarabas
Created July 20, 2022 17:29
Show Gist options
  • Save DeCarabas/8b1cf5875577342631cb5312cce3f3db to your computer and use it in GitHub Desktop.
Save DeCarabas/8b1cf5875577342631cb5312cce3f3db to your computer and use it in GitHub Desktop.
These are our current rules for integrating bazel and Tilt
# -*- mode: bazel-build -*-
def require_tool(tool):
tool = shlex.quote(tool)
local('command -v {tool} >/dev/null 2>&1 || {{ echo >&2 "{tool} is required but was not found in PATH"; exit 1; }}'.format(tool = tool))
require_tool("bazelisk")
BAZEL_RUN_CMD = "bazelisk run"
BAZEL_SOURCES_QUERY = 'kind("source file", deps(set(%s)))'
BAZEL_BUILDFILES_QUERY = "buildfiles(deps(set(%s)))"
def workspace_files():
workspace_root = str(local("bazelisk info workspace")).strip()
return [
os.path.join(workspace_root, "WORKSPACE"),
os.path.join(workspace_root, "WORKSPACE.bazel"),
]
def xml_output_to_files(output):
files = {}
for line in str(output).splitlines():
LOCATION_SLUG = 'location="'
start_index = line.find(LOCATION_SLUG)
if start_index < 0:
continue
end_index = line.find('"', start_index + len(LOCATION_SLUG))
path = line[start_index + len(LOCATION_SLUG):end_index]
# These indices sometimes end with :1:1 and
if path.endswith(":1:1"):
path = path[:-4]
# This file is problematic; it gets regenerated every build sometimes
# and tilt gets locked into a loop.
if path.endswith("local_config_cc/BUILD"):
continue
files[path] = None
return sorted(files.keys())
def bazel_query(query):
query_cmd = "bazelisk query '%s' --order_output=No --output=xml" % query
# this XML output is so noisy, so we set it to quiet and only print the
# output files
xml = local(query_cmd, quiet = True)
files = xml_output_to_files(xml)
for file in files:
print(" → " + file)
print(" (Output parsed from XML)")
return files
def bazel_build(image, target):
# Compute the build deps. We watch them here because we want to re-run
# this function when the set of dependencies changes, and these are the
# files that generate the set of dependencies.
build_deps = workspace_files() + bazel_query(BAZEL_BUILDFILES_QUERY % target)
for dep in build_deps:
watch_file(dep)
# Ask bazel for the source files that go into this target.
deps = bazel_query(BAZEL_SOURCES_QUERY % target)
# The build files *also* impact the way the compilation goes, so we need
# to fold them into the direct dependency set too, along with the actual
# source files.
deps = deps + build_deps
# Bazel puts the image at bazel/{dirname}, so transform
# //snack:image -> bazel/snack:image
dest = target.replace("//", "bazel/")
command = "{run_cmd} {target} -- --norun && docker tag {dest} $EXPECTED_REF".format(
dest = dest,
run_cmd = BAZEL_RUN_CMD,
target = target,
)
custom_build(
image,
command = command,
deps = deps,
)
def bazel_helm_path(target):
for file in workspace_files():
watch_file(file)
for file in bazel_query(BAZEL_BUILDFILES_QUERY % target):
watch_file(file)
files = bazel_query(BAZEL_SOURCES_QUERY % target)
return os.path.dirname(files[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment