From 9ee2b08498083e1a23017ba586db6c508f8b71bd Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Sat, 2 Mar 2024 15:46:20 -0800 Subject: [PATCH] Publish binaries on releases (#292) Fixes #290 Fixes #289 --- ### Type of change - Bug fix (change which fixes an issue) ### Test plan - Covered by existing test cases - Manual testing; please provide instructions so we can reproduce: --- .github/workflows/ci.yaml | 7 +++ MODULE.bazel | 13 ++-- e2e/use_release/.bazelversion | 1 + e2e/use_release/BUILD.bazel | 6 ++ e2e/use_release/MODULE.bazel | 10 +++ e2e/use_release/README.md | 6 ++ e2e/use_release/WORKSPACE.bazel | 27 +++++++++ e2e/use_release/WORKSPACE.bzlmod | 1 + e2e/use_release/__main__.py | 1 + e2e/use_release/minimal_download_test.sh | 61 +++++++++++++++++++ py/extensions.bzl | 41 +++++++++++++ py/private/toolchain/BUILD.bazel | 10 +++ py/private/toolchain/repo.bzl | 77 ++++++++++++++++++++++++ py/private/toolchain/tools.bzl | 52 +++++----------- py/private/toolchain/types.bzl | 4 +- py/private/toolchain/unpack/BUILD.bazel | 7 +-- py/private/toolchain/venv/BUILD.bazel | 9 +-- py/repositories.bzl | 40 +++++++----- tools/integrity.bzl | 18 +++--- 19 files changed, 310 insertions(+), 81 deletions(-) create mode 120000 e2e/use_release/.bazelversion create mode 100644 e2e/use_release/BUILD.bazel create mode 100644 e2e/use_release/MODULE.bazel create mode 100644 e2e/use_release/README.md create mode 100644 e2e/use_release/WORKSPACE.bazel create mode 100644 e2e/use_release/WORKSPACE.bzlmod create mode 100644 e2e/use_release/__main__.py create mode 100755 e2e/use_release/minimal_download_test.sh create mode 100644 py/extensions.bzl create mode 100644 py/private/toolchain/repo.bzl diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index af6aa3c6..0e48ce9f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -35,3 +35,10 @@ jobs: steps: - uses: actions/checkout@v4 - run: patch --dry-run -p1 < .bcr/patches/*.patch + + test-release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - working-directory: e2e/use_release + run: ./minimal_download_test.sh diff --git a/MODULE.bazel b/MODULE.bazel index 842544e4..43a81619 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -13,14 +13,15 @@ bazel_dep(name = "bazel_skylib", version = "1.4.2") bazel_dep(name = "rules_python", version = "0.29.0") bazel_dep(name = "platforms", version = "0.0.7") -archive_override( - module_name = "rules_python", - urls = "https://github.com/bazelbuild/rules_python/archive/52381415be9d3618130f02a821aef50de1e3af09.tar.gz", - integrity = "sha256-pYfEFNWqygSEElDYgJsuIeDYn9oll/rZB0GcR+6rirA=", - strip_prefix = "rules_python-52381415be9d3618130f02a821aef50de1e3af09", -) +tools = use_extension("//py:extensions.bzl", "py_tools") +tools.rules_py_tools() +use_repo(tools, "rules_py_tools") register_toolchains( + "@rules_py_tools//:all", + + # Register the "from source" toolchains last, so there's no accidental dependency on Rust + # For manual testing: comment these out to force use of pre-built binaries. "@aspect_rules_py//py/private/toolchain/venv/...", "@aspect_rules_py//py/private/toolchain/unpack/...", ) diff --git a/e2e/use_release/.bazelversion b/e2e/use_release/.bazelversion new file mode 120000 index 00000000..96cf9496 --- /dev/null +++ b/e2e/use_release/.bazelversion @@ -0,0 +1 @@ +../../.bazelversion \ No newline at end of file diff --git a/e2e/use_release/BUILD.bazel b/e2e/use_release/BUILD.bazel new file mode 100644 index 00000000..493bfc45 --- /dev/null +++ b/e2e/use_release/BUILD.bazel @@ -0,0 +1,6 @@ +load("@aspect_rules_py//py:defs.bzl", "py_binary") + +py_binary( + name = "main", + srcs = ["__main__.py"], +) diff --git a/e2e/use_release/MODULE.bazel b/e2e/use_release/MODULE.bazel new file mode 100644 index 00000000..1c857b71 --- /dev/null +++ b/e2e/use_release/MODULE.bazel @@ -0,0 +1,10 @@ +bazel_dep(name = "aspect_rules_py", version = "0.7.0") + +local_path_override( + module_name = "aspect_rules_py", + path = "../..", +) + +tools = use_extension("@aspect_rules_py//py:extensions.bzl", "py_tools") +tools.rules_py_tools(is_prerelease = False) +use_repo(tools, "rules_py_tools") diff --git a/e2e/use_release/README.md b/e2e/use_release/README.md new file mode 100644 index 00000000..8273bce5 --- /dev/null +++ b/e2e/use_release/README.md @@ -0,0 +1,6 @@ +# Test releases + +This is currently a manual test we can perform _after_ publishing a release. + +It asserts that the release_prep.sh constructed a correct tarball of the ruleset (the "Bazel Module") +and that usage of a release has the correct minimal toolchain behaviors. diff --git a/e2e/use_release/WORKSPACE.bazel b/e2e/use_release/WORKSPACE.bazel new file mode 100644 index 00000000..99bf0460 --- /dev/null +++ b/e2e/use_release/WORKSPACE.bazel @@ -0,0 +1,27 @@ +# Override http_archive for local testing +local_repository( + name = "aspect_rules_py", + path = "../..", +) + +# Fetches the rules_py dependencies. +# If you want to have a different version of some dependency, +# you should fetch it *before* calling this. +# Alternatively, you can skip calling this function, so long as you've +# already fetched all the dependencies. +load("@aspect_rules_py//py:repositories.bzl", "rules_py_dependencies", "rules_py_toolchains") + +rules_py_dependencies(register_toolchains = False) + +# Force use of pre-built release binaries regardless of the content of /tools/version.bzl +rules_py_toolchains(is_prerelease = False) + +# "Installation" for rules_python +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +python_register_toolchains( + name = "python_toolchain", + python_version = "3.9", +) + +py_repositories() diff --git a/e2e/use_release/WORKSPACE.bzlmod b/e2e/use_release/WORKSPACE.bzlmod new file mode 100644 index 00000000..850eed39 --- /dev/null +++ b/e2e/use_release/WORKSPACE.bzlmod @@ -0,0 +1 @@ +# This file replaces WORKSPACE.bazel under --enable_bzlmod diff --git a/e2e/use_release/__main__.py b/e2e/use_release/__main__.py new file mode 100644 index 00000000..8cde7829 --- /dev/null +++ b/e2e/use_release/__main__.py @@ -0,0 +1 @@ +print("hello world") diff --git a/e2e/use_release/minimal_download_test.sh b/e2e/use_release/minimal_download_test.sh new file mode 100755 index 00000000..b5bd398c --- /dev/null +++ b/e2e/use_release/minimal_download_test.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +set -o errexit -o pipefail -o nounset + +OS="$(uname | tr '[:upper:]' '[:lower:]')" +ARCH="$(arch)" +ALLOWED="rules_py_tools.${OS}_${ARCH}" +if [ "$ARCH" == "x86_64" ]; then + ALLOWED="rules_py_tools.${OS}_amd64" +fi + +# This test references pre-built artifacts from a prior release. +# Will need to bump this version in the future when there are breaking changes. +export RULES_PY_RELEASE_VERSION=0.7.0 + +############# +# Test bzlmod +( + cd ../.. + patch -p1 < .bcr/patches/*.patch +) +OUTPUT_BASE=$(mktemp -d) +output=$(bazel "--output_base=$OUTPUT_BASE" run --enable_bzlmod //:main) +if [[ "$output" != "hello world" ]]; then + >&2 echo "ERROR: bazel command did not produce expected output" + exit 1 +fi +externals=$(ls $OUTPUT_BASE/external) + +if echo "$externals" | grep -v "${ALLOWED}" | grep -v ".marker" | grep rules_py_tools. +then + >&2 echo "ERROR: rules_py binaries were fetched for platform other than ${ALLOWED}" + exit 1 +fi +if echo "$externals" | grep rust +then + >&2 echo "ERROR: we fetched a rust repository" + exit 1 +fi + +############# +# Test WORKSPACE +OUTPUT_BASE=$(mktemp -d) +output=$(bazel "--output_base=$OUTPUT_BASE" run --noenable_bzlmod //:main) +if [[ "$output" != "hello world" ]]; then + >&2 echo "ERROR: bazel command did not produce expected output" + exit 1 +fi + +externals=$(ls $OUTPUT_BASE/external) + +if echo "$externals" | grep -v "${ALLOWED}" | grep -v ".marker" | grep rules_py_tools. +then + >&2 echo "ERROR: rules_py binaries were fetched for platform other than ${ALLOWED}" + exit 1 +fi +if echo "$externals" | grep rust +then + >&2 echo "ERROR: we fetched a rust repository" + exit 1 +fi diff --git a/py/extensions.bzl b/py/extensions.bzl new file mode 100644 index 00000000..0aca5b81 --- /dev/null +++ b/py/extensions.bzl @@ -0,0 +1,41 @@ +"Module Extensions used from MODULE.bazel" + +load(":repositories.bzl", "DEFAULT_TOOLS_REPOSITORY", "rules_py_toolchains") +load("//tools:version.bzl", "IS_PRERELEASE") + +py_toolchain = tag_class(attrs = { + "name": attr.string(doc = """\ +Base name for generated repositories, allowing more than one toolchain to be registered. +Overriding the default is only permitted in the root module. +""", default = DEFAULT_TOOLS_REPOSITORY), + "is_prerelease": attr.bool( + doc = "True iff there are no pre-built tool binaries for this version of rules_py", + default = IS_PRERELEASE, + ), +}) + +def _toolchains_extension_impl(module_ctx): + registrations = [] + root_name = None + for mod in module_ctx.modules: + for toolchain in mod.tags.rules_py_tools: + if toolchain.name != DEFAULT_TOOLS_REPOSITORY and not mod.is_root: + fail("""\ + Only the root module may override the default name for the rules_py_tools toolchain. + This prevents conflicting registrations in the global namespace of external repos. + """) + + # Ensure the root wins in case of differences + if mod.is_root: + rules_py_toolchains(toolchain.name, register = False, is_prerelease = toolchain.is_prerelease) + root_name = toolchain.name + else: + registrations.append(toolchain.name) + for name in registrations: + if name != root_name: + rules_py_toolchains(name, register = False) + +py_tools = module_extension( + implementation = _toolchains_extension_impl, + tag_classes = {"rules_py_tools": py_toolchain}, +) diff --git a/py/private/toolchain/BUILD.bazel b/py/private/toolchain/BUILD.bazel index 7fb7a62b..12d26330 100644 --- a/py/private/toolchain/BUILD.bazel +++ b/py/private/toolchain/BUILD.bazel @@ -5,6 +5,16 @@ exports_files( visibility = ["//visibility:public"], ) +toolchain_type( + name = "unpack_toolchain_type", + visibility = ["//visibility:public"], +) + +toolchain_type( + name = "venv_toolchain_type", + visibility = ["//visibility:public"], +) + bzl_library( name = "autodetecting", srcs = ["autodetecting.bzl"], diff --git a/py/private/toolchain/repo.bzl b/py/private/toolchain/repo.bzl new file mode 100644 index 00000000..61296f92 --- /dev/null +++ b/py/private/toolchain/repo.bzl @@ -0,0 +1,77 @@ +"""Create a repository to hold the toolchains + +This follows guidance here: +https://docs.bazel.build/versions/main/skylark/deploying.html#registering-toolchains +" +Note that in order to resolve toolchains in the analysis phase +Bazel needs to analyze all toolchain targets that are registered. +Bazel will not need to analyze all targets referenced by toolchain.toolchain attribute. +If in order to register toolchains you need to perform complex computation in the repository, +consider splitting the repository with toolchain targets +from the repository with _toolchain targets. +Former will be always fetched, +and the latter will only be fetched when user actually needs to build code. +" +The "complex computation" in our case is simply downloading our pre-built rust binaries. +This guidance tells us how to avoid that: we put the toolchain targets in the alias repository +with only the toolchain attribute pointing into the platform-specific repositories. +""" + +load("//py/private/toolchain:tools.bzl", "RUST_BIN_CFG", "TOOLCHAIN_PLATFORMS") + +def _toolchains_repo_impl(repository_ctx): + build_content = """# Generated by toolchains_repo.bzl +# +# These can be registered in the workspace file or passed to --extra_toolchains flag. +# By default all these toolchains are registered by the py_register_toolchains macro +# so you don't normally need to interact with these targets. + +""" + for tool, cfg in RUST_BIN_CFG.items(): + for [platform, meta] in TOOLCHAIN_PLATFORMS.items(): + build_content += """ +# Declare a toolchain Bazel will select for running {tool} on the {cfg} platform. +toolchain( + name = "{tool}_{platform}_toolchain", + {cfg}_compatible_with = {compatible_with}, + # Bazel does not follow this attribute during analysis, so the referenced repo + # will only be fetched if this toolchain is selected. + toolchain = "@{user_repository_name}.{platform}//:{tool}_toolchain", + toolchain_type = "@aspect_rules_py//py/private/toolchain:{tool}_toolchain_type", +) +""".format( + cfg = cfg, + tool = tool, + platform = platform, + user_repository_name = repository_ctx.attr.user_repository_name, + compatible_with = meta.compatible_with, + ) + + # Base BUILD file for this repository + repository_ctx.file("BUILD.bazel", build_content) + +toolchains_repo = repository_rule( + _toolchains_repo_impl, + doc = """\ + Creates a single repository with toolchain definitions for all known platforms + that can be registered or selected. + """, + attrs = { + "user_repository_name": attr.string(mandatory = True, doc = """\ + What the user chose for the base name. + Needed since bzlmod apparent name has extra tilde segments. + """), + }, +) + +def _prerelease_toolchains_repo_impl(repository_ctx): + repository_ctx.file("BUILD.bazel", "# No toolchains created for pre-releases") + +prerelease_toolchains_repo = repository_rule( + _prerelease_toolchains_repo_impl, + doc = """Create a repo with an empty BUILD file, which registers no toolchains. + This is used for pre-releases, which have no pre-built binaries, but still want to call + register_toolchains("@this_repo//:all") + By doing this, we can avoid those register_toolchains callsites needing to be conditional on IS_PRERELEASE + """, +) diff --git a/py/private/toolchain/tools.bzl b/py/private/toolchain/tools.bzl index 69ba45cc..4624f1a7 100644 --- a/py/private/toolchain/tools.bzl +++ b/py/private/toolchain/tools.bzl @@ -1,10 +1,13 @@ -"""Utilities for making toolchains""" +"""Declaration of concrete toolchains for our Rust tools""" + load("//tools:integrity.bzl", "RELEASED_BINARY_INTEGRITY") load("//tools:version.bzl", "VERSION") # The expected config for each tool, whether it runs in an action or at runtime RUST_BIN_CFG = { + # unpack wheels happens inside an action "unpack": "exec", + # creating the virtualenv happens when the binary is running "venv": "target", } @@ -100,13 +103,14 @@ def source_toolchain(name, toolchain_type, bin): toolchain_type = toolchain_type, ) -def _tool_repo_impl(rctx): +def _prebuilt_tool_repo_impl(rctx): build_content = """\ # Generated by @aspect_rules_py//py/private/toolchain:tools.bzl load("@aspect_rules_py//py/private/toolchain:tools.bzl", "py_tool_toolchain") package(default_visibility = ["//visibility:public"]) """ + # For manual testing, override these environment variables # TODO: use rctx.getenv when available, see https://github.com/bazelbuild/bazel/pull/20944 release_fork = "aspect-build" @@ -125,7 +129,7 @@ package(default_visibility = ["//visibility:public"]) url = "https://github.com/{}/rules_py/releases/download/v{}/{}".format( release_fork, release_version, - filename + filename, ) rctx.download( url = url, @@ -133,43 +137,17 @@ package(default_visibility = ["//visibility:public"]) executable = True, output = tool, ) - build_content += """\ -py_tool_toolchain(name = "concrete_{tool}_toolchain", bin = "{tool}", template_var = "{tool_upper}_BIN") - -toolchain( - name = "{tool}_toolchain", - {cfg}_compatible_with = {compatible_with}, - toolchain = "concrete_{tool}_toolchain", - toolchain_type = "@aspect_rules_py//py/private/toolchain/{tool}:toolchain_type", -) -""".format( - cfg = cfg, - compatible_with = TOOLCHAIN_PLATFORMS[rctx.attr.platform].compatible_with, - tool = tool, - tool_upper = tool.upper(), -) + build_content += """py_tool_toolchain(name = "{tool}_toolchain", bin = "{tool}", template_var = "{tool_upper}_BIN")\n""".format( + tool = tool, + tool_upper = tool.upper(), + ) rctx.file("BUILD.bazel", build_content) -_tool_repo = repository_rule( - doc = "Download pre-built binary tools and create toolchains for them", - implementation = _tool_repo_impl, +prebuilt_tool_repo = repository_rule( + doc = "Download pre-built binary tools and create concrete toolchains for them", + implementation = _prebuilt_tool_repo_impl, attrs = { "platform": attr.string(mandatory = True, values = TOOLCHAIN_PLATFORMS.keys()), - } + }, ) - -def binary_tool_repos(name): - """Create a downloaded toolchain for every tool under every supported platform. - - Args: - name: prefix used in created repositories - Returns: - list of toolchain targets to register - """ - result = [] - for platform in TOOLCHAIN_PLATFORMS.keys(): - plat_repo_name = ".".join([name, platform]) - result.append("@{}//:all".format(plat_repo_name)) - _tool_repo(name = plat_repo_name, platform = platform) - return result diff --git a/py/private/toolchain/types.bzl b/py/private/toolchain/types.bzl index 9e6a2b44..bc8992ee 100644 --- a/py/private/toolchain/types.bzl +++ b/py/private/toolchain/types.bzl @@ -4,5 +4,5 @@ PY_TOOLCHAIN = "@bazel_tools//tools/python:toolchain_type" SH_TOOLCHAIN = "@bazel_tools//tools/sh:toolchain_type" # Toolchain type for the virtual env creation tools. -VENV_TOOLCHAIN = "@aspect_rules_py//py/private/toolchain/venv:toolchain_type" -UNPACK_TOOLCHAIN = "@aspect_rules_py//py/private/toolchain/unpack:toolchain_type" +VENV_TOOLCHAIN = "@aspect_rules_py//py/private/toolchain:venv_toolchain_type" +UNPACK_TOOLCHAIN = "@aspect_rules_py//py/private/toolchain:unpack_toolchain_type" diff --git a/py/private/toolchain/unpack/BUILD.bazel b/py/private/toolchain/unpack/BUILD.bazel index 3efb2688..d7ad9ec2 100644 --- a/py/private/toolchain/unpack/BUILD.bazel +++ b/py/private/toolchain/unpack/BUILD.bazel @@ -1,12 +1,7 @@ load("//py/private/toolchain:tools.bzl", "source_toolchain") -toolchain_type( - name = "toolchain_type", - visibility = ["//visibility:public"], -) - source_toolchain( name = "unpack", - toolchain_type = ":toolchain_type", bin = "//py/tools/unpack_bin", + toolchain_type = "//py/private/toolchain:unpack_toolchain_type", ) diff --git a/py/private/toolchain/venv/BUILD.bazel b/py/private/toolchain/venv/BUILD.bazel index a407433c..c1e28807 100644 --- a/py/private/toolchain/venv/BUILD.bazel +++ b/py/private/toolchain/venv/BUILD.bazel @@ -1,16 +1,11 @@ load("//py/private/toolchain:tools.bzl", "source_toolchain") -toolchain_type( - name = "toolchain_type", - visibility = ["//visibility:public"], -) - source_toolchain( name = "venv", + bin = "//py/tools/venv_bin", # When running from source, we assume the target is the exec platform. # TODO: when we have cross-compile Mac -> Linux, pre-release users should be able to # build a py_image on their Mac and have the linux venv rust_binary end up in the container. # cfg = "target", - toolchain_type = ":toolchain_type", - bin = "//py/tools/venv_bin", + toolchain_type = "//py/private/toolchain:venv_toolchain_type", ) diff --git a/py/repositories.bzl b/py/repositories.bzl index 297f6fa4..09dadc23 100644 --- a/py/repositories.bzl +++ b/py/repositories.bzl @@ -7,7 +7,8 @@ See https://docs.bazel.build/versions/main/skylark/deploying.html#dependencies load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load("//py/private/toolchain:autodetecting.bzl", _register_autodetecting_python_toolchain = "register_autodetecting_python_toolchain") -load("//py/private/toolchain:tools.bzl", "binary_tool_repos") +load("//py/private/toolchain:tools.bzl", "TOOLCHAIN_PLATFORMS", "prebuilt_tool_repo") +load("//py/private/toolchain:repo.bzl", "prerelease_toolchains_repo", "toolchains_repo") load("//tools:version.bzl", "IS_PRERELEASE") def http_archive(name, **kwargs): @@ -15,6 +16,8 @@ def http_archive(name, **kwargs): register_autodetecting_python_toolchain = _register_autodetecting_python_toolchain +DEFAULT_TOOLS_REPOSITORY = "rules_py_tools" + # WARNING: any changes in this function may be BREAKING CHANGES for users # because we'll fetch a dependency which may be different from one that # they were previously fetching later in their WORKSPACE setup, and now @@ -23,13 +26,11 @@ register_autodetecting_python_toolchain = _register_autodetecting_python_toolcha # and released only in semver majors. # buildifier: disable=unnamed-macro -def rules_py_dependencies(name = "rules_py_tools", register = True, prerelease = IS_PRERELEASE): +def rules_py_dependencies(register_toolchains = True): """Fetch rules_py's dependencies Args: - name: prefix for generated repositories - register: whether to register the toolchains created, should be false under bzlmod - prerelease: whether to build rust tools from source, rather than download pre-built binaries + register_toolchains: whether to also do default toolchain registration """ # The minimal version of bazel_skylib we require @@ -53,18 +54,29 @@ def rules_py_dependencies(name = "rules_py_tools", register = True, prerelease = strip_prefix = "rules_python-0.31.0", url = "https://github.com/bazelbuild/rules_python/releases/download/0.31.0/rules_python-0.31.0.tar.gz", ) - - # When running from a release version: - # Fetch remote tools from the release and create toolchain for them - if prerelease: + + if register_toolchains: + rules_py_toolchains() + +def rules_py_toolchains(name = DEFAULT_TOOLS_REPOSITORY, register = True, is_prerelease = IS_PRERELEASE): + """Create a downloaded toolchain for every tool under every supported platform. + + Args: + name: prefix used in created repositories + register: whether to call the register_toolchains, should be True for WORKSPACE and False for bzlmod. + is_prerelease: True iff there are no pre-built tool binaries for this version of rules_py + """ + if is_prerelease: + prerelease_toolchains_repo(name = name) if register: native.register_toolchains( "@aspect_rules_py//py/private/toolchain/venv/...", "@aspect_rules_py//py/private/toolchain/unpack/...", ) - return + else: + for platform in TOOLCHAIN_PLATFORMS.keys(): + prebuilt_tool_repo(name = ".".join([name, platform]), platform = platform) + toolchains_repo(name = name, user_repository_name = name) - toolchains = binary_tool_repos(name) - if register: - native.register_toolchains(*toolchains) - \ No newline at end of file + if register: + native.register_toolchains("@{}//:all".format(name)) diff --git a/tools/integrity.bzl b/tools/integrity.bzl index 54b6b9a6..baafe3c5 100644 --- a/tools/integrity.bzl +++ b/tools/integrity.bzl @@ -4,14 +4,14 @@ This file contents are entirely replaced during release publishing. The checked in content is only here to allow load() statements in the sources to resolve. """ -# FROM https://github.com/alexeagle/rules_py/releases/tag/v0.101.0 +# TEST DATA extracted from https://github.com/aspect-build/rules_py/releases/download/v0.7.0/rules_py-v0.7.0.tar.gz RELEASED_BINARY_INTEGRITY = { - "unpack-aarch64-apple-darwin": "5199cb98d59535ba8609c4a538be99d8759e971ab9d1e680d932091529860868", - "unpack-x86_64-apple-darwin": "23d0eb9ec09609c00d65779234f1210506eba1bf64090a01cef71d5175e3e6b6", - "venv-aarch64-apple-darwin": "e02b478358641abf72ca5192948101e18a3dabccb48e7ee704759ad39c2f718a", - "venv-x86_64-apple-darwin": "13d0c08a23b1064489df522d2327cfbaf0058b9364ca2ffee51b5b6f06a6930e", - "unpack-aarch64-unknown-linux-gnu": "48552e399a1f2ab97e62ca7fce5783b6214e284330c7555383f43acf82446636", - "unpack-x86_64-unknown-linux-gnu": "fd265552bfd236efef519f81ce783322a50d8d7ab5af5d08a713e519cedff87f", - "venv-aarch64-unknown-linux-gnu": "b05d6cbe485e8ed1872f330012929126778744208e47485d7e2be285a027c7ca", - "venv-x86_64-unknown-linux-gnu": "61f53fe45da5f2f160907c87c1a2d663bc57eee667520a46490a837825be61c9" + "unpack-aarch64-apple-darwin": "440ee3f7c06f1db301947ad4abaa5fd7c06c112e22976e863ad9732e410b31bb", + "unpack-x86_64-apple-darwin": "1afe12536a851e9a568bf280fa25e406ae7c58339e655e22636423a3da3cf28a", + "venv-aarch64-apple-darwin": "2c49ddbb814dc926c2250da4edd968c7c47ce140ded62cd6cd7c4bf2ff3fe254", + "venv-x86_64-apple-darwin": "65ee78ad30dfab4b7bac95476f9fa0524304a7b155c83e34a026b07acc28a087", + "unpack-aarch64-unknown-linux-gnu": "48552e399a1f2ab97e62ca7fce5783b6214e284330c7555383f43acf82446636", + "unpack-x86_64-unknown-linux-gnu": "fd265552bfd236efef519f81ce783322a50d8d7ab5af5d08a713e519cedff87f", + "venv-aarch64-unknown-linux-gnu": "b05d6cbe485e8ed1872f330012929126778744208e47485d7e2be285a027c7ca", + "venv-x86_64-unknown-linux-gnu": "61f53fe45da5f2f160907c87c1a2d663bc57eee667520a46490a837825be61c9", }