blob: 18bbe8f5c141f75c48fd69105a0eddd7e9beba78 [file] [log] [blame]
# Copyright 2022 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.
"""CIPD repository rule utilities."""
load("//fuchsia/workspace:utils.bzl", "workspace_path")
_CIPD_GLOBAL_BIN_ENV = "CIPD_BIN"
def _verify_cipd_bin(repository_ctx, bin):
exec_result = repository_ctx.execute([
bin,
"--version",
])
if exec_result.return_code != 0:
fail("Invalid cipd binary provided ")
def _setup_from_path(repository_ctx, path):
bin = repository_ctx.path(path)
if repository_ctx.attr.validate_cipd_bin:
_verify_cipd_bin(repository_ctx, bin)
repository_ctx.symlink(bin, "cipd")
def _platform(repository_ctx):
os = repository_ctx.os
name = os.name.split(" ")[0].lower()
arch = os.arch
if arch == "x86_64":
arch = "amd64"
elif arch == "aarch64":
arch = "arm64"
return "{}-{}".format(name, arch)
def _cipd_revision(repository_ctx):
version_file = repository_ctx.attr._cipd_client_version
rev = repository_ctx.read(version_file)
return rev
def _sha_for_platform(repository_ctx, platform):
digests_file = repository_ctx.attr._cipd_client_version_digests
digests = repository_ctx.read(digests_file)
for line in digests.splitlines():
if line.startswith("#"):
continue
# split(" ") will include the blanks so we need to split and then
# strip out the blanks
parts = []
for part in line.split(" "):
if part != "":
parts.append(part)
if len(parts) == 3 and parts[0] == platform:
return parts[2]
return None
def _download_cipd_binary(repository_ctx):
platform = _platform(repository_ctx)
rev = _cipd_revision(repository_ctx)
url = "https://chrome-infra-packages.appspot.com/client?platform={}&version={}".format(platform, rev)
sha = _sha_for_platform(repository_ctx, platform)
if sha == None:
fail("unsupported cipd platform {}".format(platform))
repository_ctx.download(
url,
executable = True,
output = "cipd",
sha256 = sha,
)
def _cipd_tool_repository_impl(repository_ctx):
if repository_ctx.attr.bin:
bin_path = workspace_path(repository_ctx, repository_ctx.attr.bin)
_setup_from_path(repository_ctx, bin_path)
elif repository_ctx.os.environ.get(_CIPD_GLOBAL_BIN_ENV):
_setup_from_path(
repository_ctx,
repository_ctx.os.environ.get(_CIPD_GLOBAL_BIN_ENV),
)
else:
_download_cipd_binary(repository_ctx)
repository_ctx.file("WORKSPACE.bazel", content = " ")
repository_ctx.file("BUILD.bazel", content = 'exports_files(glob(["**/*"]) )')
cipd_tool_repository = repository_rule(
implementation = _cipd_tool_repository_impl,
attrs = {
"bin": attr.string(doc = "The path to the cipd binary"),
"validate_cipd_bin": attr.bool(
doc = "Whether we should validate that the cipd binary is valid",
default = True,
),
"_cipd_client_version": attr.label(default = "//cipd/private/cipd_digests:cipd_client_version"),
"_cipd_client_version_digests": attr.label(default = "//cipd/private/cipd_digests:cipd_client_version.digests"),
},
)
def _cipd_tool_repository_ext_impl(ctx):
bin = None
for mod in ctx.modules:
# Only allow the root module to set the binary.
if mod.is_root:
# Check to see if the root set the bin to use.
client_tags = mod.tags.client
if len(client_tags) == 2:
fail("only one client tag may be specified at a time")
elif len(client_tags) == 1:
bin = client_tags[0].bin
cipd_tool_repository(
name = "cipd_tool",
bin = bin,
)
_cipd_client_tag = tag_class(attrs = {"bin": attr.string()})
cipd_tool_ext = module_extension(
implementation = _cipd_tool_repository_ext_impl,
tag_classes = {"client": _cipd_client_tag},
)