angular-cn/dev-infra/bazel/browsers/browser_archive_repo.bzl

97 lines
4.3 KiB
Python

"""Implementation of the `browser_archive` rule."""
def _browser_archive_impl(ctx):
url = ctx.attr.url
sha256 = ctx.attr.sha256
# If the URL resolves to a `.dmg` file, then we need to convert the file
# to a zip so that we can extract the actual binaries. We use the `convert_dmg`
# script provided by the webtesting Bazel rules.
if url.endswith(".dmg"):
download_file_name = "_download_file_%s.dmg" % ctx.attr.name
result_zip_name = "_converted_file_%s.zip" % ctx.attr.name
ctx.download(url, download_file_name, sha256)
ctx.execute([ctx.path(Label("@io_bazel_rules_webtesting//web/internal:convert_dmg.sh")), download_file_name, result_zip_name])
ctx.extract(result_zip_name)
ctx.delete(result_zip_name)
ctx.delete(download_file_name)
else:
ctx.download_and_extract(
url = url,
sha256 = sha256,
)
# The browser archive has been downloaded and extracted. We now generate a repository
# `BUILD.bazel` file that exposes the archive files, together with the specified
# named files using the `browser_configure` rule.
ctx.file("BUILD.bazel", content = """
load("@angular//dev-infra/bazel/browsers:browser_configure.bzl", "browser_configure")
licenses(%s)
browser_configure(
name = "metadata",
files = glob(["**/*"]),
named_files = %s,
visibility = ["//visibility:public"],
)
""" % (str(ctx.attr.licenses), str(ctx.attr.named_files)))
"""
Rule that can be used to download and unpack a browser archive in a dedicated Bazel
repository. Additionally, files within the archive can be denoted with an unique name
so that web tests can access browser files in a platform-agnostic way, regardless of
which `browser_archive` repository is added as dependency.
As an example for the concept of denoting archive files with an unique name, consider a case
where a a web test decides conditionally based on the current exec platform which
`browser_archive` repository is used (e.g. mac, windows or linux). The archives are different
for each platform. The test usually would need to determine the current platform, and know how
each archive is structured in order to access the browser binary within the repository. By
defining named files though, the web test could just pull a named file called `BINARY` that
always resolves to the browser binary in a platform-agnostic way.
Note #1: This rule exists as an alternative to the `platform_http_file` concept
from `rules_webtesting` because the `platform_http_file` rule does not extract the archive
directly, but relies on later build actions to perform the unpacking. This results in less
efficient caching because build actions are invalidated more frequently (e.g. `bazel clean).
We also noticed that the extraction within RBE containers is rather unstable, and extracting
the archives as part of a Bazel repository mitigates this (as extractions happens on the host).
Note #2: Additionally `rules_webtesting` defines a single repository for all platforms,
where only an archive for the current host platform is pulled. This breaks cross-compilation
because the wrong platform archive would be used for web tests that run in the exec platform.
"""
browser_archive = repository_rule(
implementation = _browser_archive_impl,
attrs = {
"url": attr.string(
doc = "Browser archive to download and extract.",
mandatory = True,
),
"sha256": attr.string(
doc = "SHA256 checksum for the archive.",
mandatory = True,
),
"licenses": attr.string_list(
mandatory = True,
allow_empty = False,
doc = """
Licenses that apply to the archive. Will be passed to a `licenses` invocation
within the repository. https://docs.bazel.build/versions/0.24.0/be/functions.html#licenses.
""",
),
"named_files": attr.string_dict(
doc = """
Dictionary that maps files to unique identifiers. This is useful
if browser archives are different on different platforms and the web
tests would not want to care about archive-specific paths. e.g. targets
expect a `CHROMIUM` key to point to the Chromium browser binary.
""",
mandatory = True,
),
},
)