blob: f9f3c1bab13654ffadcebc48ca7a19a19a7cc1f8 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2026 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Create a bazelrc file that contains unique values per invocation
based on environment variables such as uuids and paths to temporary sockets.
The generated bazelrc file is closely related to
template.remote_services.bazelrc in that it amends existing configuration
definitions.
This script is intended to work for both developer (fx) and infra builds.
"""
import argparse
import os
import sys
from typing import Iterable
_SCRIPT_DIR = os.path.dirname(__file__)
def bbid_link(bbid: str) -> str:
# Builds launched directly by the 'led' tool look different
# from other infra builds.
if "/led/" in bbid:
return f"http://go/lucibuild/{bbid}/+/build.proto"
else:
return f"http://go/bbid/{bbid}"
def metadata_option(key: str, value: str) -> str:
"""Returns the equivalent bazel option for passing metadata."""
return f"--build_metadata={key}={value}"
def build_config_option(config: str, options: str) -> str:
"""Returns a bazelrc command that maps options into a config definition."""
return f"build:{config} {options}"
def metadata_bazelrc(env: dict[str, str]) -> Iterable[str]:
uuid = env.get("FX_BUILD_UUID") # set by 'fx build'
bbid = env.get("BUILDBUCKET_ID") # set by infra builds
if not uuid and not bbid:
# This is an out-of-build invocation that we don't care to record.
return
if uuid:
# Link all invocations directly to the top-level FX_BUILD_UUID.
yield build_config_option(
"_bes_common",
metadata_option("FX_BUILD_UUID", uuid),
)
if bbid:
# Link all invocations directly to the top-level buildbucket.
yield build_config_option(
"_bes_common",
metadata_option("BUILDBUCKET_ID", bbid),
)
# LINT.IfChange(related_invocations_env_vars)
parent_build_id = env.get("RESULTSTORE_PARENT_BUILD_ID")
if not parent_build_id:
# This is a top-level build invocation.
# For infra builds, reference the bbid (buildbucket).
if bbid:
yield build_config_option(
"_bes_common",
metadata_option("PARENT_BUILD_ID", bbid),
)
yield build_config_option(
"_bes_common",
metadata_option("PARENT_BUILD_LINK", bbid_link(bbid)),
)
# For fx-builds, leave PARENT_BUILD_ID, PARENT_BUILD_LINK,
# and SIBLING_BUILDS_LINK unset.
else:
# This is a sub-build.
# Take the values provided by the environment from a parent build.
yield build_config_option(
"_bes_common",
metadata_option("PARENT_BUILD_ID", parent_build_id),
)
# URLs are already based on whether sponge/resultstore is used,
# so there is no need to select here.
parent_link = env.get("RESULTSTORE_PARENT_BUILD_LINK")
if parent_link:
yield build_config_option(
"_bes_common",
metadata_option("PARENT_BUILD_LINK", parent_link),
)
siblings_link = env.get("RESULTSTORE_SIBLING_BUILDS_LINK")
if siblings_link:
yield build_config_option(
"_bes_common",
metadata_option("SIBLING_BUILDS_LINK", siblings_link),
)
# LINT.ThenChange(
# //build/bazel/wrapper.bazel.sh:related_invocations_env_vars,
# //build/bazel/scripts/rsninja.sh:related_invocations_env_vars
# )
def service_proxies_bazelrc(env: dict[str, str]) -> Iterable[str]:
# Redirect traffic to proxies (infra only).
# Remote service configuration.
rbe_socket_path = env.get("BAZEL_rbe_socket_path")
if rbe_socket_path:
yield build_config_option(
"_remote_common", f"--remote_proxy=unix://{rbe_socket_path}"
)
# sponge and resultstore are mutually exclusive, so only one of the
# following two --bes_proxy options will ever apply.
sponge_socket_path = env.get("BAZEL_sponge_socket_path")
if sponge_socket_path:
yield build_config_option(
"sponge_infra", f"--bes_proxy=unix://{sponge_socket_path}"
)
resultstore_socket_path = env.get("BAZEL_resultstore_socket_path")
if resultstore_socket_path:
yield build_config_option(
"resultstore_infra", f"--bes_proxy=unix://{resultstore_socket_path}"
)
def generate_bazelrc(
sub_builds_link: str, env: dict[str, str]
) -> Iterable[str]:
header = [
"# This bazelrc file contains ephemeral options that are not intended",
"# to persist across build invocations.",
"# AUTO-GENERATED - DO NOT EDIT!",
]
yield from header
if sub_builds_link:
yield build_config_option(
"_bes_common",
metadata_option("SUB_BUILDS_LINK", sub_builds_link),
)
yield from metadata_bazelrc(env)
yield from service_proxies_bazelrc(env)
def main(argv):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--sub_builds_link",
type=str,
default="",
help="The URL to a search query that finds sub-builds of this invocation.",
)
args = parser.parse_args(argv)
for line in generate_bazelrc(args.sub_builds_link, os.environ):
print(line)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))