From e2195b112048056e08b90593788d69b31bb9e1b9 Mon Sep 17 00:00:00 2001 From: Martin Kuntz Jacobsen Date: Mon, 9 Nov 2026 17:33:40 +0100 Subject: [PATCH] starlark: pins.json and dx_pins extension; ruby and powershell move onto it (part of #10144) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Xut2hwESun1HL2eSVd1d5B --- MODULE.bazel | 40 ++++++--- libs/starlark/BUILD.bazel | 5 ++ libs/starlark/pins_tests.bzl | 33 +++++++ libs/starlark/tests/cells_tests.bzl | 7 +- libs/starlark/toolchain.bzl | 113 ++++++++++++++++++++++-- powershell/toolchain/BUILD.bazel | 6 +- powershell/toolchain/extensions.bzl | 15 ++-- powershell/toolchain/metadata_tests.bzl | 20 ++--- powershell/toolchain/pins.bzl | 50 ----------- powershell/toolchain/pins.json | 51 +++++++++++ powershell/toolchain/pwsh.build | 16 ++++ powershell/toolchain/repos.bzl | 61 ------------- ruby/toolchain/BUILD.bazel | 4 +- ruby/toolchain/metadata_tests.bzl | 14 ++- ruby/toolchain/pins.bzl | 34 ------- ruby/toolchain/pins.json | 41 +++++++++ ruby/toolchain/repos.bzl | 56 ++---------- ruby/toolchain/sorbet.build | 3 + 18 files changed, 316 insertions(+), 253 deletions(-) create mode 100644 libs/starlark/pins_tests.bzl delete mode 100644 powershell/toolchain/pins.bzl create mode 100644 powershell/toolchain/pins.json create mode 100644 powershell/toolchain/pwsh.build delete mode 100644 powershell/toolchain/repos.bzl delete mode 100644 ruby/toolchain/pins.bzl create mode 100644 ruby/toolchain/pins.json create mode 100644 ruby/toolchain/sorbet.build diff --git a/MODULE.bazel b/MODULE.bazel index 94cc10c849..b41fe547e6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -824,7 +824,33 @@ ruby_coverage = use_extension("//ruby/coverage:repos.bzl", "ruby_coverage") use_repo(ruby_coverage, "dx_ruby_bench_gems", "dx_ruby_coverage_gems") ruby_tools = use_extension("//ruby/toolchain:repos.bzl", "ruby_tools") -use_repo(ruby_tools, "dx_sorbet", "rules_ruby") +use_repo(ruby_tools, "rules_ruby") + +dx_pins = use_extension("//libs/starlark:toolchain.bzl", "dx_pins") +dx_pins.pin( + name = "dx_sorbet", + aliases = {"windows_arm64": "windows_x86_64"}, + build = "//ruby/toolchain:sorbet.build", + pins = "//ruby/toolchain:pins.json", +) +dx_pins.pin( + name = "dx_powershell_toolchains", + build = "//powershell/toolchain:pwsh.build", + pins = "//powershell/toolchain:pins.json", + toolchain_type = "//powershell/toolchain/type:toolchain_type", +) +use_repo( + dx_pins, + "dx_powershell_toolchains", + "dx_powershell_toolchains__linux_arm64", + "dx_powershell_toolchains__linux_x86_64", + "dx_powershell_toolchains__macos_arm64", + "dx_powershell_toolchains__macos_x86_64", + "dx_powershell_toolchains__windows_arm64", + "dx_powershell_toolchains__windows_x86_64", + "dx_pins_data", + "dx_sorbet", +) # The pinned Ruby is declared in families/ruby; deploy tests read its files. ruby = use_extension("//ruby:extensions.bzl", "ruby") @@ -1183,17 +1209,7 @@ use_repo(elixir, "dx_benchee", "dx_credo", "dx_elixir", "rules_elixir") bazel_dep(name = "rules_batch", version = "0.1.1") powershell = use_extension("//powershell/toolchain:extensions.bzl", "powershell") -use_repo( - powershell, - "dx_powershell_toolchains", - "dx_powershell_toolchains__linux_arm64", - "dx_powershell_toolchains__linux_x86_64", - "dx_powershell_toolchains__macos_arm64", - "dx_powershell_toolchains__macos_x86_64", - "dx_powershell_toolchains__windows_arm64", - "dx_powershell_toolchains__windows_x86_64", - "rules_powershell", -) +use_repo(powershell, "rules_powershell") ocaml = use_extension("//ocaml/toolchain:extensions.bzl", "ocaml") ocaml.lock( diff --git a/libs/starlark/BUILD.bazel b/libs/starlark/BUILD.bazel index f630b79c63..c690dae2a0 100644 --- a/libs/starlark/BUILD.bazel +++ b/libs/starlark/BUILD.bazel @@ -1,5 +1,6 @@ load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") load("//quality:fixtures.bzl", "real_source_target") +load(":pins_tests.bzl", "pins_tests") load(":platform.bzl", "platform_probe") bool_flag( @@ -26,6 +27,7 @@ exports_files([ "node_test.bzl", "packaging.bzl", "plan_shard.bzl", + "pins_tests.bzl", "platform.bzl", "repo.bzl", "resources.bzl", @@ -55,6 +57,7 @@ real_source_target( "jammy_runtime.bzl", "msvc_crt.bzl", "packaging.bzl", + "pins_tests.bzl", "plan_shard.bzl", "platform.bzl", "repo.bzl", @@ -72,6 +75,8 @@ real_source_target( visibility = ["//tools/ci:__pkg__"], ) +pins_tests(name = "pins_test") + platform_probe( name = "platform_probe", visibility = ["//visibility:public"], diff --git a/libs/starlark/pins_tests.bzl b/libs/starlark/pins_tests.bzl new file mode 100644 index 0000000000..7d05d9a0ee --- /dev/null +++ b/libs/starlark/pins_tests.bzl @@ -0,0 +1,33 @@ +"""The checks every pins.json shares.""" + +load("@dx_pins_data//:pins.bzl", "PINS") +load(":defs.bzl", "expect_true", "starlark_test") +load(":toolchain.bzl", "pin_checks") + +def _archive(pin): + return struct( + archive = pin["urls"][0].rpartition("/")[2], + sha256 = pin["sha256"], + urls = pin["urls"], + ) + +def _checks(): + checks = [expect_true("pins are read", len(PINS) > 0)] + for name, pins in PINS.items(): + cells = {cell: _archive(pin) for cell, pin in pins["cells"].items() if "urls" in pin} + checks += [ + expect_true(name + " has cells", len(cells) > 0), + expect_true(name + " binaries are set", all([pin["binary"] != "" for pin in pins["cells"].values()])), + ] + [ + check + for check in pin_checks(cells, pins["version"]) + ] + return checks + +def pins_tests(name): + """Declares the test that runs pin_checks over every pins.json.""" + starlark_test( + name = name, + mode = "load", + checks = _checks(), + ) diff --git a/libs/starlark/tests/cells_tests.bzl b/libs/starlark/tests/cells_tests.bzl index 3fba193d78..a4f95f4e94 100644 --- a/libs/starlark/tests/cells_tests.bzl +++ b/libs/starlark/tests/cells_tests.bzl @@ -1,5 +1,6 @@ """Shared cell setting tests.""" +load("@dx_pins_data//:pins.bzl", "PINS") load("//d/toolchain:pins.bzl", "LDC_CELLS") load("//erlang/toolchain:pins.bzl", erlang_cells = "CELLS") load("//fortran/toolchain:pins.bzl", "FORTRAN_CELLS") @@ -10,9 +11,7 @@ load("//lua/toolchain:pins.bzl", "LUALS_CELLS") load("//modules:cuda.bzl", "CUDA_CELLS") load("//ocaml/toolchain:pins.bzl", "OCAML_CELLS") load("//php/toolchain:pins.bzl", "PHP_CELLS") -load("//powershell/toolchain:pins.bzl", "PWSH_CELLS") load("//qt/sdk:pins.bzl", qt_cells = "CELLS") -load("//ruby/toolchain:pins.bzl", "SORBET_CELLS") _DEFAULT = "//conditions:default" @@ -29,9 +28,9 @@ _ALL_CELLS = { "lua": LUALS_CELLS, "ocaml": OCAML_CELLS, "php": PHP_CELLS, - "powershell": PWSH_CELLS, + "powershell": PINS["dx_powershell_toolchains"]["cells"], "qt": qt_cells, - "ruby": SORBET_CELLS, + "ruby": PINS["dx_sorbet"]["cells"], } _OSES = ["linux", "macos", "windows"] diff --git a/libs/starlark/toolchain.bzl b/libs/starlark/toolchain.bzl index 33e2777929..b57370aac8 100644 --- a/libs/starlark/toolchain.bzl +++ b/libs/starlark/toolchain.bzl @@ -2,6 +2,7 @@ load(":defs.bzl", "expect_equal", "expect_true") load(":host.bzl", "host_cell") +load(":repo.bzl", "gem_extract", "hub_repo") _HOST_CELLS = [ "linux_arm64", @@ -12,18 +13,35 @@ _HOST_CELLS = [ "windows_x86_64", ] +def _fetch(rctx, tool, pin, build): + binary = pin["binary"] + if "stub" in pin: + rctx.file(binary, pin["stub"], executable = True) + elif pin.get("type") == "gem": + gem_extract( + rctx, + url = pin["urls"], + sha256 = pin["sha256"], + canonical_id = "dx-gem:" + pin["urls"][0], + output = ".", + required = [binary], + ) + else: + rctx.download_and_extract(url = pin["urls"], sha256 = pin["sha256"], stripPrefix = pin.get("strip_prefix", "")) + if not rctx.path(binary).exists: + fail("{} archive {} has no {}".format(tool, pin["urls"][0], binary)) + if pin.get("executable"): + rctx.file(binary, rctx.read(binary), executable = True) + rctx.file("REPO.bazel", "") + rctx.file("BUILD.bazel", build.replace("{binary}", binary)) + return rctx.repo_metadata(reproducible = True) + def _host_archive_impl(rctx): cell = rctx.attr.aliases.get(host_cell(rctx), host_cell(rctx)) - cells = json.decode(rctx.attr.cells) - pin = cells.get(cell) + pin = json.decode(rctx.attr.cells).get(cell) if pin == None: fail("no pinned {} archive for {}".format(rctx.attr.tool, cell)) - rctx.download_and_extract(url = pin["urls"], sha256 = pin["sha256"], stripPrefix = pin.get("strip_prefix", "")) - if not rctx.path(pin["binary"]).exists: - fail("{} archive {} has no {}".format(rctx.attr.tool, pin["urls"][0], pin["binary"])) - rctx.file("REPO.bazel", "") - rctx.file("BUILD.bazel", rctx.attr.build.replace("{binary}", pin["binary"])) - return rctx.repo_metadata(reproducible = True) + return _fetch(rctx, rctx.attr.tool, pin, rctx.attr.build) _host_archive = repository_rule( implementation = _host_archive_impl, @@ -36,6 +54,19 @@ _host_archive = repository_rule( }, ) +def _cell_archive_impl(rctx): + return _fetch(rctx, rctx.attr.tool, json.decode(rctx.attr.pin), rctx.attr.build) + +_cell_archive = repository_rule( + implementation = _cell_archive_impl, + doc = "Downloads the pinned archive of one cell and writes its BUILD file.", + attrs = { + "build": attr.string(mandatory = True, doc = "BUILD file content; {binary} is replaced by the cell's binary path."), + "pin": attr.string(mandatory = True, doc = "JSON object of the cell's urls, sha256, binary and optional strip_prefix."), + "tool": attr.string(mandatory = True, doc = "Tool name used in failure messages."), + }, +) + def host_archive(name, tool, cells, build, aliases = {}): """Declares a repository holding the pinned archive of the host cell. @@ -110,3 +141,69 @@ def hub_checks(hub, toolchain_type, count, forbidden = []): expect_true("hub names the toolchain type", toolchain_type in hub), expect_equal("hub toolchain count", hub.count("toolchain("), count), ] + [expect_true("hub does not name " + repo, repo not in hub) for repo in forbidden] + +_OS_CONSTRAINTS = {"linux": "@platforms//os:linux", "macos": "@platforms//os:macos", "windows": "@platforms//os:windows"} + +_CPU_CONSTRAINTS = {"arm64": "@platforms//cpu:aarch64", "x86_64": "@platforms//cpu:x86_64"} + +def cell_repo(name, cell): + """Returns the name of the repository holding one cell of a pin.""" + return name + "__" + cell + +def pins_hub(name, cells, toolchain_type): + """Returns the hub BUILD file of a pin: one toolchain() per cell. + + Args: + name: Pin name. + cells: Cell names. + toolchain_type: Label string of the toolchain type. + """ + return "\n".join([ + toolchain_target( + name = cell_repo(name, cell), + exec_compatible_with = [_OS_CONSTRAINTS[cell.partition("_")[0]], _CPU_CONSTRAINTS[cell.partition("_")[2]]], + toolchain = "@{}//:toolchain".format(cell_repo(name, cell)), + toolchain_type = toolchain_type, + visibility = ["//visibility:public"], + ) + for cell in sorted(cells) + ]) + +def _dx_pins_impl(mctx): + data = {} + for mod in mctx.modules: + for tag in mod.tags.pin: + pins = json.decode(mctx.read(tag.pins)) + build = mctx.read(tag.build) + data[tag.name] = pins + if tag.toolchain_type == None: + _host_archive( + name = tag.name, + aliases = tag.aliases, + build = build, + cells = json.encode(pins["cells"]), + tool = tag.name, + ) + continue + for cell, pin in pins["cells"].items(): + _cell_archive(name = cell_repo(tag.name, cell), build = build, pin = json.encode(pin), tool = tag.name) + hub_repo(name = tag.name, files = {"BUILD.bazel": pins_hub(tag.name, pins["cells"].keys(), str(tag.toolchain_type))}) + hub_repo(name = "dx_pins_data", files = {"BUILD.bazel": "", "pins.bzl": "PINS = " + repr(data) + "\n"}) + return mctx.extension_metadata(reproducible = True) + +dx_pins = module_extension( + implementation = _dx_pins_impl, + doc = "Creates the repositories of every pins.json: one per cell and a toolchain hub, or one host-selected repository.", + tag_classes = { + "pin": tag_class( + doc = "One pins.json. With a toolchain_type it makes a repository per cell and a hub of toolchain() targets; without, one repository of the host cell.", + attrs = { + "aliases": attr.string_dict(doc = "Host cell to the pinned cell that serves it."), + "build": attr.label(mandatory = True, allow_single_file = True, doc = "BUILD file template; {binary} is replaced by the cell's binary path."), + "name": attr.string(mandatory = True, doc = "Hub, or sole, repository name."), + "pins": attr.label(mandatory = True, allow_single_file = True, doc = "JSON file of version and cells."), + "toolchain_type": attr.label(doc = "Toolchain type the hub registers; unset for a host-selected repository."), + }, + ), + }, +) diff --git a/powershell/toolchain/BUILD.bazel b/powershell/toolchain/BUILD.bazel index b2b387770b..7717498131 100644 --- a/powershell/toolchain/BUILD.bazel +++ b/powershell/toolchain/BUILD.bazel @@ -7,8 +7,8 @@ exports_files([ "extensions.bzl", "gallery.bzl", "metadata_tests.bzl", - "pins.bzl", - "repos.bzl", + "pins.json", + "pwsh.build", ]) powershell_metadata_tests(name = "metadata") @@ -20,8 +20,6 @@ real_source_target( "extensions.bzl", "gallery.bzl", "metadata_tests.bzl", - "pins.bzl", - "repos.bzl", ], tags = ["corpus"], ) diff --git a/powershell/toolchain/extensions.bzl b/powershell/toolchain/extensions.bzl index 4e0502f8f4..4b6b4d3d63 100644 --- a/powershell/toolchain/extensions.bzl +++ b/powershell/toolchain/extensions.bzl @@ -1,22 +1,19 @@ """The powershell module extension.""" -load("//libs/starlark:repo.bzl", "hub_repo", "pinned_archive") -load(":pins.bzl", "PWSH_CELLS", "RULES_POWERSHELL_SHA256", "RULES_POWERSHELL_URL") -load(":repos.bzl", "HUB_NAME", "hub_build", "pwsh_repo", "repo_name") +load("//libs/starlark:repo.bzl", "pinned_archive") + +_VERSION = "0.3.1" def _powershell_impl(mctx): pinned_archive( name = "rules_powershell", patches = [Label("//patches/rules_powershell:toolchain_type_alias.patch")], - sha256 = RULES_POWERSHELL_SHA256, - urls = [RULES_POWERSHELL_URL], + sha256 = "8ef875aa1dad8dc0f8f568547d2283f3d4b686b8e50374d6cdda4c5688fe6b7f", + urls = ["https://github.com/periareon/rules_powershell/releases/download/{0}/rules_powershell-{0}.tar.gz".format(_VERSION)], ) - for cell in sorted(PWSH_CELLS.keys()): - pwsh_repo(name = repo_name(cell), cell = cell) - hub_repo(name = HUB_NAME, files = {"BUILD.bazel": hub_build()}) return mctx.extension_metadata(reproducible = True) powershell = module_extension( implementation = _powershell_impl, - doc = "Creates rules_powershell, the pinned PowerShell builds and the toolchain hub.", + doc = "Creates the patched rules_powershell.", ) diff --git a/powershell/toolchain/metadata_tests.bzl b/powershell/toolchain/metadata_tests.bzl index cb576b9a12..8b40fbe4e4 100644 --- a/powershell/toolchain/metadata_tests.bzl +++ b/powershell/toolchain/metadata_tests.bzl @@ -1,17 +1,15 @@ -"""PowerShell toolchain pin and hub tests.""" +"""PowerShell toolchain hub tests.""" -load("//libs/starlark:defs.bzl", "expect_contains", "expect_equal", "expect_true", "starlark_test") -load("//libs/starlark:toolchain.bzl", "hub_checks") -load(":pins.bzl", "PWSH_CELLS", "PWSH_VERSION", "RULES_POWERSHELL_SHA256") -load(":repos.bzl", "hub_build", "repo_name") +load("@dx_pins_data//:pins.bzl", "PINS") +load("//libs/starlark:defs.bzl", "expect_contains", "expect_equal", "starlark_test") +load("//libs/starlark:toolchain.bzl", "cell_repo", "hub_checks", "pins_hub") def _checks(): - hub = hub_build() - return hub_checks(hub, "//powershell/toolchain/type:toolchain_type", len(PWSH_CELLS), ["@rules_powershell"]) + [ - expect_true("pwsh digests are sha256", all([len(c.sha256) == 64 for c in PWSH_CELLS.values()])), - expect_true("artifacts name the version", all([PWSH_VERSION in c.artifact for c in PWSH_CELLS.values()])), - expect_equal("rules_powershell digest", len(RULES_POWERSHELL_SHA256), 64), - expect_contains("hub names each platform repo", hub, "@" + repo_name("linux_x86_64") + "//:toolchain"), + cells = PINS["dx_powershell_toolchains"]["cells"].keys() + hub = pins_hub("dx_powershell_toolchains", cells, "//powershell/toolchain/type:toolchain_type") + return hub_checks(hub, "//powershell/toolchain/type:toolchain_type", len(cells), ["@rules_powershell"]) + [ + expect_equal("cells are the six host cells", len(cells), 6), + expect_contains("hub names each platform repo", hub, "@" + cell_repo("dx_powershell_toolchains", "linux_x86_64") + "//:toolchain"), ] def powershell_metadata_tests(name): diff --git a/powershell/toolchain/pins.bzl b/powershell/toolchain/pins.bzl deleted file mode 100644 index 1f769fc1dd..0000000000 --- a/powershell/toolchain/pins.bzl +++ /dev/null @@ -1,50 +0,0 @@ -"""Pinned rules_powershell archive and PowerShell 7.5.13 builds.""" - -PWSH_VERSION = "7.5.13" - -RULES_POWERSHELL_VERSION = "0.3.1" - -RULES_POWERSHELL_SHA256 = "8ef875aa1dad8dc0f8f568547d2283f3d4b686b8e50374d6cdda4c5688fe6b7f" - -RULES_POWERSHELL_URL = "https://github.com/periareon/rules_powershell/releases/download/0.3.1/rules_powershell-0.3.1.tar.gz" - -PWSH_DOWNLOAD = "https://github.com/PowerShell/PowerShell/releases/download/v" + PWSH_VERSION + "/" - -PWSH_CELLS = { - "linux_arm64": struct( - artifact = "powershell-7.5.13-linux-arm64.tar.gz", - sha256 = "6a556353ccfb0a414b80322334eac29a540a398537d3cf8dcc3ecec9cd8abd66", - exec_compatible_with = ["@platforms//os:linux", "@platforms//cpu:aarch64"], - binary = "pwsh", - ), - "linux_x86_64": struct( - artifact = "powershell-7.5.13-linux-x64.tar.gz", - sha256 = "e9256bfc6ac98fcbec97270e8a986577a7346a587837cc80d30595eef3c2546b", - exec_compatible_with = ["@platforms//os:linux", "@platforms//cpu:x86_64"], - binary = "pwsh", - ), - "macos_arm64": struct( - artifact = "powershell-7.5.13-osx-arm64.tar.gz", - sha256 = "0d2f48707d18a388096bee8820967c2ef78156f4eb74700d8a77c50798b99e94", - exec_compatible_with = ["@platforms//os:macos", "@platforms//cpu:aarch64"], - binary = "pwsh", - ), - "macos_x86_64": struct( - artifact = "powershell-7.5.13-osx-x64.tar.gz", - sha256 = "57b18193fb4038b115d2b0bfe284c275e471027cde1ad202e777febf2c7da58f", - exec_compatible_with = ["@platforms//os:macos", "@platforms//cpu:x86_64"], - binary = "pwsh", - ), - "windows_arm64": struct( - artifact = "PowerShell-7.5.13-win-arm64.zip", - sha256 = "fc850ea69b8d476a4c1bab1a2321a0b656260efa425681a62c290d1f7054c9e8", - exec_compatible_with = ["@platforms//os:windows", "@platforms//cpu:aarch64"], - binary = "pwsh.exe", - ), - "windows_x86_64": struct( - artifact = "PowerShell-7.5.13-win-x64.zip", - sha256 = "120b8f0b04f3b3f6e8c351ddbe568bf596cdca15eeb2ecb7e724060051a36d65", - exec_compatible_with = ["@platforms//os:windows", "@platforms//cpu:x86_64"], - binary = "pwsh.exe", - ), -} diff --git a/powershell/toolchain/pins.json b/powershell/toolchain/pins.json new file mode 100644 index 0000000000..b6cb598f2d --- /dev/null +++ b/powershell/toolchain/pins.json @@ -0,0 +1,51 @@ +{ + "cells": { + "linux_arm64": { + "binary": "pwsh", + "executable": true, + "sha256": "6a556353ccfb0a414b80322334eac29a540a398537d3cf8dcc3ecec9cd8abd66", + "urls": [ + "https://github.com/PowerShell/PowerShell/releases/download/v7.5.13/powershell-7.5.13-linux-arm64.tar.gz" + ] + }, + "linux_x86_64": { + "binary": "pwsh", + "executable": true, + "sha256": "e9256bfc6ac98fcbec97270e8a986577a7346a587837cc80d30595eef3c2546b", + "urls": [ + "https://github.com/PowerShell/PowerShell/releases/download/v7.5.13/powershell-7.5.13-linux-x64.tar.gz" + ] + }, + "macos_arm64": { + "binary": "pwsh", + "executable": true, + "sha256": "0d2f48707d18a388096bee8820967c2ef78156f4eb74700d8a77c50798b99e94", + "urls": [ + "https://github.com/PowerShell/PowerShell/releases/download/v7.5.13/powershell-7.5.13-osx-arm64.tar.gz" + ] + }, + "macos_x86_64": { + "binary": "pwsh", + "executable": true, + "sha256": "57b18193fb4038b115d2b0bfe284c275e471027cde1ad202e777febf2c7da58f", + "urls": [ + "https://github.com/PowerShell/PowerShell/releases/download/v7.5.13/powershell-7.5.13-osx-x64.tar.gz" + ] + }, + "windows_arm64": { + "binary": "pwsh.exe", + "sha256": "fc850ea69b8d476a4c1bab1a2321a0b656260efa425681a62c290d1f7054c9e8", + "urls": [ + "https://github.com/PowerShell/PowerShell/releases/download/v7.5.13/PowerShell-7.5.13-win-arm64.zip" + ] + }, + "windows_x86_64": { + "binary": "pwsh.exe", + "sha256": "120b8f0b04f3b3f6e8c351ddbe568bf596cdca15eeb2ecb7e724060051a36d65", + "urls": [ + "https://github.com/PowerShell/PowerShell/releases/download/v7.5.13/PowerShell-7.5.13-win-x64.zip" + ] + } + }, + "version": "7.5.13" +} diff --git a/powershell/toolchain/pwsh.build b/powershell/toolchain/pwsh.build new file mode 100644 index 0000000000..1f512aab2b --- /dev/null +++ b/powershell/toolchain/pwsh.build @@ -0,0 +1,16 @@ +load("@rules_powershell//powershell:pwsh_toolchain.bzl", "pwsh_toolchain") + +filegroup( + name = "powershell_bin", + srcs = ["{binary}"], + data = glob( + include = ["**"], + exclude = ["BUILD.bazel"], + ), +) + +pwsh_toolchain( + name = "toolchain", + pwsh = ":powershell_bin", + visibility = ["//visibility:public"], +) diff --git a/powershell/toolchain/repos.bzl b/powershell/toolchain/repos.bzl deleted file mode 100644 index 2f72f176f3..0000000000 --- a/powershell/toolchain/repos.bzl +++ /dev/null @@ -1,61 +0,0 @@ -"""Hermetic PowerShell acquisition and toolchain registration.""" - -load("//libs/starlark:toolchain.bzl", "toolchain_target") -load( - ":pins.bzl", - "PWSH_CELLS", - "PWSH_DOWNLOAD", -) - -HUB_NAME = "dx_powershell_toolchains" - -_PWSH_BUILD = """load("@rules_powershell//powershell:pwsh_toolchain.bzl", "pwsh_toolchain") - -filegroup( - name = "powershell_bin", - srcs = ["{binary}"], - data = glob( - include = ["**"], - exclude = ["BUILD.bazel"], - ), -) - -pwsh_toolchain( - name = "toolchain", - pwsh = ":powershell_bin", - visibility = ["//visibility:public"], -) -""" - -def repo_name(cell): - """Returns the repository name of one PowerShell build.""" - return HUB_NAME + "__" + cell - -def _pwsh_impl(rctx): - cell = PWSH_CELLS[rctx.attr.cell] - rctx.download_and_extract(url = [PWSH_DOWNLOAD + cell.artifact], sha256 = cell.sha256) - if not cell.binary.endswith(".exe"): - rctx.file(cell.binary, rctx.read(cell.binary), executable = True) - rctx.file("BUILD.bazel", _PWSH_BUILD.format(binary = cell.binary)) - return rctx.repo_metadata(reproducible = True) - -pwsh_repo = repository_rule( - implementation = _pwsh_impl, - doc = "Downloads the pinned PowerShell build of one platform.", - attrs = { - "cell": attr.string(mandatory = True, doc = "Platform key in PWSH_CELLS."), - }, -) - -def hub_build(): - """Returns the hub BUILD file: one toolchain per platform.""" - return "\n".join([ - toolchain_target( - name = repo_name(cell), - target_compatible_with = PWSH_CELLS[cell].exec_compatible_with, - toolchain = "@{}//:toolchain".format(repo_name(cell)), - toolchain_type = str(Label("//powershell/toolchain/type:toolchain_type")), - visibility = ["//visibility:public"], - ) - for cell in sorted(PWSH_CELLS.keys()) - ]) diff --git a/ruby/toolchain/BUILD.bazel b/ruby/toolchain/BUILD.bazel index c505602921..12665ef8f8 100644 --- a/ruby/toolchain/BUILD.bazel +++ b/ruby/toolchain/BUILD.bazel @@ -6,8 +6,9 @@ package(default_visibility = ["//visibility:public"]) exports_files([ "BUILD.bazel", "metadata_tests.bzl", - "pins.bzl", "repos.bzl", + "pins.json", + "sorbet.build", ]) ruby_metadata_tests(name = "metadata") @@ -19,7 +20,6 @@ real_source_target( starlark_srcs = [ "BUILD.bazel", "metadata_tests.bzl", - "pins.bzl", "repos.bzl", ], tags = ["corpus"], diff --git a/ruby/toolchain/metadata_tests.bzl b/ruby/toolchain/metadata_tests.bzl index d55d72689e..778097cc63 100644 --- a/ruby/toolchain/metadata_tests.bzl +++ b/ruby/toolchain/metadata_tests.bzl @@ -1,21 +1,17 @@ """Sorbet pin tests.""" -load("//libs/starlark:defs.bzl", "expect_contains", "expect_equal", "expect_true", "starlark_test") +load("@dx_pins_data//:pins.bzl", "PINS") +load("//libs/starlark:defs.bzl", "expect_equal", "expect_true", "starlark_test") load("//libs/starlark:host.bzl", "host_cell_of") -load(":pins.bzl", "SORBET_CELLS", "SORBET_VERSION", "sorbet_url") -load(":repos.bzl", "sorbet_build") def _checks(): return [ - expect_equal("sorbet version", SORBET_VERSION, "0.6.13599"), - expect_equal("pinned cells", sorted(SORBET_CELLS.keys()), ["linux_arm64", "linux_x86_64", "macos_arm64", "macos_x86_64"]), - expect_true("digests are sha256", all([len(c.sha256) == 64 for c in SORBET_CELLS.values()])), - expect_true("gems name the version", all([SORBET_VERSION in c.gem and c.gem.endswith(".gem") for c in SORBET_CELLS.values()])), - expect_equal("gem url", sorbet_url("sorbet-static-1-x86_64-linux.gem"), "https://rubygems.org/downloads/sorbet-static-1-x86_64-linux.gem"), expect_equal("linux host", host_cell_of("linux", "amd64"), "linux_x86_64"), expect_equal("mac arm host", host_cell_of("mac os x", "aarch64"), "macos_arm64"), expect_equal("windows host", host_cell_of("windows server 2022", "amd64"), "windows_x86_64"), - expect_contains("the repo exports the binary", sorbet_build("libexec/sorbet"), 'exports_files(["libexec/sorbet"])'), + expect_equal("sorbet pinned cells", sorted(PINS["dx_sorbet"]["cells"].keys()), ["linux_arm64", "linux_x86_64", "macos_arm64", "macos_x86_64", "windows_x86_64"]), + expect_true("sorbet gems", all([c["type"] == "gem" for c in PINS["dx_sorbet"]["cells"].values() if "urls" in c])), + expect_true("sorbet windows stub", "stub" in PINS["dx_sorbet"]["cells"]["windows_x86_64"]), ] def ruby_metadata_tests(name): diff --git a/ruby/toolchain/pins.bzl b/ruby/toolchain/pins.bzl deleted file mode 100644 index b315ca0946..0000000000 --- a/ruby/toolchain/pins.bzl +++ /dev/null @@ -1,34 +0,0 @@ -"""Pinned Sorbet (sorbet-static) gems for the Ruby type check.""" - -RULES_RUBY_VERSION = "0.29.0" -RULES_RUBY_URL = "https://github.com/bazel-contrib/rules_ruby/releases/download/v" + RULES_RUBY_VERSION + "/rules_ruby-v" + RULES_RUBY_VERSION + ".tar.gz" -RULES_RUBY_SHA256 = "c92c2102ead9f051b7bb19ed7075cc5c4617cdd20b313b5b2f598f9f45b3e315" - -SORBET_VERSION = "0.6.13599" - -# Keyed by "_" as the repository rule derives it from the host. The macOS gem is a -# universal (fat) binary, so both darwin cells share it. Sorbet ships no Windows build. -SORBET_CELLS = { - "macos_arm64": struct( - gem = "sorbet-static-" + SORBET_VERSION + "-universal-darwin.gem", - sha256 = "c023f9bdc8b974640b9eb3960295ec8f41dcfa385c89a699ceec8c6ed328eea6", - ), - "macos_x86_64": struct( - gem = "sorbet-static-" + SORBET_VERSION + "-universal-darwin.gem", - sha256 = "c023f9bdc8b974640b9eb3960295ec8f41dcfa385c89a699ceec8c6ed328eea6", - ), - "linux_arm64": struct( - gem = "sorbet-static-" + SORBET_VERSION + "-aarch64-linux.gem", - sha256 = "797fb456360f91dd40c5eb1eaecee630742c2de112a76e3787506040fb750864", - ), - "linux_x86_64": struct( - gem = "sorbet-static-" + SORBET_VERSION + "-x86_64-linux.gem", - sha256 = "6fbb673e4d69b344bf5b6bec916820f87be08a351b2e4ff33df126345b1e8a70", - ), -} - -SORBET_BINARY = "libexec/sorbet" - -def sorbet_url(gem): - """Returns the rubygems download URL of one pinned gem file.""" - return "https://rubygems.org/downloads/" + gem diff --git a/ruby/toolchain/pins.json b/ruby/toolchain/pins.json new file mode 100644 index 0000000000..720c17651d --- /dev/null +++ b/ruby/toolchain/pins.json @@ -0,0 +1,41 @@ +{ + "cells": { + "linux_arm64": { + "binary": "libexec/sorbet", + "sha256": "797fb456360f91dd40c5eb1eaecee630742c2de112a76e3787506040fb750864", + "type": "gem", + "urls": [ + "https://rubygems.org/downloads/sorbet-static-0.6.13599-aarch64-linux.gem" + ] + }, + "linux_x86_64": { + "binary": "libexec/sorbet", + "sha256": "6fbb673e4d69b344bf5b6bec916820f87be08a351b2e4ff33df126345b1e8a70", + "type": "gem", + "urls": [ + "https://rubygems.org/downloads/sorbet-static-0.6.13599-x86_64-linux.gem" + ] + }, + "macos_arm64": { + "binary": "libexec/sorbet", + "sha256": "c023f9bdc8b974640b9eb3960295ec8f41dcfa385c89a699ceec8c6ed328eea6", + "type": "gem", + "urls": [ + "https://rubygems.org/downloads/sorbet-static-0.6.13599-universal-darwin.gem" + ] + }, + "macos_x86_64": { + "binary": "libexec/sorbet", + "sha256": "c023f9bdc8b974640b9eb3960295ec8f41dcfa385c89a699ceec8c6ed328eea6", + "type": "gem", + "urls": [ + "https://rubygems.org/downloads/sorbet-static-0.6.13599-universal-darwin.gem" + ] + }, + "windows_x86_64": { + "binary": "libexec/sorbet", + "stub": "#!/bin/sh\necho \"sorbet has no Windows build: the Ruby type check is not available on Windows\" >&2\nexit 2\n" + } + }, + "version": "0.6.13599" +} diff --git a/ruby/toolchain/repos.bzl b/ruby/toolchain/repos.bzl index be0f9801de..eb5bebfbc0 100644 --- a/ruby/toolchain/repos.bzl +++ b/ruby/toolchain/repos.bzl @@ -1,52 +1,10 @@ -"""Hermetic Sorbet acquisition: the pinned sorbet-static gem of the host, unpacked.""" +"""The patched rules_ruby archive.""" -load("//libs/starlark:host.bzl", "host_cell") -load("//libs/starlark:repo.bzl", "gem_extract", "pinned_archive") -load(":pins.bzl", "RULES_RUBY_SHA256", "RULES_RUBY_URL", "RULES_RUBY_VERSION", "SORBET_BINARY", "SORBET_CELLS", "sorbet_url") +load("//libs/starlark:repo.bzl", "pinned_archive") -_BUILD = """package(default_visibility = ["//visibility:public"]) - -exports_files(["{binary}"]) -""" - -_WINDOWS_STUB = """#!/bin/sh -echo "sorbet has no Windows build: the Ruby type check is not available on Windows" >&2 -exit 2 -""" - -def sorbet_build(binary): - """Returns the BUILD file of the Sorbet repository.""" - return _BUILD.format(binary = binary) - -def _sorbet_impl(rctx): - cell = host_cell(rctx) - rctx.file("REPO.bazel", "") - if cell.startswith("windows"): - # No download: a stub keeps the label valid and fails loudly if it is ever run. - rctx.file(SORBET_BINARY, _WINDOWS_STUB, executable = True) - rctx.file("BUILD.bazel", sorbet_build(SORBET_BINARY)) - return - pin = SORBET_CELLS.get(cell) - if pin == None: - fail("no pinned sorbet-static gem for " + cell) - url = sorbet_url(pin.gem) - gem_extract( - rctx, - url = url, - sha256 = pin.sha256, - canonical_id = "dx-sorbet-gem:" + url, - output = ".", - required = [SORBET_BINARY], - ) - rctx.file("BUILD.bazel", sorbet_build(SORBET_BINARY)) - -_sorbet = repository_rule( - implementation = _sorbet_impl, - doc = "Downloads and unpacks the pinned sorbet-static gem of the host platform.", -) +_VERSION = "0.29.0" def _ruby_tools_impl(mctx): - _sorbet(name = "dx_sorbet") pinned_archive( name = "rules_ruby", crlf = ["ruby/private/binary/binary.cmd.tpl"], @@ -56,13 +14,13 @@ def _ruby_tools_impl(mctx): Label("//patches/rules_ruby:coverage.patch"), Label("//patches/rules_ruby:rubyinstaller_archive.patch"), ], - sha256 = RULES_RUBY_SHA256, - strip_prefix = "rules_ruby-" + RULES_RUBY_VERSION, - urls = [RULES_RUBY_URL], + sha256 = "c92c2102ead9f051b7bb19ed7075cc5c4617cdd20b313b5b2f598f9f45b3e315", + strip_prefix = "rules_ruby-" + _VERSION, + urls = ["https://github.com/bazel-contrib/rules_ruby/releases/download/v{0}/rules_ruby-v{0}.tar.gz".format(_VERSION)], ) return mctx.extension_metadata(reproducible = True) ruby_tools = module_extension( implementation = _ruby_tools_impl, - doc = "Creates the pinned Sorbet repository and the patched rules_ruby.", + doc = "Creates the patched rules_ruby.", ) diff --git a/ruby/toolchain/sorbet.build b/ruby/toolchain/sorbet.build new file mode 100644 index 0000000000..4411b66a99 --- /dev/null +++ b/ruby/toolchain/sorbet.build @@ -0,0 +1,3 @@ +package(default_visibility = ["//visibility:public"]) + +exports_files(["{binary}"])