diff --git a/.devcontainer/post_create_command.sh b/.devcontainer/post_create_command.sh index 3fa2982..6101a47 100755 --- a/.devcontainer/post_create_command.sh +++ b/.devcontainer/post_create_command.sh @@ -14,8 +14,12 @@ # ******************************************************************************* npm install -g @devcontainers/cli + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +REPOSITORY_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd -P)" + +sudo "${REPOSITORY_ROOT}/tools/tool_installer.py" install shellcheck yamlfmt + pre-commit install scripts/create_builder.sh - -sudo apt-get update && sudo apt-get install -y shellcheck diff --git a/.gitignore b/.gitignore index 0c08d08..31f6757 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,12 @@ # Exported image files shall never be committed. /export.img build/ + +# bazel files +/bazel-* + +# AI +/.codex + +# Python files +*.pyc diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3fecbb9..9a33895 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,14 +22,19 @@ repos: - id: check-executables-have-shebangs - id: check-added-large-files args: [--maxkb=50, --enforce-all] # increase or add git lfs if too strict - - repo: https://github.com/google/yamlfmt - rev: 21ca5323a9c87ee37a434e0ca908efc0a89daa07 # v0.21.0 + exclude: ^MODULE\.bazel\.lock$ + - repo: local hooks: - id: yamlfmt - - repo: https://github.com/jumanjihouse/pre-commit-hooks - rev: 38980559e3a605691d6579f96222c30778e5a69e # 3.0.0 - hooks: + name: yamlfmt + entry: tools/run_tool.sh yamlfmt + language: system + types: [yaml] - id: shellcheck + name: shellcheck + entry: tools/run_tool.sh shellcheck + language: system + types: [shell] - repo: https://github.com/eclipse-score/tooling rev: 31ff8eee214e4e97ef8f5cb46e443273515b63ec hooks: diff --git a/.shellcheckrc b/.shellcheckrc index 2d48e04..5424a52 100644 --- a/.shellcheckrc +++ b/.shellcheckrc @@ -24,3 +24,6 @@ disable=SC2046 # optional checks, fixes might not be easy and better not break the code disable=SC2292,SC2154,SC2312 + +# SC1091: Not following sourced files that are not specified as input +disable=SC1091 diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000..913a6ae --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,31 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +module(name = "score_devcontainer") + +bazel_dep(name = "rules_multitool", version = "1.11.1") + +multitool = use_extension("@rules_multitool//multitool:extension.bzl", "multitool") + +multitool.hub(lockfile = "//tools:lockfiles/actionlint.lock.json") +multitool.hub(lockfile = "//tools:lockfiles/ruff.lock.json") +multitool.hub(lockfile = "//tools:lockfiles/shellcheck.lock.json") +multitool.hub(lockfile = "//tools:lockfiles/yamlfmt.lock.json") +multitool.hub(lockfile = "//tools:lockfiles/uv.lock.json") +multitool.hub(lockfile = "//tools:lockfiles/buildifier.lock.json") +multitool.hub(lockfile = "//tools:lockfiles/starpls.lock.json") +multitool.hub(lockfile = "//tools:lockfiles/bazelisk.lock.json") + +use_repo(multitool, "multitool") + +register_toolchains("@multitool//toolchains:all") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 0000000..028cfea --- /dev/null +++ b/MODULE.bazel.lock @@ -0,0 +1,606 @@ +{ + "lockFileVersion": 26, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", + "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c", + "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", + "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", + "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e", + "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1", + "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4", + "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", + "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", + "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", + "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", + "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", + "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", + "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", + "https://bcr.bazel.build/modules/bazel_lib/3.0.0-rc.0/MODULE.bazel": "d6e00979a98ac14ada5e31c8794708b41434d461e7e7ca39b59b765e6d233b18", + "https://bcr.bazel.build/modules/bazel_lib/3.0.0-rc.0/source.json": "7051768079aa19302df2b9446ad0889839fd08b7d59851eba2c99234d665c9ba", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", + "https://bcr.bazel.build/modules/buildifier_prebuilt/7.3.1/MODULE.bazel": "537faf0ad9f5892910074b8e43b4c91c96f1d5d86b6ed04bdbe40cf68aa48b68", + "https://bcr.bazel.build/modules/buildifier_prebuilt/7.3.1/source.json": "55153a5e6ca9c8a7e266c4b46b951e8a010d25ec6062bc35d5d4f89925796bad", + "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", + "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", + "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", + "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", + "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", + "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d", + "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42", + "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", + "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", + "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68", + "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", + "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", + "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", + "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", + "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", + "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", + "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", + "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", + "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_multitool/1.11.1/MODULE.bazel": "f826d2d394e8d964e44ebb4a75ebcfe4e9cd4eb150e2ddcd60398ffeb939696a", + "https://bcr.bazel.build/modules/rules_multitool/1.11.1/source.json": "201f43de1d35bd17f25a4fed3ba5a2ec500ef5e08b7d4b341bb9fd39cef0cbc6", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", + "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", + "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", + "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", + "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", + "https://bcr.bazel.build/modules/rules_shell/0.4.1/MODULE.bazel": "00e501db01bbf4e3e1dd1595959092c2fadf2087b2852d3f553b5370f5633592", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", + "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", + "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", + "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd", + "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400", + "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", + "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@buildifier_prebuilt+//:defs.bzl%buildifier_prebuilt_deps_extension": { + "general": { + "bzlTransitiveDigest": "3SXpv/oaemUJfW9RAoTqenEgHJE2pkdbrrkPif6Vk00=", + "usagesDigest": "eWMDBEn8E8CrwAPXrlrjIap2pseSMhxDyDdrntHBOOE=", + "recordedInputs": [ + "REPO_MAPPING:buildifier_prebuilt+,bazel_skylib bazel_skylib+", + "REPO_MAPPING:buildifier_prebuilt+,bazel_tools bazel_tools" + ], + "generatedRepoSpecs": { + "buildifier_darwin_amd64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-darwin-amd64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "375f823103d01620aaec20a0c29c6cbca99f4fd0725ae30b93655c6704f44d71" + } + }, + "buildifier_darwin_arm64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-darwin-arm64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "5a6afc6ac7a09f5455ba0b89bd99d5ae23b4174dc5dc9d6c0ed5ce8caac3f813" + } + }, + "buildifier_linux_amd64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-linux-amd64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "5474cc5128a74e806783d54081f581662c4be8ae65022f557e9281ed5dc88009" + } + }, + "buildifier_linux_arm64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-linux-arm64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "0bf86c4bfffaf4f08eed77bde5b2082e4ae5039a11e2e8b03984c173c34a561c" + } + }, + "buildifier_windows_amd64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-windows-amd64.exe" + ], + "downloaded_file_path": "buildifier.exe", + "executable": true, + "sha256": "370cd576075ad29930a82f5de132f1a1de4084c784a82514bd4da80c85acf4a8" + } + }, + "buildozer_darwin_amd64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-darwin-amd64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "854c9583efc166602276802658cef3f224d60898cfaa60630b33d328db3b0de2" + } + }, + "buildozer_darwin_arm64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-darwin-arm64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "31b1bfe20d7d5444be217af78f94c5c43799cdf847c6ce69794b7bf3319c5364" + } + }, + "buildozer_linux_amd64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-linux-amd64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "3305e287b3fcc68b9a35fd8515ee617452cd4e018f9e6886b6c7cdbcba8710d4" + } + }, + "buildozer_linux_arm64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-linux-arm64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "0b5a2a717ac4fc911e1fec8d92af71dbb4fe95b10e5213da0cc3d56cea64a328" + } + }, + "buildozer_windows_amd64": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-windows-amd64.exe" + ], + "downloaded_file_path": "buildozer.exe", + "executable": true, + "sha256": "58d41ce53257c5594c9bc86d769f580909269f68de114297f46284fbb9023dcf" + } + }, + "buildifier_prebuilt_toolchains": { + "repoRuleId": "@@buildifier_prebuilt+//:defs.bzl%_buildifier_toolchain_setup", + "attributes": { + "assets_json": "[{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"375f823103d01620aaec20a0c29c6cbca99f4fd0725ae30b93655c6704f44d71\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"5a6afc6ac7a09f5455ba0b89bd99d5ae23b4174dc5dc9d6c0ed5ce8caac3f813\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"5474cc5128a74e806783d54081f581662c4be8ae65022f557e9281ed5dc88009\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"0bf86c4bfffaf4f08eed77bde5b2082e4ae5039a11e2e8b03984c173c34a561c\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"windows\",\"sha256\":\"370cd576075ad29930a82f5de132f1a1de4084c784a82514bd4da80c85acf4a8\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"854c9583efc166602276802658cef3f224d60898cfaa60630b33d328db3b0de2\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"31b1bfe20d7d5444be217af78f94c5c43799cdf847c6ce69794b7bf3319c5364\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"3305e287b3fcc68b9a35fd8515ee617452cd4e018f9e6886b6c7cdbcba8710d4\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"0b5a2a717ac4fc911e1fec8d92af71dbb4fe95b10e5213da0cc3d56cea64a328\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"windows\",\"sha256\":\"58d41ce53257c5594c9bc86d769f580909269f68de114297f46284fbb9023dcf\",\"version\":\"v7.3.1\"}]" + } + } + } + } + }, + "@@pybind11_bazel+//:internal_configure.bzl%internal_configure_extension": { + "general": { + "bzlTransitiveDigest": "b+RP7Sgl8KN0VHamrgTqzGLuYPcQ/Mo4ptNkkHUIIlA=", + "usagesDigest": "D1r3lfzMuUBFxgG8V6o0bQTLMk3GkaGOaPzw53wrwyw=", + "recordedInputs": [ + "REPO_MAPPING:pybind11_bazel+,bazel_tools bazel_tools", + "FILE:@@pybind11_bazel+//MODULE.bazel e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34" + ], + "generatedRepoSpecs": { + "pybind11": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file": "@@pybind11_bazel+//:pybind11-BUILD.bazel", + "strip_prefix": "pybind11-2.12.0", + "urls": [ + "https://github.com/pybind/pybind11/archive/v2.12.0.zip" + ] + } + } + } + } + }, + "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { + "general": { + "bzlTransitiveDigest": "Ga4z8lQy1YQ5rAMy+dOl0dqcCEBnYNCXku8x3YQmDZI=", + "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", + "recordedInputs": [ + "REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools" + ], + "generatedRepoSpecs": { + "com_github_jetbrains_kotlin_git": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_jetbrains_kotlin": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_google_ksp": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + }, + "com_github_pinterest_ktlint": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "rules_android": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } + } + } + } + }, + "@@rules_python+//python/extensions:config.bzl%config": { + "general": { + "bzlTransitiveDigest": "iibnRYgg8LpcfmH7EAnVwYePC3jsVaJ6Id8XxUjSZps=", + "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", + "recordedInputs": [ + "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build", + "REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click", + "REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama", + "REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata", + "REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer", + "REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools", + "REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging", + "REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517", + "REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip", + "REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools", + "REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks", + "REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools", + "REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli", + "REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel", + "REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp" + ], + "generatedRepoSpecs": { + "rules_python_internal": { + "repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo", + "attributes": { + "transition_setting_generators": {}, + "transition_settings": [] + } + }, + "pypi__build": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl", + "sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__click": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", + "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__colorama": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", + "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__importlib_metadata": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl", + "sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__installer": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", + "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__more_itertools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl", + "sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__packaging": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", + "sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pep517": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl", + "sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl", + "sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip_tools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl", + "sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pyproject_hooks": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl", + "sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__setuptools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl", + "sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__tomli": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", + "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__wheel": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl", + "sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__zipp": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl", + "sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + } + } + } + }, + "@@rules_python+//python/uv:uv.bzl%uv": { + "general": { + "bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=", + "usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=", + "recordedInputs": [ + "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_python+,platforms platforms" + ], + "generatedRepoSpecs": { + "uv": { + "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo", + "attributes": { + "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'", + "toolchain_names": [ + "none" + ], + "toolchain_implementations": { + "none": "'@@rules_python+//python:none'" + }, + "toolchain_compatible_with": { + "none": [ + "@platforms//:incompatible" + ] + }, + "toolchain_target_settings": {} + } + } + } + } + } + }, + "facts": {} +} diff --git a/REUSE.toml b/REUSE.toml index d6231a3..6904c6c 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -25,7 +25,9 @@ SPDX-License-Identifier = "Apache-2.0" [[annotations]] path = ["resources/reopen_in_container.png", - "resources/devcontainer_success.png" + "resources/devcontainer_success.png", + "tools/lockfiles/*.lock.json", + "MODULE.bazel.lock", ] SPDX-FileCopyrightText = "Copyright (c) 2026 Contributors to the Eclipse Foundation" SPDX-License-Identifier = "Apache-2.0" diff --git a/src/s-core-devcontainer/.devcontainer/Dockerfile b/src/s-core-devcontainer/.devcontainer/Dockerfile index 502dbcd..2ba2494 100644 --- a/src/s-core-devcontainer/.devcontainer/Dockerfile +++ b/src/s-core-devcontainer/.devcontainer/Dockerfile @@ -16,4 +16,6 @@ FROM buildpack-deps:noble-curl LABEL dev.containers.features="common" +COPY tools /usr/local/share/score-tools + RUN userdel -f -r ubuntu diff --git a/src/s-core-devcontainer/.devcontainer/bazel-feature/devcontainer-feature.json b/src/s-core-devcontainer/.devcontainer/bazel-feature/devcontainer-feature.json index d60e94f..b15d32c 100644 --- a/src/s-core-devcontainer/.devcontainer/bazel-feature/devcontainer-feature.json +++ b/src/s-core-devcontainer/.devcontainer/bazel-feature/devcontainer-feature.json @@ -3,9 +3,6 @@ "id": "bazel", "version": "1.0.0", "description": "Bazel and supplimentary tools for working with Bazel-based projects.", - "dependsOn": { - "./s-core-local": {} // needed for extracting versions (versions.sh) - }, "onCreateCommand": "/devcontainer/features/bazel/on_create_command.sh", "postCreateCommand": { // The repos in S-CORE may use different Bazel versions. This ensures that the required version is installed. diff --git a/src/s-core-devcontainer/.devcontainer/bazel-feature/install.sh b/src/s-core-devcontainer/.devcontainer/bazel-feature/install.sh index 3bcdc72..fca90c3 100755 --- a/src/s-core-devcontainer/.devcontainer/bazel-feature/install.sh +++ b/src/s-core-devcontainer/.devcontainer/bazel-feature/install.sh @@ -29,7 +29,7 @@ rm -f "${COPY_TARGET}/devcontainer-features.env" "${COPY_TARGET}/devcontainer-fe DEBIAN_FRONTEND=noninteractive # Read tool versions + metadata into environment variables -. /devcontainer/features/s-core-local/versions.sh /devcontainer/features/bazel/versions.yaml +. /usr/local/share/score-tools/versions.sh /devcontainer/features/bazel/versions.yaml ARCHITECTURE=$(dpkg --print-architecture) @@ -39,20 +39,11 @@ apt-get update # Container build dependencies are not pinned, since they are removed anyway after container creation. apt-get install apt-transport-https -y -# Bazelisk, directly from GitHub -# Using the existing devcontainer feature is not optimal: -# - it does not check the SHA256 checksum of the downloaded file -# - it cannot pre-install a specific version of Bazel, or prepare bash completion -BAZELISK_VARIANT="amd64" -SHA256SUM="${bazelisk_amd64_sha256}" -if [ "${ARCHITECTURE}" = "arm64" ]; then - BAZELISK_VARIANT="arm64" - SHA256SUM="${bazelisk_arm64_sha256}" -fi -curl -L "https://github.com/bazelbuild/bazelisk/releases/download/v${bazelisk_version}/bazelisk-${BAZELISK_VARIANT}.deb" -o /tmp/bazelisk.deb -echo "${SHA256SUM} /tmp/bazelisk.deb" | sha256sum -c - || exit 1 -apt-get install -y --no-install-recommends --fix-broken /tmp/bazelisk.deb -rm /tmp/bazelisk.deb +# Lockfile-managed Bazel tooling +/usr/local/share/score-tools/tool_installer.py install bazelisk buildifier starpls + +# Bazelisk + Bazel +ln -sf /usr/local/bin/bazelisk /usr/local/bin/bazel # Pre-install a fixed Bazel version, setup the bash command completion export USE_BAZEL_VERSION=${bazel_version} @@ -67,29 +58,6 @@ sh -c "echo 'INSTALLED_BAZEL_VERSION=${bazel_version}' >> /devcontainer/features # This is required for corporate environments with custom CA certificates echo 'startup --host_jvm_args=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit' >> /etc/bazel.bazelrc -# Buildifier, directly from GitHub (apparently no APT repository available) -# The version is pinned to a specific release, and the SHA256 checksum is provided by the devcontainer-features.json file. -BUILDIFIER_VARIANT="amd64" -SHA256SUM="${buildifier_amd64_sha256}" -if [ "${ARCHITECTURE}" = "arm64" ]; then - BUILDIFIER_VARIANT="arm64" - SHA256SUM="${buildifier_arm64_sha256}" -fi -curl -L "https://github.com/bazelbuild/buildtools/releases/download/v${buildifier_version}/buildifier-linux-${BUILDIFIER_VARIANT}" -o /usr/local/bin/buildifier -echo "${SHA256SUM} /usr/local/bin/buildifier" | sha256sum -c - || exit 1 -chmod +x /usr/local/bin/buildifier - -# Starlark Language Server, directly from GitHub (apparently no APT repository available) -STARPLS_VARIANT="amd64" -SHA256SUM="${starpls_amd64_sha256}" -if [ "${ARCHITECTURE}" = "arm64" ]; then - STARPLS_VARIANT="aarch64" - SHA256SUM="${starpls_arm64_sha256}" -fi -curl -L "https://github.com/withered-magic/starpls/releases/download/v${starpls_version}/starpls-linux-${STARPLS_VARIANT}" -o /usr/local/bin/starpls -echo "${SHA256SUM} /usr/local/bin/starpls" | sha256sum -c - || exit 1 -chmod +x /usr/local/bin/starpls - # Code completion for C++ code of Bazel projects # (see https://github.com/kiron1/bazel-compile-commands) source /etc/lsb-release diff --git a/src/s-core-devcontainer/.devcontainer/bazel-feature/tests/test_default.sh b/src/s-core-devcontainer/.devcontainer/bazel-feature/tests/test_default.sh index b47c48e..bb85e25 100755 --- a/src/s-core-devcontainer/.devcontainer/bazel-feature/tests/test_default.sh +++ b/src/s-core-devcontainer/.devcontainer/bazel-feature/tests/test_default.sh @@ -16,17 +16,20 @@ set -euo pipefail # Read tool versions + metadata into environment variables -. /devcontainer/features/s-core-local/versions.sh /devcontainer/features/bazel/versions.yaml +. /usr/local/share/score-tools/versions.sh /devcontainer/features/bazel/versions.yaml +bazelisk_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version bazelisk)" +buildifier_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version buildifier)" +starpls_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version starpls)" # Bazel-related tools ## This is the bazel version preinstalled in the devcontainer. ## A solid test would disable the network interface first to prevent a different version from being downloaded, ## but that requires CAP_NET_ADMIN, which is not yet added. export USE_BAZEL_VERSION=${bazel_version} -check "validate bazelisk is working and has the correct version" bash -c "bazelisk version | grep '${bazelisk_version}'" +check "validate bazelisk is working and has the correct version" bash -c "bazelisk version | grep '${bazelisk_lockfile_version}'" check "validate bazel is working and has the correct version" bash -c "bazel version | grep '${bazel_version}'" unset USE_BAZEL_VERSION -check "validate buildifier is working and has the correct version" bash -c "buildifier --version | grep '${buildifier_version}'" -check "validate starpls is working and has the correct version" bash -c "starpls version | grep '${starpls_version}'" +check "validate buildifier is working and has the correct version" bash -c "buildifier --version | grep '${buildifier_lockfile_version}'" +check "validate starpls is working and has the correct version" bash -c "starpls version | grep '${starpls_lockfile_version}'" check "validate bazel-compile-commands is working and has the correct version" bash -c "bazel-compile-commands --version 2>&1 | grep '${bazel_compile_commands_version}'" diff --git a/src/s-core-devcontainer/.devcontainer/bazel-feature/versions.yaml b/src/s-core-devcontainer/.devcontainer/bazel-feature/versions.yaml index b207ead..a3fd803 100644 --- a/src/s-core-devcontainer/.devcontainer/bazel-feature/versions.yaml +++ b/src/s-core-devcontainer/.devcontainer/bazel-feature/versions.yaml @@ -14,40 +14,6 @@ bazel: # https://github.com/bazelbuild/bazel/releases -- latest version as of 2025-09-24 version: 8.4.1 # no need to define sha256 here, as bazel is installed via bazelisk -buildifier: - version: 8.2.1 - amd64: - # The following sha256sum is for the binary buildifier-linux-amd64 - # from the GitHub release page of buildtools - # It is generated by running 'sha256sum buildifier-linux-amd64' - sha256: 6ceb7b0ab7cf66fceccc56a027d21d9cc557a7f34af37d2101edb56b92fcfa1a - arm64: - # The following sha256sum is for the binary buildifier-linux-arm64 - # from the GitHub release page of buildtools - # It is generated by running 'sha256sum buildifier-linux-arm64' - sha256: 3baa1cf7eb41d51f462fdd1fff3a6a4d81d757275d05b2dd5f48671284e9a1a5 -bazelisk: - version: 1.27.0 - amd64: - # The following sha256sums are for the deb package bazelisk__amd64.deb - # It is generated by running 'sha256sum bazelisk__amd64.deb' - sha256: d8b00ea975c823e15263c80200ac42979e17368547fbff4ab177af035badfa83 - arm64: - # The following sha256sums are for the deb package bazelisk__arm64.deb - # It is generated by running 'sha256sum bazelisk__arm64.deb' - sha256: 173c5b367b485a30ce58c1d0d560b39d257a2d7a3c859c45d7d05eb61605a2a1 -starpls: - version: 0.1.22 - amd64: - # The following sha256sum is for the binary starpls-linux-amd64 - # from the GitHub release page of starpls - # It is generated by running 'sha256sum starpls-linux-amd64' - sha256: 7c661cdde0d1c026665086d07523d825671e29056276681616bb32d0273c5eab - arm64: - # The following sha256sum is for the binary starpls-linux-arm64 - # from the GitHub release page of starpls - # It is generated by running 'sha256sum starpls-linux-arm64' - sha256: 55877ec4c3ff03e1d90d59c76f69a3a144b6c29688747c8ac4d77993e2eef1ad bazel_compile_commands: version: 0.18.0 amd64: diff --git a/src/s-core-devcontainer/.devcontainer/devcontainer.json b/src/s-core-devcontainer/.devcontainer/devcontainer.json index 33fdeb0..f1394b0 100644 --- a/src/s-core-devcontainer/.devcontainer/devcontainer.json +++ b/src/s-core-devcontainer/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ "build": { // Installs latest version from the Distribution "dockerfile": "./${localEnv:DEVCONTAINER_DOCKERFILE_NAME:Dockerfile}", - "context": ".", + "context": "../../../", "args": { "HTTP_PROXY": "${localEnv:HTTP_PROXY}", "HTTPS_PROXY": "${localEnv:HTTPS_PROXY}", diff --git a/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh b/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh index 94b39ac..ff41759 100755 --- a/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh +++ b/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh @@ -31,58 +31,11 @@ rm -f "${COPY_TARGET}/devcontainer-features.env" "${COPY_TARGET}/devcontainer-fe DEBIAN_FRONTEND=noninteractive # Read tool versions + metadata into environment variables -. /devcontainer/features/s-core-local/versions.sh /devcontainer/features/s-core-local/versions.yaml +. /usr/local/share/score-tools/versions.sh /devcontainer/features/s-core-local/versions.yaml ARCHITECTURE=$(dpkg --print-architecture) KERNEL=$(uname -s) -# Downloads and extracts a tool from GitHub releases, based on the provided URL pattern, version and architecture-specific checksums. -# The URL pattern can include placeholders for version and architecture variant -download_and_extract_from_github() { - local url_pattern="$1" - local tool_name="$2" - local amd64_name="$3" - local arm64_name="$4" - local extract_names="$5" - local strip_components="${6:-0}" - local temp_file="/tmp/${tool_name}" - - local version_name="${tool_name}_version" - export version="${!version_name}" - variant="${amd64_name}" - local sha256sum_name="${tool_name}_amd64_sha256" - if [ "${ARCHITECTURE}" = "arm64" ]; then - variant="${arm64_name}" - sha256sum_name="${tool_name}_arm64_sha256" - fi - sha256sum="${!sha256sum_name}" - export variant - - local url - url="$(eval "echo ${url_pattern}")" - - curl -L "${url}" -o "${temp_file}" - echo "${sha256sum} ${temp_file}" | sha256sum -c - || exit 1 - - local tar_options="" - if [[ "${url}" == *.tar.gz ]]; then - tar_options="-xzf" - elif [[ "${url}" == *.tar.xz ]]; then - tar_options="-xf" - elif [[ "${url}" == *.tar.zst ]]; then - tar_options="-I zstd -xf" - fi - - local extract_names_expanded - extract_names_expanded="$(eval "echo ${extract_names}")" - - # shellcheck disable=SC2086 - # tar_options and extract_names_expanded are expected to be word-split - tar ${tar_options} "${temp_file}" -C "/usr/local/bin" --strip-components="${strip_components}" ${extract_names_expanded} - - rm "${temp_file}" -} - # always add PIPX_BIN_DIR to path PIPX_BIN_DIR_EXPORT="$(grep "export PIPX_BIN_DIR" /etc/bash.bashrc)" eval "${PIPX_BIN_DIR_EXPORT}" @@ -98,13 +51,14 @@ apt-get install -y man-db manpages manpages-dev manpages-posix manpages-posix-de # Container build dependencies are not pinned, since they are removed anyway after container creation. apt-get install apt-transport-https -y -# static code analysis for shell scripts -download_and_extract_from_github \ - 'https://github.com/koalaman/shellcheck/releases/download/v${version}/shellcheck-v${version}.linux.${variant}.tar.xz' \ - "shellcheck" \ - "x86_64" "aarch64" \ - 'shellcheck-v${version}/shellcheck' \ - 1 +# Python, via APT +apt-get install -y "python${python_version}" python3-pip python3-venv +# The following packages correspond to the list of packages installed by the +# devcontainer feature "python" (cf. https://github.com/devcontainers/features/tree/main/src/python ) +apt-get install -y flake8 python3-autopep8 black python3-yapf mypy pydocstyle pycodestyle bandit pipenv virtualenv pylint + +# Lockfile-managed local developer tools +/usr/local/share/score-tools/tool_installer.py install shellcheck ruff actionlint yamlfmt uv uvx # GraphViz # The Ubuntu Noble package of GraphViz @@ -118,12 +72,6 @@ apt-get install -y git apt-get install -y git-lfs apt-get install -y gh -# Python, via APT -apt-get install -y "python${python_version}" python3-pip python3-venv -# The following packages correspond to the list of packages installed by the -# devcontainer feature "python" (cf. https://github.com/devcontainers/features/tree/main/src/python ) -apt-get install -y flake8 python3-autopep8 black python3-yapf mypy pydocstyle pycodestyle bandit pipenv virtualenv pylint - # OpenJDK 21, via APT # Set JAVA_HOME environment variable system-wide, since some tools rely on it (e.g., Bazel's rules_java) apt-get install -y ca-certificates-java openjdk-21-jdk-headless="${openjdk_21_version}*" @@ -134,36 +82,6 @@ echo -e "JAVA_HOME=${JAVA_HOME}\nexport JAVA_HOME" > /etc/profile.d/java_home.sh # qemu-system-arm apt-get install -y --no-install-recommends --fix-broken qemu-system-arm="${qemu_system_arm_version}*" -# ruff -download_and_extract_from_github \ - 'https://github.com/astral-sh/ruff/releases/download/${version}/ruff-${variant}-unknown-linux-gnu.tar.gz' \ - "ruff" \ - "x86_64" "aarch64" \ - 'ruff-${variant}-unknown-linux-gnu/ruff' \ - 1 - -# actionlint -download_and_extract_from_github \ - 'https://github.com/rhysd/actionlint/releases/download/v${version}/actionlint_${version}_linux_${variant}.tar.gz' \ - "actionlint" \ - "amd64" "arm64" \ - 'actionlint' - -# yamlfmt -download_and_extract_from_github \ - 'https://github.com/google/yamlfmt/releases/download/v${version}/yamlfmt_${version}_Linux_${variant}.tar.gz' \ - "yamlfmt" \ - "x86_64" "arm64" \ - 'yamlfmt' - -# uv -download_and_extract_from_github \ - 'https://github.com/astral-sh/uv/releases/download/${version}/uv-${variant}-unknown-linux-gnu.tar.gz' \ - "uv" \ - "x86_64" "aarch64" \ - 'uv-${variant}-unknown-linux-gnu/uv uv-${variant}-unknown-linux-gnu/uvx' \ - 1 - # basedpyright su $(ls /home) -c "uv tool install basedpyright@\"${basedpyright_version}\"" diff --git a/src/s-core-devcontainer/.devcontainer/s-core-local/tests/test_default.sh b/src/s-core-devcontainer/.devcontainer/s-core-local/tests/test_default.sh index b2e6731..1042838 100755 --- a/src/s-core-devcontainer/.devcontainer/s-core-local/tests/test_default.sh +++ b/src/s-core-devcontainer/.devcontainer/s-core-local/tests/test_default.sh @@ -19,13 +19,20 @@ ARCHITECTURE=$(dpkg --print-architecture) KERNEL=$(uname -s) # Read tool versions + metadata into environment variables -. /devcontainer/features/s-core-local/versions.sh /devcontainer/features/s-core-local/versions.yaml +. /usr/local/share/score-tools/versions.sh /devcontainer/features/s-core-local/versions.yaml + +shellcheck_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version shellcheck)" +ruff_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version ruff)" +actionlint_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version actionlint)" +yamlfmt_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version yamlfmt)" +uv_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version uv)" +uvx_lockfile_version="$(/usr/local/share/score-tools/tool_installer.py version uvx)" # pre-commit, it is available via $PATH in login shells, but not in non-login shells check "validate pre-commit is working and has the correct version" bash -c "pre-commit --version | grep '4.5.1'" # Common tooling -check "validate shellcheck is working and has the correct version" bash -c "shellcheck --version | grep '${shellcheck_version}'" +check "validate shellcheck is working and has the correct version" bash -c "shellcheck --version | grep '${shellcheck_lockfile_version}'" # For an unknown reason, dot -V reports on Ubuntu Noble a version 2.43.0, while the package has a different version. # Hence, we have to work around that. @@ -56,17 +63,17 @@ check "validate java is working and has the correct version" bash -c "java -vers check "validate JAVA_HOME is set correctly" bash -c "echo ${JAVA_HOME} | xargs readlink -f | grep \"java-21-openjdk\"" # ruff -check "validate ruff is working and has the correct version" bash -c "ruff --version | grep '${ruff_version}'" +check "validate ruff is working and has the correct version" bash -c "ruff --version | grep '${ruff_lockfile_version}'" # actionlint -check "validate actionlint is working and has the correct version" bash -c "actionlint --version | grep '${actionlint_version}'" +check "validate actionlint is working and has the correct version" bash -c "actionlint --version | grep '${actionlint_lockfile_version}'" # yamlfmt -check "validate yamlfmt is working and has the correct version" bash -c "yamlfmt --version | grep '${yamlfmt_version}'" +check "validate yamlfmt is working and has the correct version" bash -c "yamlfmt --version | grep '${yamlfmt_lockfile_version}'" # uv -check "validate uv is working and has the correct version" bash -c "uv --version | grep '${uv_version}'" -check "validate uvx is working and has the correct version" bash -c "uvx --version | grep '${uv_version}'" +check "validate uv is working and has the correct version" bash -c "uv --version | grep '${uv_lockfile_version}'" +check "validate uvx is working and has the correct version" bash -c "uvx --version | grep '${uvx_lockfile_version}'" # additional developer tools check "validate gdb is working and has the correct version" bash -c "gdb --version | grep '${gdb_version}'" diff --git a/src/s-core-devcontainer/.devcontainer/s-core-local/versions.yaml b/src/s-core-devcontainer/.devcontainer/s-core-local/versions.yaml index fcb8a81..37961b4 100644 --- a/src/s-core-devcontainer/.devcontainer/s-core-local/versions.yaml +++ b/src/s-core-devcontainer/.devcontainer/s-core-local/versions.yaml @@ -10,12 +10,6 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -actionlint: - version: 1.7.7 - amd64: - sha256: 023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757 - arm64: - sha256: 401942f9c24ed71e4fe71b76c7d638f66d8633575c4016efd2977ce7c28317d0 basedpyright: version: 1.35.0 graphviz: @@ -40,24 +34,6 @@ gh: version: 2.45.0 openjdk_21: version: 21.0.10 -ruff: - version: 0.11.13 - amd64: - sha256: 01aa32d29d00876b8d1429c617ed63a00b1fc81abfa4183bb05c9cb647fbc3d0 - arm64: - sha256: 551af2ebc439d8268dcaf871ea60ad035f688728d30943dcbb2bf775e105213e -shellcheck: - version: 0.10.0 - amd64: - sha256: 6c881ab0698e4e6ea235245f22832860544f17ba386442fe7e9d629f8cbedf87 - arm64: - sha256: 324a7e89de8fa2aed0d0c28f3dab59cf84c6d74264022c00c22af665ed1a09bb -uv: - version: 0.10.4 - amd64: - sha256: 6b52a47358deea1c5e173278bf46b2b489747a59ae31f2a4362ed5c6c1c269f7 - arm64: - sha256: c84a6e6405715caa6e2f5ef8e5f29a5d0bc558a954e9f1b5c082b9d4708c222e codeql: # the coding_standards_version below dictates the codeql version version: 2.21.4 @@ -71,9 +47,3 @@ codeql_coding_standards: version: 2.54.0 valgrind: version: 3.22.0 -yamlfmt: - version: 0.17.0 - amd64: - sha256: e91dd8722001596b8e4777a29d4a526a10ff276c4ff8a5ae39ff59be5a033054 - arm64: - sha256: ebe78a5547dac68f05a01c9a2845901b3c658095432b107bef3084dfe0b2629d diff --git a/src/s-core-devcontainer/.devcontainer/with-proxy-vars.Dockerfile b/src/s-core-devcontainer/.devcontainer/with-proxy-vars.Dockerfile index 372c4a2..ab546e9 100644 --- a/src/s-core-devcontainer/.devcontainer/with-proxy-vars.Dockerfile +++ b/src/s-core-devcontainer/.devcontainer/with-proxy-vars.Dockerfile @@ -33,6 +33,7 @@ ENV no_proxy=${no_proxy} LABEL dev.containers.features="common" # Unset proxy variables for all login shells -COPY unset-proxy.sh /etc/bash_completion.d/unset-proxy.sh +COPY src/s-core-devcontainer/.devcontainer/unset-proxy.sh /etc/bash_completion.d/unset-proxy.sh +COPY tools /usr/local/share/score-tools RUN userdel -f -r ubuntu diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel new file mode 100644 index 0000000..62192f4 --- /dev/null +++ b/tools/BUILD.bazel @@ -0,0 +1,61 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +package(default_visibility = ["//visibility:public"]) + +exports_files(glob(["lockfiles/*.lock.json"])) + +alias( + name = "actionlint", + actual = "@multitool//tools/actionlint:cwd", +) + +alias( + name = "bazelisk", + actual = "@multitool//tools/bazelisk:cwd", +) + +alias( + name = "buildifier", + actual = "@multitool//tools/buildifier:cwd", +) + +alias( + name = "ruff", + actual = "@multitool//tools/ruff:cwd", +) + +alias( + name = "shellcheck", + actual = "@multitool//tools/shellcheck:cwd", +) + +alias( + name = "starpls", + actual = "@multitool//tools/starpls:cwd", +) + +alias( + name = "uv", + actual = "@multitool//tools/uv:cwd", +) + +alias( + name = "uvx", + actual = "@multitool//tools/uvx:cwd", +) + +alias( + name = "yamlfmt", + actual = "@multitool//tools/yamlfmt:cwd", +) diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..df64898 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,328 @@ + + +# Tooling Strategy: Reproducible CLI Tools Across Development Environments + +> This document complements the general infrastructure direction defined in +> [DR-001 Infrastructure Design Decision](https://eclipse-score.github.io/score/main/design_decisions/DR-001-infra.html) +> and specifies how CLI tooling is provided across environments. + +## Purpose + +We provide selected CLI tools such as `actionlint` and `shellcheck` in a reproducible way across supported development environments. + +The goal is simple: + +- same tool versions +- same behavior +- same results + +independent of how developers choose to work. + +--- + +## Strategy + +We support two ways to access the same tooling: + +- **DevContainer** +- **Bazel via `rules_multitool`** + +Both are supported intentionally. + +Not all developers work the same way. Some prefer a fully managed environment, others prefer to stay on their host system. Both workflows exist in practice, and both need to produce identical results. + +![Tooling architecture](arch.svg) + +--- + +## Design Principle + +> Reproducibility is required. +> The execution path is a developer choice. + +This means: + +- no reliance on system-installed tools +- no hidden dependencies +- no environment-specific behavior + +--- + +## DevContainer + +The DevContainer provides: + +- a ready-to-use environment +- minimal setup effort +- predictable tooling + +For many developers, this is the most straightforward option. + +--- + +## Bazel-Based Tool Access + +We additionally expose tools via Bazel using [`rules_multitool`](https://github.com/bazel-contrib/rules_multitool). + +Example usage: +- `bazel run //tools:actionlint` +- `bazel run //tools:shellcheck` + +This exists primarily to support workflows outside the DevContainer. + +It allows: + +- reproducible tool execution on the host +- consistent versions across platforms +- alignment with CI execution + +At the same time, invoking standalone tools through a build system is not always the most ergonomic experience. The setup therefore focuses on making this path reliable rather than minimal. + +--- + +## Why We Support Both + +In practice: + +- some developers use the DevContainer +- some developers do not +- some switch between both depending on the task + +Relying on only one of these paths would either: + +- reduce adoption (DevContainer-only), or +- introduce inconsistencies (native-only) + +Supporting both allows flexibility without sacrificing consistency. + +--- + +## Why `rules_multitool` + +We use [`rules_multitool`](https://github.com/bazel-contrib/rules_multitool) to provide: + +- pinned tool versions +- checksum verification +- platform-specific binaries (Linux x64, macOS arm64) +- a uniform way to expose CLI tools via Bazel + +This is particularly useful for standalone tools such as: + +- `actionlint` +- `shellcheck` + +The alternative would be to manually maintain platform mappings, download logic, and wrappers for each tool. At scale, that quickly turns into a parallel infrastructure effort. + +--- + +## Why This Approach + +This setup reflects the actual constraints: + +- large number of users +- multiple host platforms +- mixed development workflows +- need for consistent results across local and CI + +A single enforced workflow would simplify the model, but would not match how the system is used in reality. + +--- + +## Alternatives Considered + +### DevContainer only + +Conceptually simple, but assumes universal adoption. In practice, that assumption does not hold, leading to gaps in reproducibility. + +--- + +### Bazel toolchains + +Technically correct and very powerful, but introduce significantly more complexity than needed for standalone CLI tools. + +--- + +## Why Use a Niche Solution + +`rules_multitool` is not widely used, and that is expected. + +Most teams: + +- operate on a single platform (usually Linux) +- rely on CI-only validation +- accept minor inconsistencies in local setups + +Under those conditions, simpler approaches are sufficient. + +Our setup differs: + +- cross-platform development (Linux + macOS ARM) +- large team size +- frequent local execution of tools +- low tolerance for inconsistencies + +In this context, reproducibility becomes more important than minimizing tooling layers. + +--- + +## Source of Truth + +For tools downloaded directly from upstream release artifacts that participate +in the shared lockfile-based setup, the authoritative metadata lives in the +`tools/lockfiles/*.lock.json` files. + +These lockfiles define: + +- supported platforms +- download URLs +- checksums +- archive or package layout + +Both Bazel via `rules_multitool` and the DevContainer installation scripts +consume the same lockfiles. + +Feature installation scripts must not duplicate version, URL, or checksum data +for these tools. + +Tools that are currently still managed directly inside a feature script, or via +the distribution package manager, remain managed elsewhere. + +--- + +## Using From Another Repository + +There are two supported Bazel usage patterns for consumers outside this +repository. + +### Option 1: Reuse the exported tool targets directly + +If another repository wants to use the exact targets defined here, it can depend +on this module and run the tools through external labels. + +Consumer `MODULE.bazel`: + +```starlark +module(name = "consumer") + +bazel_dep(name = "score_devcontainer", version = "1.4.1") +``` + +Then run the tools through the exported targets from this repository: + +- `bazel run @score_devcontainer//tools:actionlint -- --version` +- `bazel run @score_devcontainer//tools:shellcheck -- --version` +- `bazel run @score_devcontainer//tools:ruff -- --version` + +If the consumer wants local target names, it can keep option 1 and add local +aliases on top: + +Consumer `BUILD.bazel`: + +```starlark +alias( + name = "shellcheck", + actual = "@score_devcontainer//tools:shellcheck", +) + +alias( + name = "actionlint", + actual = "@score_devcontainer//tools:actionlint", +) +``` + +Then run: + +- `bazel run //:shellcheck -- --version` +- `bazel run //:actionlint -- --version` + +This is the simplest option if the consumer wants the targets defined here, but +prefers local labels in its own repository. + +### Option 2: Reuse the lockfiles, but define local targets in the consumer + +If another repository wants to keep its own target names, it can import the +lockfiles exported by this repository and create its own `rules_multitool` hub. + +The lockfiles are exported as files from the top-level `tools` package, so the +external labels look like this: + +- `@score_devcontainer//tools:lockfiles/actionlint.lock.json` +- `@score_devcontainer//tools:lockfiles/shellcheck.lock.json` + +Consumer `MODULE.bazel`: + +```starlark +module(name = "consumer") + +bazel_dep(name = "rules_multitool", version = "1.11.1") +bazel_dep(name = "score_devcontainer", version = "1.4.1") + +multitool = use_extension("@rules_multitool//multitool:extension.bzl", "multitool") + +multitool.hub(lockfile = "@score_devcontainer//tools:lockfiles/shellcheck.lock.json") +multitool.hub(lockfile = "@score_devcontainer//tools:lockfiles/actionlint.lock.json") + +use_repo(multitool, "multitool") +register_toolchains("@multitool//toolchains:all") +``` + +Consumer `BUILD.bazel`: + +```starlark +alias( + name = "shellcheck", + actual = "@multitool//tools/shellcheck:cwd", +) + +alias( + name = "actionlint", + actual = "@multitool//tools/actionlint:cwd", +) +``` + +Then run: + +- `bazel run //:shellcheck -- --version` +- `bazel run //:actionlint -- --version` + +This option is useful if the consumer wants to share the pinned tool metadata +but expose its own wrapper targets. + +### Version alignment + +The `score_devcontainer` Bazel module version corresponds to the DevContainer +image version. Repositories that use both the DevContainer and the Bazel module +must pin the same version to ensure identical tool versions in both paths. + +### Notes + +- The lockfile labels above are intended as the cross-repository API for Bazel + consumers. +- The lockfile shell installer in this directory is internal support code for + the DevContainer image build. It is not intended as a stable cross-repository + API. + +--- + +## Summary + +We provide: + +- a **DevContainer** for convenience and quick setup +- **Bazel-based tooling** for reproducible execution outside the container + +This combination allows developers to choose their workflow while ensuring consistent and predictable results across the project. diff --git a/tools/arch.svg b/tools/arch.svg new file mode 100644 index 0000000..1abf659 --- /dev/null +++ b/tools/arch.svg @@ -0,0 +1,75 @@ + + + + Tooling architecture + A shared lockfile catalog feeds DevContainer installation scripts and Bazel rules_multitool targets, giving both execution paths the same tool versions and checksums. + + + + + + + + + + + Shared tool lockfiles + versions, URLs, checksums, platforms + + + DevContainer + feature installers download tools + + + Bazel + rules_multitool exposes targets + + + + + same metadata + same metadata + diff --git a/tools/lockfiles/actionlint.lock.json b/tools/lockfiles/actionlint.lock.json new file mode 100644 index 0000000..9c37306 --- /dev/null +++ b/tools/lockfiles/actionlint.lock.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "actionlint": { + "version": "1.7.7", + "binaries": [ + { + "kind": "archive", + "file": "actionlint", + "url": "https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_darwin_arm64.tar.gz", + "sha256": "2693315b9093aeacb4ebd91a993fea54fc215057bf0da2659056b4bc033873db", + "type": "tar.gz", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "file": "actionlint", + "url": "https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz", + "sha256": "023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757", + "type": "tar.gz", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "file": "actionlint", + "url": "https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_arm64.tar.gz", + "sha256": "401942f9c24ed71e4fe71b76c7d638f66d8633575c4016efd2977ce7c28317d0", + "type": "tar.gz", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/lockfiles/bazelisk.lock.json b/tools/lockfiles/bazelisk.lock.json new file mode 100644 index 0000000..6fd42a5 --- /dev/null +++ b/tools/lockfiles/bazelisk.lock.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "bazelisk": { + "version": "1.27.0", + "binaries": [ + { + "kind": "file", + "url": "https://github.com/bazelbuild/bazelisk/releases/download/v1.27.0/bazelisk-darwin-arm64", + "sha256": "8bf08c894ccc19ef37f286e58184c3942c58cb08da955e990522703526ddb720", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "file", + "url": "https://github.com/bazelbuild/bazelisk/releases/download/v1.27.0/bazelisk-linux-amd64", + "sha256": "e1508323f347ad1465a887bc5d2bfb91cffc232d11e8e997b623227c6b32fb76", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "file", + "url": "https://github.com/bazelbuild/bazelisk/releases/download/v1.27.0/bazelisk-linux-arm64", + "sha256": "bb608519a440d45d10304eb684a73a2b6bb7699c5b0e5434361661b25f113a5d", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/lockfiles/buildifier.lock.json b/tools/lockfiles/buildifier.lock.json new file mode 100644 index 0000000..680c647 --- /dev/null +++ b/tools/lockfiles/buildifier.lock.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "buildifier": { + "version": "8.2.1", + "binaries": [ + { + "kind": "file", + "url": "https://github.com/bazelbuild/buildtools/releases/download/v8.2.1/buildifier-darwin-arm64", + "sha256": "cfab310ae22379e69a3b1810b433c4cd2fc2c8f4a324586dfe4cc199943b8d5a", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "file", + "url": "https://github.com/bazelbuild/buildtools/releases/download/v8.2.1/buildifier-linux-amd64", + "sha256": "6ceb7b0ab7cf66fceccc56a027d21d9cc557a7f34af37d2101edb56b92fcfa1a", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "file", + "url": "https://github.com/bazelbuild/buildtools/releases/download/v8.2.1/buildifier-linux-arm64", + "sha256": "3baa1cf7eb41d51f462fdd1fff3a6a4d81d757275d05b2dd5f48671284e9a1a5", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/lockfiles/ruff.lock.json b/tools/lockfiles/ruff.lock.json new file mode 100644 index 0000000..39a3338 --- /dev/null +++ b/tools/lockfiles/ruff.lock.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "ruff": { + "version": "0.11.13", + "binaries": [ + { + "kind": "archive", + "file": "ruff-aarch64-apple-darwin/ruff", + "url": "https://github.com/astral-sh/ruff/releases/download/0.11.13/ruff-aarch64-apple-darwin.tar.gz", + "sha256": "7d5e8feea7ee5c3962807996cad557e8a0c4d676c1cba6223bfb0e8b2ca07723", + "type": "tar.gz", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "file": "ruff-x86_64-unknown-linux-gnu/ruff", + "url": "https://github.com/astral-sh/ruff/releases/download/0.11.13/ruff-x86_64-unknown-linux-gnu.tar.gz", + "sha256": "01aa32d29d00876b8d1429c617ed63a00b1fc81abfa4183bb05c9cb647fbc3d0", + "type": "tar.gz", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "file": "ruff-aarch64-unknown-linux-gnu/ruff", + "url": "https://github.com/astral-sh/ruff/releases/download/0.11.13/ruff-aarch64-unknown-linux-gnu.tar.gz", + "sha256": "551af2ebc439d8268dcaf871ea60ad035f688728d30943dcbb2bf775e105213e", + "type": "tar.gz", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/lockfiles/shellcheck.lock.json b/tools/lockfiles/shellcheck.lock.json new file mode 100644 index 0000000..7022955 --- /dev/null +++ b/tools/lockfiles/shellcheck.lock.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "shellcheck": { + "version": "0.10.0", + "binaries": [ + { + "kind": "archive", + "file": "shellcheck-v0.10.0/shellcheck", + "url": "https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.darwin.aarch64.tar.xz", + "sha256": "bbd2f14826328eee7679da7221f2bc3afb011f6a928b848c80c321f6046ddf81", + "type": "tar.xz", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "file": "shellcheck-v0.10.0/shellcheck", + "url": "https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz", + "sha256": "6c881ab0698e4e6ea235245f22832860544f17ba386442fe7e9d629f8cbedf87", + "type": "tar.xz", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "file": "shellcheck-v0.10.0/shellcheck", + "url": "https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.aarch64.tar.xz", + "sha256": "324a7e89de8fa2aed0d0c28f3dab59cf84c6d74264022c00c22af665ed1a09bb", + "type": "tar.xz", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/lockfiles/starpls.lock.json b/tools/lockfiles/starpls.lock.json new file mode 100644 index 0000000..0806e21 --- /dev/null +++ b/tools/lockfiles/starpls.lock.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "starpls": { + "version": "0.1.22", + "binaries": [ + { + "kind": "file", + "url": "https://github.com/withered-magic/starpls/releases/download/v0.1.22/starpls-darwin-arm64", + "sha256": "675b7be4554e6c219b6774a6b814ec21061096e08ecdd8b8aeeaf3913eb20a4e", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "file", + "url": "https://github.com/withered-magic/starpls/releases/download/v0.1.22/starpls-linux-amd64", + "sha256": "7c661cdde0d1c026665086d07523d825671e29056276681616bb32d0273c5eab", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "file", + "url": "https://github.com/withered-magic/starpls/releases/download/v0.1.22/starpls-linux-aarch64", + "sha256": "55877ec4c3ff03e1d90d59c76f69a3a144b6c29688747c8ac4d77993e2eef1ad", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/lockfiles/uv.lock.json b/tools/lockfiles/uv.lock.json new file mode 100644 index 0000000..8317747 --- /dev/null +++ b/tools/lockfiles/uv.lock.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "uv": { + "version": "0.10.4", + "binaries": [ + { + "kind": "archive", + "file": "uv-aarch64-apple-darwin/uv", + "url": "https://github.com/astral-sh/uv/releases/download/0.10.4/uv-aarch64-apple-darwin.tar.gz", + "sha256": "a6852e4dc565c8fedcf5adcdf09fca7caf5347739bed512bd95b15dada36db51", + "type": "tar.gz", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "file": "uv-x86_64-unknown-linux-gnu/uv", + "url": "https://github.com/astral-sh/uv/releases/download/0.10.4/uv-x86_64-unknown-linux-gnu.tar.gz", + "sha256": "6b52a47358deea1c5e173278bf46b2b489747a59ae31f2a4362ed5c6c1c269f7", + "type": "tar.gz", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "file": "uv-aarch64-unknown-linux-gnu/uv", + "url": "https://github.com/astral-sh/uv/releases/download/0.10.4/uv-aarch64-unknown-linux-gnu.tar.gz", + "sha256": "c84a6e6405715caa6e2f5ef8e5f29a5d0bc558a954e9f1b5c082b9d4708c222e", + "type": "tar.gz", + "os": "linux", + "cpu": "arm64" + } + ] + }, + "uvx": { + "version": "0.10.4", + "binaries": [ + { + "kind": "archive", + "file": "uv-aarch64-apple-darwin/uvx", + "url": "https://github.com/astral-sh/uv/releases/download/0.10.4/uv-aarch64-apple-darwin.tar.gz", + "sha256": "a6852e4dc565c8fedcf5adcdf09fca7caf5347739bed512bd95b15dada36db51", + "type": "tar.gz", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "file": "uv-x86_64-unknown-linux-gnu/uvx", + "url": "https://github.com/astral-sh/uv/releases/download/0.10.4/uv-x86_64-unknown-linux-gnu.tar.gz", + "sha256": "6b52a47358deea1c5e173278bf46b2b489747a59ae31f2a4362ed5c6c1c269f7", + "type": "tar.gz", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "file": "uv-aarch64-unknown-linux-gnu/uvx", + "url": "https://github.com/astral-sh/uv/releases/download/0.10.4/uv-aarch64-unknown-linux-gnu.tar.gz", + "sha256": "c84a6e6405715caa6e2f5ef8e5f29a5d0bc558a954e9f1b5c082b9d4708c222e", + "type": "tar.gz", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/lockfiles/yamlfmt.lock.json b/tools/lockfiles/yamlfmt.lock.json new file mode 100644 index 0000000..f00e3c6 --- /dev/null +++ b/tools/lockfiles/yamlfmt.lock.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://raw.githubusercontent.com/bazel-contrib/rules_multitool/main/lockfile.schema.json", + "yamlfmt": { + "version": "0.17.0", + "binaries": [ + { + "kind": "archive", + "file": "yamlfmt", + "url": "https://github.com/google/yamlfmt/releases/download/v0.17.0/yamlfmt_0.17.0_Darwin_arm64.tar.gz", + "sha256": "1be37d76a79caa5073ce342de24f7b8b2509c2a482178286f44b72835469052b", + "type": "tar.gz", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "file": "yamlfmt", + "url": "https://github.com/google/yamlfmt/releases/download/v0.17.0/yamlfmt_0.17.0_Linux_x86_64.tar.gz", + "sha256": "e91dd8722001596b8e4777a29d4a526a10ff276c4ff8a5ae39ff59be5a033054", + "type": "tar.gz", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "file": "yamlfmt", + "url": "https://github.com/google/yamlfmt/releases/download/v0.17.0/yamlfmt_0.17.0_Linux_arm64.tar.gz", + "sha256": "ebe78a5547dac68f05a01c9a2845901b3c658095432b107bef3084dfe0b2629d", + "type": "tar.gz", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tools/run_tool.sh b/tools/run_tool.sh new file mode 100755 index 0000000..504547d --- /dev/null +++ b/tools/run_tool.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Unified entry point for running a CLI tool by name. +# Inside a container the tool is expected on PATH; outside, it is resolved via Bazel. +# See tools/README.md for the rationale behind supporting both paths. + +set -euo pipefail + +if [[ "$#" -lt 1 ]]; then + echo "Usage: $0 [args...]" >&2 + exit 2 +fi + +tool_name="$1" +shift + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +repository_root="$(cd "${script_dir}/.." && pwd -P)" + +if { [[ -f /.dockerenv ]] || [[ -f /run/.containerenv ]] || [[ -d /devcontainer ]]; } && + command -v "${tool_name}" >/dev/null 2>&1; then + exec "${tool_name}" "$@" +fi + +if command -v bazel >/dev/null 2>&1; then +cd "${repository_root}" +exec bazel run "//tools:${tool_name}" -- "$@" +fi + +echo "Could not run '${tool_name}': not available on PATH in a container, and bazel was not found." >&2 +exit 127 diff --git a/tools/tool_installer.py b/tools/tool_installer.py new file mode 100755 index 0000000..f660f24 --- /dev/null +++ b/tools/tool_installer.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python3 +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +"""Install pinned tools from the `tools/lockfiles/*.lock.json` catalog. + +Dependency-free (stdlib only) so devcontainer feature installers can use it +without extra packages. + +Usage: + tool_installer.py install shellcheck yamlfmt + tool_installer.py version shellcheck +""" + +# pyright: reportAny=false, reportUnusedCallResult=false, reportExplicitAny=false + +from __future__ import annotations + +import argparse +import hashlib +import json +import platform +import shutil +import sys +import tarfile +import tempfile +import urllib.request +import zipfile +from pathlib import Path +from typing import NotRequired, TypedDict + + +class Binary(TypedDict): + """A single binary entry from a tool's lockfile definition.""" + + os: str + cpu: str + kind: str + url: str + sha256: str + type: NotRequired[str] + file: NotRequired[str] + + +class ToolData(TypedDict): + """Tool metadata from a lockfile entry.""" + + version: NotRequired[str] + binaries: list[Binary] + + +LOCKFILE_ROOT = Path(__file__).resolve().parent / "lockfiles" + + +def _detect_os() -> str: + """Map Python's platform string to the lockfile schema's OS names.""" + system = platform.system() + if system == "Linux": + return "linux" + if system == "Darwin": + return "macos" + raise SystemExit(f"Unsupported OS: {system}") + + +def _detect_cpu() -> str: + """Map Python's machine string to the lockfile schema's CPU names.""" + machine = platform.machine().lower() + if machine in {"x86_64", "amd64"}: + return "x86_64" + if machine in {"arm64", "aarch64"}: + return "arm64" + raise SystemExit(f"Unsupported CPU architecture: {machine}") + + +def _lockfile_path(lockfile: str) -> Path: + """Resolve a lockfile basename like `ruff` to `ruff.lock.json`.""" + return LOCKFILE_ROOT / f"{lockfile}.lock.json" + + +def _load_tool(lockfile: str, tool: str) -> ToolData: + """Load one tool entry from a lockfile and fail with a clear message.""" + with _lockfile_path(lockfile).open(encoding="utf-8") as handle: + data = json.load(handle) + + try: + return data[tool] + except KeyError as exc: + raise SystemExit( + f"Tool '{tool}' not found in lockfile '{lockfile}.lock.json'", + ) from exc + + +def _find_lockfile(tool: str) -> str: + """Find the lockfile basename that declares a tool.""" + for path in sorted(LOCKFILE_ROOT.glob("*.lock.json")): + with path.open(encoding="utf-8") as handle: + data = json.load(handle) + if tool in data: + return path.name.removesuffix(".lock.json") + + raise SystemExit(f"Tool '{tool}' not found in lockfile catalog") + + +def _resolve_lockfile(tool: str, lockfile: str | None = None) -> str: + """Return the lockfile basename for *tool*, auto-detecting when needed.""" + if lockfile is not None: + return lockfile + if _lockfile_path(tool).exists(): + return tool + return _find_lockfile(tool) + + +def _select_binary(tool_data: ToolData, os_name: str, cpu: str) -> Binary: + """Pick the binary entry matching the requested platform.""" + for binary in tool_data["binaries"]: + if binary["os"] == os_name and binary["cpu"] == cpu: + return binary + + raise SystemExit( + f"No binary defined for os={os_name!r}, cpu={cpu!r}", + ) + + +def _cmd_version(args: argparse.Namespace) -> int: + """Print the declared version for one tool.""" + args.lockfile = _resolve_lockfile(args.tool, args.lockfile) + tool_data = _load_tool(args.lockfile, args.tool) + version = tool_data.get("version") + if version is None: + raise SystemExit( + f"Tool '{args.tool}' in '{args.lockfile}.lock.json' does not define a version", + ) + print(version) + return 0 + + +def _place_binary(source: Path, destination: Path) -> None: + """Copy a file to its destination with executable permissions.""" + destination.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(source, destination) + destination.chmod(0o755) + + +def _extract_member( + binary: Binary, archive_path: Path, out_path: Path, tool: str +) -> None: + """Extract one member from an archive and write it to *out_path*.""" + archive_type = binary.get("type", "") + member = binary.get("file") + if member is None: + raise SystemExit(f"Binary entry for {tool} does not define 'file' field") + + if archive_type in ("tar.gz", "tgz", "tar.xz", "txz"): + with tarfile.open(archive_path) as tf: + reader = tf.extractfile(member) + if reader is None: + raise SystemExit(f"Cannot extract '{member}' from archive for {tool}") + out_path.write_bytes(reader.read()) + elif archive_type == "zip": + with zipfile.ZipFile(archive_path) as zf: + out_path.write_bytes(zf.read(member)) + else: + raise SystemExit(f"Unsupported archive type '{archive_type}' for {tool}") + + +def _cmd_install(args: argparse.Namespace) -> int: + """Download, verify, and install tools from the lockfile catalog.""" + dest_dir = Path(args.destination) + + for tool in args.tools: + lockfile = _resolve_lockfile(tool, args.lockfile) + tool_data = _load_tool(lockfile, tool) + binary = _select_binary(tool_data, args.os, args.cpu) + + kind = binary["kind"] + url = binary["url"] + expected_sha256 = binary["sha256"] + destination = dest_dir / tool + + with tempfile.TemporaryDirectory() as tmp: + tmp = Path(tmp) + download = tmp / "download" + + urllib.request.urlretrieve(url, download) + + actual = hashlib.sha256(download.read_bytes()).hexdigest() + if actual != expected_sha256: + raise SystemExit( + f"Checksum mismatch for {tool}: " + + f"expected {expected_sha256}, got {actual}" + ) + + if kind == "file": + _place_binary(download, destination) + elif kind == "archive": + extracted = tmp / "extracted" + _extract_member(binary, download, extracted, tool) + if extracted.exists(): + _place_binary(extracted, destination) + else: + raise SystemExit(f"Unsupported kind '{kind}' for {tool}") + + return 0 + + +def _build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="Install pinned tools from multitool-compatible lockfiles.", + ) + subparsers = parser.add_subparsers(dest="command", required=True) + + install_parser = subparsers.add_parser( + "install", + help="Download, verify, and install tools.", + ) + install_parser.add_argument("tools", nargs="+") + install_parser.add_argument("--lockfile") + install_parser.add_argument("--destination", default="/usr/local/bin") + install_parser.add_argument("--os", default=_detect_os()) + install_parser.add_argument("--cpu", default=_detect_cpu()) + install_parser.set_defaults(func=_cmd_install) + + version_parser = subparsers.add_parser( + "version", + help="Print the declared version for a tool.", + ) + version_parser.add_argument("tool") + version_parser.add_argument("--lockfile") + version_parser.set_defaults(func=_cmd_version) + + return parser + + +def main(argv: list[str] | None = None) -> int: + parser = _build_parser() + args = parser.parse_args(argv) + return args.func(args) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/s-core-devcontainer/.devcontainer/s-core-local/versions.sh b/tools/versions.sh similarity index 100% rename from src/s-core-devcontainer/.devcontainer/s-core-local/versions.sh rename to tools/versions.sh