diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6bb8e41e..233b98e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,10 @@ # How to Contribute +## Windows + +If running this repo on Windows, run `configure.bat` to set it up before running +any bazel commands. This removes features that are not supported yet on this platform. + ## Formatting Starlark files should be formatted by buildifier. diff --git a/MODULE.bazel b/MODULE.bazel index 7727f6e0..03e8b75f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -15,7 +15,7 @@ bazel_dep(name = "aspect_rules_js", version = "1.40.0") bazel_dep(name = "bazel_skylib", version = "1.4.2") bazel_dep(name = "platforms", version = "0.0.7") bazel_dep(name = "rules_multirun", version = "0.9.0") -bazel_dep(name = "rules_multitool", version = "0.4.0") +bazel_dep(name = "rules_multitool", version = "0.8.0") # Needed in the root because we dereference ProtoInfo in our aspect impl bazel_dep(name = "rules_proto", version = "6.0.0") diff --git a/README.md b/README.md index bd090872..df9fe24c 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ New tools are being added frequently, so check this page again! | Language | Formatter | Linter(s) | | ---------------------- | --------------------- | ---------------- | -| C / C++ | [clang-format] | ([#112]) | +| C / C++ | [clang-format] | [clang-tidy] | | Cuda | [clang-format] | | | CSS, Less, Sass | [Prettier] | | | Go | [gofmt] or [gofumpt] | | @@ -68,7 +68,7 @@ New tools are being added frequently, so check this page again! [shellcheck]: https://www.shellcheck.net/ [shfmt]: https://github.com/mvdan/sh [clang-format]: https://clang.llvm.org/docs/ClangFormat.html -[#112]: https://github.com/aspect-build/rules_lint/issues/112 +[clang-tidy]: https://clang.llvm.org/extra/clang-tidy/ [vale]: https://vale.sh/ [yamlfmt]: https://github.com/google/yamlfmt [rustfmt]: https://rust-lang.github.io/rustfmt diff --git a/configure.bat b/configure.bat new file mode 100644 index 00000000..4b51916a --- /dev/null +++ b/configure.bat @@ -0,0 +1,11 @@ +:: run this on Windows to set up example for use +@echo Configuring example for Windows +:: aspect-cli doesn't support windows, so disable it +del %~dp0.bazeliskrc +del %~dp0example\.bazeliskrc +:: ../.bazelversion syntax not supported by windows bazelisk +del %~dp0example\.bazelversion +copy %~dp0.bazelversion %~dp0example +:: copy clang-tidy and clang-format +copy "%USERPROFILE%\Downloads\clang+llvm-18.1.6-x86_64-pc-windows-msvc.tar\clang+llvm-18.1.6-x86_64-pc-windows-msvc\bin\clang-tidy.exe" %~dp0example\tools\lint\ +copy "%USERPROFILE%\Downloads\clang+llvm-18.1.6-x86_64-pc-windows-msvc.tar\clang+llvm-18.1.6-x86_64-pc-windows-msvc\bin\clang-format.exe" %~dp0example\tools\lint\ diff --git a/example/MODULE.bazel b/example/MODULE.bazel index 1a6c9461..23e65886 100644 --- a/example/MODULE.bazel +++ b/example/MODULE.bazel @@ -1,20 +1,26 @@ "Bazel dependencies" +# todo, remove this comment +#WARNING: For repository 'bazel_skylib', the root module requires module version bazel_skylib@1.4.2, but got bazel_skylib@1.5.0 in the resolved dependency graph. +#WARNING: For repository 'rules_java', the root module requires module version rules_java@5.5.0, but got rules_java@7.4.0 in the resolved dependency graph. +#WARNING: For repository 'rules_jvm_external', the root module requires module version rules_jvm_external@4.5, but got rules_jvm_external@5.3 in the resolved dependency graph. +#WARNING: For repository 'rules_python', the root module requires module version rules_python@0.26.0, but got rules_python@0.27.1 in the resolved dependency graph. + bazel_dep(name = "aspect_rules_lint", version = "0.0.0") bazel_dep(name = "aspect_bazel_lib", version = "2.7.7") bazel_dep(name = "aspect_rules_js", version = "2.0.0-rc0") bazel_dep(name = "aspect_rules_ts", version = "3.0.0-rc0") -bazel_dep(name = "rules_buf", version = "0.2.0") -bazel_dep(name = "bazel_skylib", version = "1.4.2") -bazel_dep(name = "toolchains_llvm", version = "0.10.3") +bazel_dep(name = "rules_buf", version = "0.3.0") +bazel_dep(name = "bazel_skylib", version = "1.5.0") +bazel_dep(name = "toolchains_llvm", version = "1.0.0") bazel_dep(name = "toolchains_protoc", version = "0.3.0") -bazel_dep(name = "rules_java", version = "5.5.0") -bazel_dep(name = "rules_jvm_external", version = "4.5") +bazel_dep(name = "rules_java", version = "7.4.0") +bazel_dep(name = "rules_jvm_external", version = "5.3") bazel_dep(name = "rules_go", version = "0.42.0", repo_name = "io_bazel_rules_go") bazel_dep(name = "rules_proto", version = "6.0.0") -bazel_dep(name = "rules_python", version = "0.26.0") +bazel_dep(name = "rules_python", version = "0.27.1") bazel_dep(name = "rules_rust", version = "0.45.1") -bazel_dep(name = "buildifier_prebuilt", version = "6.3.3") +bazel_dep(name = "buildifier_prebuilt", version = "6.4.0") bazel_dep(name = "platforms", version = "0.0.8") bazel_dep(name = "rules_kotlin", version = "1.9.0") bazel_dep(name = "rules_cc", version = "0.0.9") @@ -24,19 +30,46 @@ local_path_override( path = "..", ) +# chris overrides +# Configure and register the toolchain. +git_override( + module_name = "toolchains_llvm", + commit = "f2de4fc207ad0ad46da25969300e17b3ac7a2536", + remote = "https://github.com/peakschris/toolchains_llvm", +) + +git_override( + module_name = "rules_multitool", + commit = "45ad7ae3e157e4922b80140afb8763c3bf1672f4", + remote = "https://github.com/theoremlp/rules_multitool", +) + +git_override( + module_name = "rules_multirun", + commit = "e75bb2b1217da35f357773304442e58b7f306dff", + remote = "https://github.com/peakschris/rules_multirun", +) + +git_override( + module_name = "rules_buf", + commit = "a422f4ec6106e513c201992214321ea6b1765beb", + remote = "https://github.com/bufbuild/rules_buf", +) + rules_ts_ext = use_extension("@aspect_rules_ts//ts:extensions.bzl", "ext") rules_ts_ext.deps() use_repo(rules_ts_ext, "npm_typescript") -# Configure and register the toolchain. + llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") llvm.toolchain( llvm_versions = { - "": "16.0.0", + "": "18.1.4", "darwin-x86_64": "15.0.7", }, ) use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm") +#register_toolchains("@llvm_toolchain//:all") npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm") npm.npm_translate_lock( diff --git a/example/README.md b/example/README.md index dc7988ba..54eebfe5 100644 --- a/example/README.md +++ b/example/README.md @@ -5,6 +5,8 @@ It contains sources in multiple languages. ### With Aspect CLI +_linux/mac only_ + Run `bazel lint src:all` > If the 'lint' command isn't found, make sure you have a new enough version of Aspect CLI. @@ -33,6 +35,34 @@ From /shared/cache/bazel/user_base/b6913b1339fd4037a680edabc6135c1d/execroot/_ma ``` +## Windows: + +### Setup +If running this repo on Windows, run `configure.bat` to set it up before running +any bazel commands. This removes features that are not supported yet on this platform. + +### Run +Aspect CLI is not supported [[aspect-cli#598](https://github.com/aspect-build/aspect-cli/issues/598)]. Instead, use the shell script: + +- ensure jq is on the path +- `set BAZEL_SH=c:\msys64\usr\bin\bash.exe` _git bash has issues_ +- rules_lint/example> `bash lint.sh src:all` + +linters that are not yet supported OOTB on Windows are not included in lint.sh. You may still be able to use them on Windows by manually configuring +their binaries and providing them to the appropriate rules. + +#### Linter issues on Windows: + +These linters do not currently work OOTB: +- buf - the buf toolchain doesn't auto-expose its tools [[rules_buf#78](https://github.com/bufbuild/rules_buf/issues/78)] +- eslint - depends on rules_js which doesn't currently support windows due to an issue with bsdtar.exe [[rules_js#1739](https://github.com/aspect-build/rules_js/issues/1739)] +- ktlint - also fails due to bsdtar.exe + +Whilst these linters do not work here OOTB, you may be able to get them to work by providing your own versions to the toolchain. + +#### Format issues on Windows: +- format does not currently work due to an issue with rules_multirun: [[rules_multirun#56](https://github.com/keith/rules_multirun/issues/56)] + ## ESLint This folder simply follows the instructions at https://typescript-eslint.io/getting-started diff --git a/example/buf.yaml b/example/buf.yaml index 29fd418d..8c4a662f 100644 --- a/example/buf.yaml +++ b/example/buf.yaml @@ -1,4 +1,4 @@ version: v1 lint: use: - - IMPORT_USED + - DEFAULT diff --git a/example/lint.sh b/example/lint.sh index f4e6c199..d155b7ee 100755 --- a/example/lint.sh +++ b/example/lint.sh @@ -35,13 +35,13 @@ esac args=() if [ $machine == "Windows" ]; then # avoid missing linters on windows platform - args=("--aspects=$(echo //tools/lint:linters.bzl%{flake8,pmd,ruff,vale,clang_tidy} | tr ' ' ',')") + args=("--aspects=$(echo //tools/lint:linters.bzl%{buf,flake8,pmd,ruff,shellcheck,vale,clang_tidy} | tr ' ' ',')") else args=("--aspects=$(echo //tools/lint:linters.bzl%{buf,eslint,flake8,ktlint,pmd,ruff,shellcheck,vale,clang_tidy} | tr ' ' ',')") fi # NB: perhaps --remote_download_toplevel is needed as well with remote execution? -args+=( +args+= # Allow lints of code that fails some validation action # See https://github.com/aspect-build/rules_ts/pull/574#issuecomment-2073632879 "--norun_validations" diff --git a/example/src/BUILD.bazel b/example/src/BUILD.bazel index fdd06e61..541885a1 100644 --- a/example/src/BUILD.bazel +++ b/example/src/BUILD.bazel @@ -35,6 +35,11 @@ proto_library( deps = [":unused"], ) +proto_library( + name = "hello_proto", + srcs = ["hello.proto"], +) + py_library( name = "unused_import", srcs = ["unused_import.py"], diff --git a/example/src/hello.proto b/example/src/hello.proto new file mode 100644 index 00000000..40440eeb --- /dev/null +++ b/example/src/hello.proto @@ -0,0 +1,29 @@ +// src/hello.proto:1:1:Enum value name "RAINY" should be prefixed with "CONDITION_". +// src/hello.proto:1:1:Enum value name "SUNNY" should be prefixed with "CONDITION_". +// src/hello.proto:1:1:Enum zero value name "SUNNY" should be suffixed with "_UNSPECIFIED". +// src/hello.proto:1:1:Files with package "weather" must be within a directory "weather" relative to root but were in directory "src". +// src/hello.proto:1:1:Package name "weather" should be suffixed with a correctly formed version, such as "weather.v1". +// src/hello.proto:1:1:RPC request type "Location" should be named "GetWeatherRequest" or "WeatherServiceGetWeatherRequest". + +syntax = "proto3"; + +package weather; + +enum Condition { + SUNNY = 0; + RAINY = 1; +} + +message Location { + float latitude = 1; + float longitude = 2; +} + +message GetWeatherResponse { + float temperature = 1; + Condition conditions = 2; +} + +service WeatherService { + rpc GetWeather (Location) returns (GetWeatherResponse); +} diff --git a/example/tools/format/BUILD.bazel b/example/tools/format/BUILD.bazel index ae36f668..9de1700a 100644 --- a/example/tools/format/BUILD.bazel +++ b/example/tools/format/BUILD.bazel @@ -43,6 +43,7 @@ alias( actual = select({ "@bazel_tools//src/conditions:linux": "@swiftformat", "@bazel_tools//src/conditions:darwin": "@swiftformat_mac", + "@bazel_tools//src/conditions:windows": "@swiftformat_windows", }), ) @@ -53,8 +54,16 @@ java_binary( runtime_deps = ["@maven//:org_scalameta_scalafmt_cli_2_13"], ) -format_multirun( +alias( name = "format", + actual = select({ + "@bazel_tools//src/conditions:windows": "format_windows", + "//conditions:default": "format_default", + }), +) + +format_multirun( + name = "format_default", cc = "@llvm_toolchain_llvm//:bin/clang-format", css = ":prettier", cuda = "@llvm_toolchain_llvm//:bin/clang-format", @@ -80,6 +89,13 @@ format_multirun( yaml = "@aspect_rules_lint//format:yamlfmt", ) +format_multirun( + name = "format_windows", + cc = "@llvm_toolchain_llvm//:bin/clang-format.exe", + cuda = "@llvm_toolchain_llvm//:bin/clang-format.exe", + visibility = ["//:__subpackages__"], +) + format_test( name = "format_test", size = "small", diff --git a/example/tools/lint/BUILD.bazel b/example/tools/lint/BUILD.bazel index 9d0aa219..585aa783 100644 --- a/example/tools/lint/BUILD.bazel +++ b/example/tools/lint/BUILD.bazel @@ -79,10 +79,7 @@ native_binary( "@bazel_tools//src/conditions:linux_aarch64": "@llvm_toolchain_llvm//:bin/clang-tidy", "@bazel_tools//src/conditions:darwin_x86_64": "@llvm_toolchain_llvm//:bin/clang-tidy", "@bazel_tools//src/conditions:darwin_arm64": "@llvm_toolchain_llvm//:bin/clang-tidy", - # llvm_toolchain doesn't support windows: https://github.com/bazel-contrib/toolchains_llvm/issues/4 - # as a workaround, you can download exes from - # https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.6 and make available locally. - "@bazel_tools//src/conditions:windows_x64": "clang-tidy.exe", + "@bazel_tools//src/conditions:windows_x64": "@llvm_toolchain_llvm//:bin/clang-tidy.exe", }, ), out = "clang_tidy", diff --git a/format/multitool.lock.json b/format/multitool.lock.json index 84908303..6e90b19d 100644 --- a/format/multitool.lock.json +++ b/format/multitool.lock.json @@ -26,9 +26,16 @@ { "kind": "file", "url": "https://github.com/mvdan/gofumpt/releases/download/v0.6.0/gofumpt_v0.6.0_darwin_amd64", - "sha256": "59e6047b3fa2fb65b60cf7f8be9b77cf6b31b428a9a24042ce29e85140868036", + "sha256": "e7e188a93555b3172601170ce454aceb474cb139d935fd7b5d4ebec9ca158db1", "os": "macos", "cpu": "x86_64" + }, + { + "kind": "file", + "url": "https://github.com/mvdan/gofumpt/releases/download/v0.6.0/gofumpt_v0.6.0_windows_amd64.exe", + "sha256": "e7e188a93555b3172601170ce454aceb474cb139d935fd7b5d4ebec9ca158db1", + "os": "windows", + "cpu": "x86_64" } ] }, @@ -65,6 +72,22 @@ "sha256": "76901637f60589bb9bf91b3481d4aecbc31efcd35ca99ae72bcb510b00270ad9", "os": "macos", "cpu": "x86_64" + }, + { + "kind": "archive", + "url": "https://github.com/google/go-jsonnet/releases/download/v0.20.0/go-jsonnet_0.20.0_Windows_arm64.tar.gz", + "file": "jsonnetfmt", + "sha256": "76901637f60589bb9bf91b3481d4aecbc31efcd35ca99ae72bcb510b00270ad9", + "os": "windows", + "cpu": "arm64" + }, + { + "kind": "archive", + "url": "https://github.com/google/go-jsonnet/releases/download/v0.20.0/go-jsonnet_0.20.0_Windows_x86_64.tar.gz", + "file": "jsonnetfmt", + "sha256": "82440a646a8d29487a243afc880db245f612a205d3eccbb900bc76d7a4049ad1", + "os": "windows", + "cpu": "x86_64" } ] }, @@ -97,6 +120,20 @@ "sha256": "c0218b47a0301bb006f49fad85d2c08de23df303472834faf5639d04121320f8", "os": "macos", "cpu": "x86_64" + }, + { + "kind": "file", + "url": "https://github.com/google/go-jsonnet/releases/download/v0.20.0/go-jsonnet_0.20.0_Windows_arm64.tar.gz", + "sha256": "1481240d2a90d4f0b530688d76d4f9117d17a756b6027cfa42b96f0707317f83", + "os": "windows", + "cpu": "arm64" + }, + { + "kind": "file", + "url": "https://github.com/google/go-jsonnet/releases/download/v0.20.0/go-jsonnet_0.20.0_Windows_x86_64.tar.gz", + "sha256": "82440a646a8d29487a243afc880db245f612a205d3eccbb900bc76d7a4049ad1", + "os": "windows", + "cpu": "x86_64" } ] }, @@ -133,6 +170,14 @@ "sha256": "0eaf64e28f82e2defd06f7a6f3187d8cea03d5d9fcd2af54f549a6c32d6833f7", "os": "macos", "cpu": "x86_64" + }, + { + "kind": "archive", + "url": "https://releases.hashicorp.com/terraform/1.7.5/terraform_1.7.5_windows_amd64.zip", + "file": "terraform", + "sha256": "9b7be6ae159191ec1f4b5b9d27529ae5243e41020fb545c0041235bec8d92269", + "os": "windows", + "cpu": "x86_64" } ] }, @@ -169,6 +214,22 @@ "sha256": "499ad4ff8b842981d464b474e868905752833d55c71904ef019967229432da93", "os": "macos", "cpu": "x86_64" + }, + { + "kind": "archive", + "url": "https://github.com/google/yamlfmt/releases/download/v0.12.1/yamlfmt_0.12.1_Windows_arm64.tar.gz", + "file": "yamlfmt", + "sha256": "499ad4ff8b842981d464b474e868905752833d55c71904ef019967229432da93", + "os": "windows", + "cpu": "arm64" + }, + { + "kind": "archive", + "url": "https://github.com/google/yamlfmt/releases/download/v0.12.1/yamlfmt_0.12.1_Windows_x86_64.tar.gz", + "file": "yamlfmt.exe", + "sha256": "904d07c75f18585f22b9e4f45a0d40619827b361721ff3e0ef90f2c13d503bdc", + "os": "windows", + "cpu": "x86_64" } ] } diff --git a/format/repositories.bzl b/format/repositories.bzl index c9b3b35d..1c49a29d 100644 --- a/format/repositories.bzl +++ b/format/repositories.bzl @@ -58,8 +58,8 @@ def fetch_swiftformat(): name = "swiftformat", build_file_content = "filegroup(name = \"swiftformat\", srcs=[\"swiftformat_linux\"], visibility=[\"//visibility:public\"])", patch_cmds = ["chmod u+x swiftformat_linux"], - sha256 = "f62813980c2848cb1941f1456a2a06251c2e2323183623760922058b98c70745", - url = "https://github.com/nicklockwood/SwiftFormat/releases/download/0.49.17/swiftformat_linux.zip", + #sha256 = "f62813980c2848cb1941f1456a2a06251c2e2323183623760922058b98c70745", + url = "https://github.com/nicklockwood/SwiftFormat/releases/download/0.54.0/swiftformat_linux.zip", ) http_archive( @@ -70,6 +70,13 @@ def fetch_swiftformat(): "if command -v xattr > /dev/null; then xattr -c swiftformat; fi", "chmod u+x swiftformat", ], - sha256 = "978eaffdc3716bbc0859aecee0d83875cf3ab8d8725779448f0035309d9ad9f3", - url = "https://github.com/nicklockwood/SwiftFormat/releases/download/0.49.17/swiftformat.zip", + #sha256 = "978eaffdc3716bbc0859aecee0d83875cf3ab8d8725779448f0035309d9ad9f3", + url = "https://github.com/nicklockwood/SwiftFormat/releases/download/0.54.0/swiftformat.zip", + ) + + http_archive( + name = "swiftformat_windows", + build_file_content = "filegroup(name = \"swiftformat_windows\", srcs=[\"swiftformat.exe\"], visibility=[\"//visibility:public\"])", + #sha256 = "978eaffdc3716bbc0859aecee0d83875cf3ab8d8725779448f0035309d9ad9f3", + url = "https://github.com/nicklockwood/SwiftFormat/releases/download/0.54.0/swiftformat_windows.exe.zip", ) diff --git a/lint/clang_tidy.bzl b/lint/clang_tidy.bzl index a885d69f..9e1b3058 100644 --- a/lint/clang_tidy.bzl +++ b/lint/clang_tidy.bzl @@ -403,3 +403,4 @@ def lint_clang_tidy_aspect(binary, configs = [], global_config = [], header_filt toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], fragments = ["cpp"], ) + diff --git a/lint/clang_versions.bzl b/lint/clang_versions.bzl new file mode 100644 index 00000000..a9b3d9b0 --- /dev/null +++ b/lint/clang_versions.bzl @@ -0,0 +1,3 @@ +"This file is automatically updated by mirror_clang.sh" +CLANG_VERSIONS = { +} diff --git a/lint/mirror_clang.sh b/lint/mirror_clang.sh new file mode 100755 index 00000000..1274e6bb --- /dev/null +++ b/lint/mirror_clang.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -x +set -o errexit -o nounset -o pipefail + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +RELEASES=$(mktemp) +RAW=$(mktemp) + +REPOSITORY=${1:-"llvm/llvm-project"} +JQ_FILTER=\ +'map( + { + "key": .tag_name, + "value": .assets + | map(select((.name | contains("vale_")) and (.name | endswith("checksums.txt") | not) )) + | map({ + "key": .name | capture("clang+llvm-[0-9\\.]+-(?.*)\\.(tar\\.gz|tar\\.xz)") | .platform, + "value": .name, + }) + | from_entries + } +) | from_entries' + +SHA256_FILTER=\ +' +map( + select(.name == $tag) + | .assets + | map(.browser_download_url)[] + | select(endswith("checksums.txt")) +)[] +' + +curl > $RELEASES \ + --silent \ + --header "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/${REPOSITORY}/releases?per_page=1 + +jq "$JQ_FILTER" <$RELEASES >$RAW + +# Combine the new versions with the existing ones. +# New versions should appear first, but existing content should overwrite new +CURRENT=$(mktemp) +python3 -c "import json; exec(open('$SCRIPT_DIR/clang_versions.bzl').read()); print(json.dumps(CLANG_VERSIONS))" > $CURRENT +OUT=$(mktemp) +jq --slurp '.[0] * .[1]' $RAW $CURRENT > $OUT + +FIXED=$(mktemp) +# Replace placeholder sha256 URLs with their content +for tag in $(jq -r 'keys | .[]' < $OUT); do + # Download checksums for this tag + # Note: this is wasteful; we will curl for sha256 files even if the CURRENT content already had resolved them + for sha256url in $(jq --arg tag $tag -r "$SHA256_FILTER" < $RELEASES); do + sha256=$(curl --silent --location $sha256url | awk '{print $1}') + jq ".[\"$tag\"] |= with_entries(.value = (if .value == \"$sha256url\" then \"$sha256\" else .value end))" < $OUT > $FIXED + mv $FIXED $OUT + done +done + +# Overwrite the file with updated content +( + echo '"This file is automatically updated by mirror_clang.sh"' + echo -n "CLANG_VERSIONS = " + cat $OUT +)>$SCRIPT_DIR/clang_versions.bzl diff --git a/lint/multitool.lock.json b/lint/multitool.lock.json index 18620587..e3135c31 100644 --- a/lint/multitool.lock.json +++ b/lint/multitool.lock.json @@ -33,6 +33,14 @@ "sha256": "ef27684f23279d112d8ad84e0823642e43f838993bbb8c0963db9b58a90464c2", "os": "macos", "cpu": "x86_64" + }, + { + "kind": "archive", + "url": "https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.zip", + "file": "shellcheck.exe", + "sha256": "eb6cd53a54ea97a56540e9d296ce7e2fa68715aa507ff23574646c1e12b2e143", + "os": "windows", + "cpu": "x86_64" } ] }