Bazel module to help create and maintain Bazel external repos.
First, make sure you are running Bazel with Bzlmod. Then, add the module as a
dependency in your MODULE.bazel
:
bazel_dep(name = "download_archives", version = "<VERSION>")
If you need to use a specific commit or version tag from the repo instead of a
version from the registry, add a non-registry override in your MODULE.bazel
file, e.g. archive_override
:
REF = "v<VERSION>" # NOTE: can be a repo tag or a commit hash
archive_override(
module_name = "download_archives",
integrity = "", # TODO: copy the SRI hash that Bazel prints when fetching
strip_prefix = "bazel_download_archives-%s" % REF.strip("v"),
urls = ["https://github.com/jjmaestro/bazel_download_archives/archive/%s.tar.gz" % REF],
)
NOTE:
integrity
is intentionally empty so Bazel will warn and print the SRI hash of
the downloaded artifact. Leaving it empty is a security risk. Always verify
the contents of the downloaded artifact, copy the printed hash and update
MODULE.bazel
accordingly.
download_archives
is a repository rule to create and maintain Bazel
external repos. It helps reduce boilerplate code by keeping a JSON index file
with all of the metadata required to download and extract an archive: the
archive's version
(s) and the source
(s) from which to try to download the
archive.
This repository rule wraps rctx.download_and_extract
and creates a Bazel
repo under @<REPO_NAME>
, downloading and extracting one archive from one
of the sources for each of the archive versions in the [repo JSON index].
When downloading the archive, if a source fails it will try the next one, and only fail if all sources are exhausted.
On top of just reducing boilerplate code, the download_archives
repository
rule also adds helper constants and alias
es to the Bazel repo. Please read
the docs for more information about all of their additional functionality.
Here's an example that shows how to create a @wget_src
repo for GNU wget:
First, define a repo.json
JSON index file in a package. Don't forget to add a
BUILD.bazel
file in it if one doesn't already exists).
E.g. for a //third-party/wget
package:
mkdir -p third-party/wget
touch third-party/wget/BUILD.bazel
Then add the following to the repo.json
file:
{
"version": 1,
"sources": {
"github.com": {
"owner": "mirror",
"repo": "wget",
"tag": "v{version}",
"url": "https://{source}/{owner}/{repo}/archive/refs/tags/{tag}.tar.gz",
"strip_prefix": "{repo}-{version}"
},
"gitlab.com": {
"owner": "gnuwget",
"repo": "wget",
"tag": "v{version}",
"filename": "{repo}-{tag}",
"url": "https://{source}/{owner}/{repo}/-/archive/{tag}/{filename}.tar.gz",
"strip_prefix": "{filename}"
}
},
"versions": {
"1.24.5": {
"integrity": {
"gitlab.com": "sha256-1Yw1cok0niLv563o07/BrjbCQIflWxK8UFlav9srtcw="
}
},
"1.21.3": {
"github.com": "sha256-VbH6fHnent2TtbYxbNoatK4RNkY3MVPXokJhRzPZBg8=",
"gitlab.com": "sha256-3w3ImvW4t/H2eMkZbUH+F1zkARSI3cIJSgJFg4ULPU4="
}
}
}
Then, add the following to MODULE.bazel
:
download_archives = use_repo_rule("@download_archives//download/archives:defs.bzl", "download_archives")
download_archives(
name = "wget_src",
index = "//third-party/wget:repo.json",
# NOTE:
# This is how you would add a custom patch for one of the versions. See
# "Patching" docs for more information about patches.
# patches = {
# "//third-party/wget/patches:0001-1.24.5-test-patch.patch": ">=1.24.5/*",
# },
)
To test the Bazel repo, run bazel fetch @wget_src
. This will attempt to
download and extract all the versions defined in the repo index from the
available sources.
And, to list all the targets in the repo, run bazel query @wget_src//...
.
📄 Docs
Please feel free to open issues and PRs, contributions are always welcome! See CONTRIBUTING.md for more info on how to work with this repo.