Compare commits

...

35 Commits

Author SHA1 Message Date
Taiki Endo
da41fb311f Release 2.47.21 2025-01-21 20:14:58 +09:00
Taiki Endo
82214f4be3 Update knope@latest to 0.18.3 2025-01-21 11:03:20 +09:00
Taiki Endo
5c7ec4ff6e Release 2.47.20 2025-01-21 10:57:05 +09:00
Taiki Endo
401fb25d5a Update wasmtime@latest to 29.0.0 2025-01-21 06:12:09 +09:00
Taiki Endo
24758ef6e7 Release 2.47.19 2025-01-21 00:30:57 +09:00
Taiki Endo
24ac8132a4 Update trunk@latest to 0.21.6 2025-01-21 00:13:29 +09:00
Taiki Endo
b4c4e2f7c4 Update parse-changelog@latest to 0.6.11 2025-01-20 06:11:22 +09:00
Taiki Endo
a7adeb15af Release 2.47.18 2025-01-19 18:15:15 +09:00
Taiki Endo
25b04c0ead Update cargo-deny@latest to 0.16.4 2025-01-19 18:14:28 +09:00
Taiki Endo
c39a412ce9 Update cargo-binstall@latest to 1.10.22 2025-01-19 18:14:28 +09:00
Taiki Endo
fe065954f6 Release 2.47.17 2025-01-19 14:09:43 +09:00
Taiki Endo
aaa64a3351 Update cargo-audit@latest to 0.21.1 2025-01-19 13:13:08 +09:00
Taiki Endo
f99317473f Release 2.47.16 2025-01-19 03:16:29 +09:00
Taiki Endo
3523902f5a Update cargo-make@latest to 0.37.24 2025-01-19 03:15:07 +09:00
Taiki Endo
e6e3706b36 Update readme 2025-01-17 16:45:12 +09:00
Taiki Endo
9469185794 Format shell scripts with indent_size = 2 to match scripts in CI config 2025-01-17 16:44:56 +09:00
Taiki Endo
1b8d452217 ci: Test ubuntu-22.04-arm and ubuntu-24.04-arm
https://github.blog/changelog/2025-01-16-linux-arm64-hosted-runners-now-available-for-free-in-public-repositories-public-preview/
2025-01-17 16:35:45 +09:00
Taiki Endo
d125c0a835 Release 2.47.15 2025-01-17 02:02:24 +09:00
Taiki Endo
319a0f2f5f Update cargo-tarpaulin@latest to 0.31.5 2025-01-17 01:46:51 +09:00
Taiki Endo
0fe4860065 Update cargo-llvm-cov@latest to 0.6.16 2025-01-17 01:46:51 +09:00
Taiki Endo
44e8874873 Update cargo-hack@latest to 0.6.34 2025-01-17 01:46:51 +09:00
Taiki Endo
5f3e9b7a2d ci: Disable buggy dependabot grouped update 2025-01-16 22:19:33 +09:00
Taiki Endo
55912949de Update cspell dictionary 2025-01-16 21:35:10 +09:00
Taiki Endo
e26ea2a159 Release 2.47.14 2025-01-16 10:43:59 +09:00
Taiki Endo
00b370abc3 Update cargo-nextest@latest to 0.9.88 2025-01-16 09:36:49 +09:00
Taiki Endo
6ae49f1b8b Release 2.47.13 2025-01-15 10:55:04 +09:00
Taiki Endo
2967b5da19 Update wasmtime@latest to 28.0.1 2025-01-15 09:36:31 +09:00
Taiki Endo
5a32d87288 Update release-plz@latest to 0.3.113 2025-01-15 09:36:31 +09:00
Taiki Endo
1f8124ee27 Update cargo-binstall@latest to 1.10.21 2025-01-14 00:15:51 +09:00
Taiki Endo
b58c61fa21 Apply clippy::unused_trait_names lint 2025-01-13 23:41:50 +09:00
Taiki Endo
333ea3e9a4 Release 2.47.12 2025-01-13 13:06:32 +09:00
Taiki Endo
172419740d Update wasm-bindgen@latest to 0.2.100 2025-01-13 09:37:37 +09:00
Taiki Endo
6d0e68ca2c Update rclone@latest to 1.69.0 2025-01-13 03:16:22 +09:00
Taiki Endo
b4c13e81de Update cargo-binstall@latest to 1.10.20 2025-01-11 18:13:11 +09:00
Taiki Endo
62b3405f01 ci: Tweak step name 2025-01-11 13:17:28 +09:00
30 changed files with 1802 additions and 1360 deletions

View File

@@ -11,7 +11,7 @@ indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{json,md,rb,yml,yaml}]
[*.{json,md,rb,sh,yml,yaml}]
indent_size = 2
[*.{js,yml,yaml}]

View File

@@ -32,4 +32,3 @@ wasmtime
watchexec
xbuild
xscale
zigbuild

View File

@@ -7,10 +7,6 @@ updates:
commit-message:
prefix: ''
labels: []
groups:
cargo:
patterns:
- '*'
- package-ecosystem: github-actions
directory: /
schedule:
@@ -18,7 +14,3 @@ updates:
commit-message:
prefix: ''
labels: []
groups:
github-actions:
patterns:
- '*'

View File

@@ -47,7 +47,9 @@ jobs:
include:
# NB: Sync list with https://github.com/taiki-e/checkout-action/blob/HEAD/.github/workflows/ci.yml
- os: ubuntu-22.04
- os: ubuntu-22.04-arm
- os: ubuntu-24.04
- os: ubuntu-24.04-arm
- os: ubuntu-22.04
tool: major.minor.patch
- os: ubuntu-22.04
@@ -255,7 +257,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.CREATE_PR_TOKEN }}
PR_NUMBER: ${{ steps.create-pull-request.outputs.pull-request-number }}
if: github.repository_owner == 'taiki-e' && (github.event_name == 'schedule' || github.event_name == 'push' && github.ref == 'refs/heads/main') && steps.diff.outputs.success == 'false' && steps.create-pull-request.outputs.pull-request-operation == 'created'
- name: Auto approve for auto-generated PR
- name: Approve auto-generated PR for auto-merge
run: gh pr review --approve "${PR_NUMBER:?}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -10,6 +10,62 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
## [Unreleased]
## [2.47.21] - 2025-01-21
- Update `knope@latest` to 0.18.3.
## [2.47.20] - 2025-01-21
- Update `wasmtime@latest` to 29.0.0.
## [2.47.19] - 2025-01-20
- Update `trunk@latest` to 0.21.6.
- Update `parse-changelog@latest` to 0.6.11.
## [2.47.18] - 2025-01-19
- Update `cargo-deny@latest` to 0.16.4.
- Update `cargo-binstall@latest` to 1.10.22.
## [2.47.17] - 2025-01-19
- Update `cargo-audit@latest` to 0.21.1.
## [2.47.16] - 2025-01-18
- Update `cargo-make@latest` to 0.37.24.
## [2.47.15] - 2025-01-16
- Update `cargo-tarpaulin@latest` to 0.31.5.
- Update `cargo-llvm-cov@latest` to 0.6.16.
- Update `cargo-hack@latest` to 0.6.34.
## [2.47.14] - 2025-01-16
- Update `cargo-nextest@latest` to 0.9.88.
## [2.47.13] - 2025-01-15
- Update `wasmtime@latest` to 28.0.1.
- Update `release-plz@latest` to 0.3.113.
- Update `cargo-binstall@latest` to 1.10.21.
## [2.47.12] - 2025-01-13
- Update `wasm-bindgen@latest` to 0.2.100.
- Update `rclone@latest` to 1.69.0.
- Update `cargo-binstall@latest` to 1.10.20.
## [2.47.11] - 2025-01-11
- Update `editorconfig-checker@latest` to 3.1.2.
@@ -3314,7 +3370,17 @@ Note: This release is considered a breaking change because installing on version
Initial release
[Unreleased]: https://github.com/taiki-e/install-action/compare/v2.47.11...HEAD
[Unreleased]: https://github.com/taiki-e/install-action/compare/v2.47.21...HEAD
[2.47.21]: https://github.com/taiki-e/install-action/compare/v2.47.20...v2.47.21
[2.47.20]: https://github.com/taiki-e/install-action/compare/v2.47.19...v2.47.20
[2.47.19]: https://github.com/taiki-e/install-action/compare/v2.47.18...v2.47.19
[2.47.18]: https://github.com/taiki-e/install-action/compare/v2.47.17...v2.47.18
[2.47.17]: https://github.com/taiki-e/install-action/compare/v2.47.16...v2.47.17
[2.47.16]: https://github.com/taiki-e/install-action/compare/v2.47.15...v2.47.16
[2.47.15]: https://github.com/taiki-e/install-action/compare/v2.47.14...v2.47.15
[2.47.14]: https://github.com/taiki-e/install-action/compare/v2.47.13...v2.47.14
[2.47.13]: https://github.com/taiki-e/install-action/compare/v2.47.12...v2.47.13
[2.47.12]: https://github.com/taiki-e/install-action/compare/v2.47.11...v2.47.12
[2.47.11]: https://github.com/taiki-e/install-action/compare/v2.47.10...v2.47.11
[2.47.10]: https://github.com/taiki-e/install-action/compare/v2.47.9...v2.47.10
[2.47.9]: https://github.com/taiki-e/install-action/compare/v2.47.8...v2.47.9

View File

@@ -26,6 +26,7 @@ inline_asm_x86_att_syntax = "warn"
trailing_empty_array = "warn"
transmute_undefined_repr = "warn"
undocumented_unsafe_blocks = "warn"
unused_trait_names = "warn"
# Suppress buggy or noisy clippy lints
bool_assert_comparison = { level = "allow", priority = 1 }
borrow_as_ptr = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/8286

View File

@@ -22,8 +22,8 @@ GitHub Action for installing development tools (mainly from GitHub Releases).
| Name | Required | Description | Type | Default |
| -------- |:--------:| --------------------------------------- | ------- | ------- |
| tool | **true** | Tools to install (comma-separated list) | String | |
| checksum | false | Whether to enable checksums | Boolean | `true` |
| tool | **✓** | Tools to install (comma-separated list) | String | |
| checksum | | Whether to enable checksums | Boolean | `true` |
### Example workflow

1408
main.sh

File diff suppressed because it is too large Load Diff

View File

@@ -20,10 +20,28 @@
},
"license_markdown": "[Apache-2.0](https://github.com/rustsec/rustsec/blob/HEAD/cargo-audit/LICENSE-APACHE) OR [MIT](https://github.com/rustsec/rustsec/blob/HEAD/cargo-audit/LICENSE-MIT)",
"latest": {
"version": "0.21.0"
"version": "0.21.1"
},
"0.21": {
"version": "0.21.0"
"version": "0.21.1"
},
"0.21.1": {
"x86_64_linux_musl": {
"etag": "0x8DD383807A86B60",
"checksum": "e1d057a43028cb2359adcb75029e345b5791fbd2a1a01a3b8f16521035662cf3"
},
"x86_64_macos": {
"etag": "0x8DD3837D203A3C3",
"checksum": "ca21223691975d97a2442623a4d90e933d349199a728fdabaf98124ff65ee53f"
},
"x86_64_windows": {
"etag": "0x8DD383870DE65E0",
"checksum": "cb90ebf6c76bdf7014fb0114b3bc897917ce0ea5ecaf16f7dc7009612941dace"
},
"aarch64_linux_gnu": {
"etag": "0x8DD383809DEED88",
"checksum": "bd9a9ceb4887f28c8ace1a35da39818cbdcf98b1088bcd47544bff3a07e856bf"
}
},
"0.21.0": {
"x86_64_linux_musl": {

View File

@@ -22,32 +22,32 @@
},
"license_markdown": "[GPL-3.0](https://github.com/cargo-bins/cargo-binstall/blob/HEAD/crates/bin/LICENSE)",
"latest": {
"version": "1.10.19"
"version": "1.10.22"
},
"1.10.19": {
"1.10.22": {
"x86_64_linux_musl": {
"etag": "0x8DD2C8160F75960",
"checksum": "44f44538682b103312b37961edbd06428dcbf927a0afc3cc89062d45bc08d688"
"etag": "0x8DD38568770C382",
"checksum": "74d7c647c7e60bb8464fa551702fdd38a7241f5cedb2c4edc3b11639cd1dae47"
},
"x86_64_macos": {
"etag": "0x8DD2C811A50D857",
"checksum": "a2ae7d9ea8a4c58d5c5d8405cc3eed80e3b3027dcce16fd2f36116cb2926080f"
"etag": "0x8DD38560D10F1DA",
"checksum": "0abaad286197df9e5a3d25bfdca682fa91fef65fef13f42e20ec24a98165c71a"
},
"x86_64_windows": {
"etag": "0x8DD2C821B327936",
"checksum": "f80e1f22b452a3069aec615ed03bc74a2a9e57e1c92d09868537dc0cd852da8f"
"etag": "0x8DD3857BFED715A",
"checksum": "36d6ea24db049a36d0eab33003e6ee007955f01a8ce89fef46d4026adb86db96"
},
"aarch64_linux_musl": {
"etag": "0x8DD2C811BD72089",
"checksum": "7e95454e15278eb746790e67bb3f3620e3f4ded13956e7887f6f9a8b1f21c1ab"
"etag": "0x8DD38563219A538",
"checksum": "b8c32b1b007482f42f6c4b5f8cfeb168f9674ec6448bfa29ae0c4ba01b7a370b"
},
"aarch64_macos": {
"etag": "0x8DD2C814B56C94F",
"checksum": "e6abcd57e2918f50f85117e80799ef525876b4e109a5126561ed69f89bb79ee5"
"etag": "0x8DD3856413081F7",
"checksum": "97ce4a2f18181f052dda266b042d8bb220e48ffe40ca75e796ae4c5e418b9e01"
},
"aarch64_windows": {
"etag": "0x8DD2C8225C8456F",
"checksum": "285891e236fc3e12dff687e15cf69805fc9edbc20eb8fb1e046065b59f711b46"
"etag": "0x8DD3857931A5667",
"checksum": "d86dfba0c13f7c84724e1d21fcec35b8a42633733215a61d1ee183455b12db5e"
}
}
}

View File

@@ -24,10 +24,32 @@
},
"license_markdown": "[MIT](https://github.com/EmbarkStudios/cargo-deny/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/EmbarkStudios/cargo-deny/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.16.3"
"version": "0.16.4"
},
"0.16": {
"version": "0.16.3"
"version": "0.16.4"
},
"0.16.4": {
"x86_64_linux_musl": {
"etag": "0x8DD3859CBF28AAD",
"checksum": "28b7f8e12df46a9ce186547e38278c851905fc4bda59a0cc57d2aade9fdf6962"
},
"x86_64_macos": {
"etag": "0x8DD3859A8D7C4BE",
"checksum": "01b43782acc7d6900b364fd588897e0ea5874b3583be40bfcf6cad8ad2c97aaf"
},
"x86_64_windows": {
"etag": "0x8DD385A21433507",
"checksum": "11a7ab2ea060a9e6141a3fbab8a6a9bbe30b97ce87fe4fbbb8f6c3a4b8410681"
},
"aarch64_linux_musl": {
"etag": "0x8DD3859CD936886",
"checksum": "56bbe9d8238480472325b019d6ab2eb3ed2601664826f67678ed0a5b8c9d5ba0"
},
"aarch64_macos": {
"etag": "0x8DD3859A47FDF9C",
"checksum": "6b91a75fb4eecc606757125f1cbea103df81b833bafbdceda1611bfa7737a364"
}
},
"0.16.3": {
"x86_64_linux_musl": {

View File

@@ -3,10 +3,42 @@
"template": null,
"license_markdown": "[Apache-2.0](https://github.com/taiki-e/cargo-hack/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-hack/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.6.33"
"version": "0.6.34"
},
"0.6": {
"version": "0.6.33"
"version": "0.6.34"
},
"0.6.34": {
"x86_64_linux_musl": {
"url": "https://github.com/taiki-e/cargo-hack/releases/download/v0.6.34/cargo-hack-x86_64-unknown-linux-musl.tar.gz",
"etag": "0x8DD364BF6437B65",
"checksum": "7b58e29544ae7b357deda5118a17053e4929f94f8d8595215d27cbbb415c47a5"
},
"x86_64_macos": {
"url": "https://github.com/taiki-e/cargo-hack/releases/download/v0.6.34/cargo-hack-x86_64-apple-darwin.tar.gz",
"etag": "0x8DD364C545B2CF1",
"checksum": "4fc72e4b3e1d7c7063efeddd4ebc196b4ee062e9b772dad24bebf8cb15749e21"
},
"x86_64_windows": {
"url": "https://github.com/taiki-e/cargo-hack/releases/download/v0.6.34/cargo-hack-x86_64-pc-windows-msvc.tar.gz",
"etag": "0x8DD364C4A143D6D",
"checksum": "6206ca07f99945f58765d1669fb2a995d96d809424ff7424257ce5f0fad23401"
},
"aarch64_linux_musl": {
"url": "https://github.com/taiki-e/cargo-hack/releases/download/v0.6.34/cargo-hack-aarch64-unknown-linux-musl.tar.gz",
"etag": "0x8DD364BFC48B3B7",
"checksum": "2b30401f9eb7664affdda7ce13b5d8421e2ea5ea74a854a71679ff68bf766761"
},
"aarch64_macos": {
"url": "https://github.com/taiki-e/cargo-hack/releases/download/v0.6.34/cargo-hack-aarch64-apple-darwin.tar.gz",
"etag": "0x8DD364C24072F24",
"checksum": "f2e88526e44b5934b5a0a2aa10fbf621ec44fe509c6ac6a82e1d49fa41d70943"
},
"aarch64_windows": {
"url": "https://github.com/taiki-e/cargo-hack/releases/download/v0.6.34/cargo-hack-aarch64-pc-windows-msvc.tar.gz",
"etag": "0x8DD364C3F0E09C1",
"checksum": "9c9903aa9ae2caaf38c37a0375e18afc50da1c1ca69c3f89b4219b530ab59a0c"
}
},
"0.6.33": {
"x86_64_linux_musl": {

View File

@@ -19,10 +19,32 @@
},
"license_markdown": "[Apache-2.0](https://github.com/taiki-e/cargo-llvm-cov/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-llvm-cov/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.6.15"
"version": "0.6.16"
},
"0.6": {
"version": "0.6.15"
"version": "0.6.16"
},
"0.6.16": {
"x86_64_linux_musl": {
"etag": "0x8DD364B5D41374E",
"checksum": "2145d09b8263ba8bdf32f362919e0e2bb8170404bf6edd380b7b442f9017df58"
},
"x86_64_macos": {
"etag": "0x8DD364B96067E67",
"checksum": "337c619978c7595113353db5775cf953052aba85746f884085e31d2757a03e87"
},
"x86_64_windows": {
"etag": "0x8DD364BA6E069FE",
"checksum": "39f9ee12b9673f081bee6b250a186fbf438bb3f4b8897417d23ee74b199e02ce"
},
"aarch64_linux_musl": {
"etag": "0x8DD364B61561F48",
"checksum": "02a3a2d9c5de145319bd01f7ae63b6a76f0b57229887859a79b9fc0f57978b33"
},
"aarch64_macos": {
"etag": "0x8DD364B8C4E0B3B",
"checksum": "f1ab5f573d6c49d463f8117501462e2a6a0cead9124b68b4a2fbd8a3f5aad7ba"
}
},
"0.6.15": {
"x86_64_linux_musl": {

View File

@@ -20,10 +20,28 @@
},
"license_markdown": "[Apache-2.0](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE)",
"latest": {
"version": "0.37.23"
"version": "0.37.24"
},
"0.37": {
"version": "0.37.23"
"version": "0.37.24"
},
"0.37.24": {
"x86_64_linux_musl": {
"etag": "0x8DD37D36A8C5F07",
"checksum": "ff76969f0caab39c56d168b94b2540fde34609aa6562d555081818ece387b005"
},
"x86_64_macos": {
"etag": "0x8DD37D2ECB9F67A",
"checksum": "afd10db16ce089e0208d4829d46351833d9eb61f3181452a38a2a089bafedc31"
},
"x86_64_windows": {
"etag": "0x8DD37D379E8369F",
"checksum": "f7c757c7e147023ac86d80b134e5a59e0ed8ff032e39be3464cc4aad1e5e0f33"
},
"aarch64_macos": {
"etag": "0x8DD37D2EB99C51D",
"checksum": "823fe51d2baa5679a5dfd33c703d0176374f8f023a2ee950f2e03dc4f31ee523"
}
},
"0.37.23": {
"x86_64_linux_musl": {

View File

@@ -19,10 +19,33 @@
},
"license_markdown": "[Apache-2.0](https://github.com/nextest-rs/nextest/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/nextest-rs/nextest/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.9.87"
"version": "0.9.88"
},
"0.9": {
"version": "0.9.87"
"version": "0.9.88"
},
"0.9.88": {
"previous_stable_version": "0.9.87",
"x86_64_linux_gnu": {
"etag": "0x8DD35B614AADEF1",
"checksum": "6fdb196e5643d50cad6daeefea5c978fff4904f5593eecba472f5ea3150e2aa0"
},
"x86_64_linux_musl": {
"etag": "0x8DD35B63691ECBA",
"checksum": "6fd7676908b4211f12f6298726544509fcb8c6b49a74bacb755d002260b3172c"
},
"x86_64_macos": {
"etag": "0x8DD35B6411A656E",
"checksum": "fe12274625473fe3c9895e28550364fb0afd1faea4e222c36a79b0c1ce1933ae"
},
"x86_64_windows": {
"etag": "0x8DD35B657950DD1",
"checksum": "ddc050a9c52db279bc2a532edf374633c27fb04a4cff679e574a6a19171d6d99"
},
"aarch64_linux_gnu": {
"etag": "0x8DD35B62BE93E0B",
"checksum": "040c1fd58f8853a2104f64c2cc1e7c66bfb48b72637ab1e72027375672d94b6c"
}
},
"0.9.87": {
"previous_stable_version": "0.9.86",

View File

@@ -19,10 +19,32 @@
},
"license_markdown": "[MIT](https://github.com/xd009642/tarpaulin/blob/develop/LICENSE-MIT) OR [Apache-2.0](https://github.com/xd009642/tarpaulin/blob/develop/LICENSE-APACHE)",
"latest": {
"version": "0.31.4"
"version": "0.31.5"
},
"0.31": {
"version": "0.31.4"
"version": "0.31.5"
},
"0.31.5": {
"x86_64_linux_musl": {
"etag": "0x8DD36405804CBF3",
"checksum": "a5f2fdf67023775444c95afe5f0c190885944ca91250d39ac03788924eaa486d"
},
"x86_64_macos": {
"etag": "0x8DD3640173A9B5F",
"checksum": "8376c76c9d16f35ea0358d3683a4cfc638286eabf7fe12acdb31c4efb4ebeb6b"
},
"x86_64_windows": {
"etag": "0x8DD3640D5D46201",
"checksum": "96d93282bcd9c8e52fbe1dab2dff023512f198b5f0cff375c2fbce12fd978c5e"
},
"aarch64_linux_musl": {
"etag": "0x8DD364052DB3E9D",
"checksum": "b371cd0b30c8b7ae86badb9d92965acd740baa3412e11975cfb2ed54dc1b8130"
},
"aarch64_macos": {
"etag": "0x8DD364041B7A438",
"checksum": "476cd4eafea7ebaa21eb560dcd708cf412090214df17a45703c6454a88727cf1"
}
},
"0.31.4": {
"x86_64_linux_musl": {

30
manifests/knope.json generated
View File

@@ -3,10 +3,36 @@
"template": null,
"license_markdown": "[MIT](https://github.com/knope-dev/knope/blob/main/LICENSE)",
"latest": {
"version": "0.18.2"
"version": "0.18.3"
},
"0.18": {
"version": "0.18.2"
"version": "0.18.3"
},
"0.18.3": {
"x86_64_linux_musl": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.18.3/knope-x86_64-unknown-linux-musl.tgz",
"etag": "0x8DD39BE215D7200",
"checksum": "7ebe693bcb214dceef133b9f0ce14af052f74056b205c6175dac3d99713bf8e6",
"bin": "knope-x86_64-unknown-linux-musl/knope"
},
"x86_64_macos": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.18.3/knope-x86_64-apple-darwin.tgz",
"etag": "0x8DD39BE215F1DD1",
"checksum": "a9717b6883436850118e9549acccbe75553ff89a0934d1578c90f280ef974243",
"bin": "knope-x86_64-apple-darwin/knope"
},
"x86_64_windows": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.18.3/knope-x86_64-pc-windows-msvc.tgz",
"etag": "0x8DD39BE21590A2E",
"checksum": "1f8056add6ab3b2af6a1570f166cd4d5f76003ec6d4982c1c3f59eae093580c1",
"bin": "knope-x86_64-pc-windows-msvc/knope.exe"
},
"aarch64_macos": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.18.3/knope-aarch64-apple-darwin.tgz",
"etag": "0x8DD39BE21590A2E",
"checksum": "f2ea1719bd3f7143c7ba68ef1a5dfb977739a88f6b93a1e915674ec36fdf3040",
"bin": "knope-aarch64-apple-darwin/knope"
}
},
"0.18.2": {
"x86_64_linux_musl": {

View File

@@ -3,10 +3,42 @@
"template": null,
"license_markdown": "[Apache-2.0](https://github.com/taiki-e/parse-changelog/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/parse-changelog/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.6.10"
"version": "0.6.11"
},
"0.6": {
"version": "0.6.10"
"version": "0.6.11"
},
"0.6.11": {
"x86_64_linux_musl": {
"url": "https://github.com/taiki-e/parse-changelog/releases/download/v0.6.11/parse-changelog-x86_64-unknown-linux-musl.tar.gz",
"etag": "0x8DD38C1F612ECE8",
"checksum": "805c0e86ad53c734973e1f55efc8fb6d82919029fdca4d27f80d590f94688edc"
},
"x86_64_macos": {
"url": "https://github.com/taiki-e/parse-changelog/releases/download/v0.6.11/parse-changelog-x86_64-apple-darwin.tar.gz",
"etag": "0x8DD38C20DC407CA",
"checksum": "9176db18ab6adc3bb1d4302eb52c83a9d46319df2b4671fccc4669dd8ce36fc6"
},
"x86_64_windows": {
"url": "https://github.com/taiki-e/parse-changelog/releases/download/v0.6.11/parse-changelog-x86_64-pc-windows-msvc.tar.gz",
"etag": "0x8DD38C22DBBA859",
"checksum": "299c282946f836b200940f0b4b2c8646e51eff9f3602bd0c2a99b483aa2d4429"
},
"aarch64_linux_musl": {
"url": "https://github.com/taiki-e/parse-changelog/releases/download/v0.6.11/parse-changelog-aarch64-unknown-linux-musl.tar.gz",
"etag": "0x8DD38C1F6DE0AEB",
"checksum": "a294359f1b1a904a34911fbf482c69ee28924dc8c27f2a1b84b4eb2108b6df3d"
},
"aarch64_macos": {
"url": "https://github.com/taiki-e/parse-changelog/releases/download/v0.6.11/parse-changelog-aarch64-apple-darwin.tar.gz",
"etag": "0x8DD38C1F6FB83DD",
"checksum": "e4e841ba10e7a0e314ec192142c016974f4999a03fc0f37c8803708654098c91"
},
"aarch64_windows": {
"url": "https://github.com/taiki-e/parse-changelog/releases/download/v0.6.11/parse-changelog-aarch64-pc-windows-msvc.tar.gz",
"etag": "0x8DD38C22406DAAB",
"checksum": "a5606df69e240edcf24e9466abdce004ba21c9f9cafe42d659fd3f3cb3d375e6"
}
},
"0.6.10": {
"x86_64_linux_musl": {

33
manifests/rclone.json generated
View File

@@ -28,10 +28,39 @@
},
"license_markdown": "[MIT](https://github.com/rclone/rclone/blob/master/COPYING)",
"latest": {
"version": "1.68.2"
"version": "1.69.0"
},
"1": {
"version": "1.68.2"
"version": "1.69.0"
},
"1.69": {
"version": "1.69.0"
},
"1.69.0": {
"x86_64_linux_musl": {
"etag": "0x8DD3324F9F9FD71",
"checksum": "813892bb54ebc5891664b85c9cfc0e05ee50d39e3d5bb1ddd6d53d0f93a64dc2"
},
"x86_64_macos": {
"etag": "0x8DD3325E8440A19",
"checksum": "88475be8666944d5161bd15605d483f1bb55d9a46220b9dcf317b26e01659009"
},
"x86_64_windows": {
"etag": "0x8DD3326252ADAAD",
"checksum": "73f55188dbd15056b9728cb646f4e9774534b148dec3eed9ccbbaa381b95ce78"
},
"aarch64_linux_musl": {
"etag": "0x8DD33251C72E345",
"checksum": "82e4c24ee0cdbdfb93356e66cf14875ae4063f9923d2678e7d686119e98d75fe"
},
"aarch64_macos": {
"etag": "0x8DD3325F16EC073",
"checksum": "d8d22aca8f4af4c24ea01668a452d02888bef45e3a01c663cbb7d78bd1e21db2"
},
"aarch64_windows": {
"etag": "0x8DD33262D4C7710",
"checksum": "83c3e46f1b4414848cf676f58aa3f14ee428ba22bd963ecb0b70dada717ebfdb"
}
},
"1.68": {
"version": "1.68.2"

View File

@@ -22,10 +22,36 @@
},
"license_markdown": "[MIT](https://github.com/release-plz/release-plz/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/release-plz/release-plz/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.3.112"
"version": "0.3.113"
},
"0.3": {
"version": "0.3.112"
"version": "0.3.113"
},
"0.3.113": {
"x86_64_linux_musl": {
"etag": "0x8DD34DE89D16C19",
"checksum": "581dc963e0aaf1791064429e9f746307ede0a8ea29d10041dd90c02bdbd13783"
},
"x86_64_macos": {
"etag": "0x8DD34DF8889BC58",
"checksum": "0811c988fda4552a31a8ab90776100e31bf8bb987f9337d05dc3dc92669848f4"
},
"x86_64_windows": {
"etag": "0x8DD34DF81C2F907",
"checksum": "68da2a1aba802069e5c59e42017f5e589f44e66d6105528893b294f1b296b916"
},
"aarch64_linux_musl": {
"etag": "0x8DD34DE988E8048",
"checksum": "01a1d2fa25811aa2e9e008fc9edf9ae3128b686c5e5f9a2c774fe7dc37346c27"
},
"aarch64_macos": {
"etag": "0x8DD34E03A6691B8",
"checksum": "f0f23f958541440f4f9669580ae04500feaaad2cdbfee3636a14729236d04e64"
},
"aarch64_windows": {
"etag": "0x8DD34DF694608E7",
"checksum": "8236943701c7f2ce2fa7c99f6f65392543fd6293fe7cb30878b17c171078ae48"
}
},
"0.3.112": {
"x86_64_linux_musl": {

26
manifests/trunk.json generated
View File

@@ -19,10 +19,32 @@
},
"license_markdown": "[MIT](https://github.com/trunk-rs/trunk/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/trunk-rs/trunk/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.21.5"
"version": "0.21.6"
},
"0.21": {
"version": "0.21.5"
"version": "0.21.6"
},
"0.21.6": {
"x86_64_linux_musl": {
"etag": "0x8DD395263DA4485",
"checksum": "cd0897cb2db44c3305bea357a150759b7ba7cfc3e4290498d73692bbf87a55f3"
},
"x86_64_macos": {
"etag": "0x8DD3952638703EF",
"checksum": "3bf14129b4f4cdbdf82d4742da19972ec13bd7be8fb1cabd477d9dbf2d215b87"
},
"x86_64_windows": {
"etag": "0x8DD395263A03BE8",
"checksum": "02e025f6a3b4eecc1edc23b14864e15471a4d6159f9a91ec5f9b1cd1617563ca"
},
"aarch64_linux_musl": {
"etag": "0x8DD395263490844",
"checksum": "8a8a49af75a0499031372506f2703904504d3c1c2034aa48e648ccd7ef1f2238"
},
"aarch64_macos": {
"etag": "0x8DD39526347F804",
"checksum": "7f65126595d00d6e660b9f3e89fedc40a927bd06556461e45ae592468addeb05"
}
},
"0.21.5": {
"x86_64_linux_musl": {

View File

@@ -44,10 +44,32 @@
},
"license_markdown": "[MIT](https://github.com/rustwasm/wasm-bindgen/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/rustwasm/wasm-bindgen/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.2.99"
"version": "0.2.100"
},
"0.2": {
"version": "0.2.99"
"version": "0.2.100"
},
"0.2.100": {
"x86_64_linux_musl": {
"etag": "0x8DD335FEBC3B912",
"checksum": "63d6a38deb65bd7023c02bdf382ab66b0d2c0241c8582fd3413b5a808b8aeb5b"
},
"x86_64_macos": {
"etag": "0x8DD335FEBCF929E",
"checksum": "72289c54f63d2a2723aacfb38e7b22044d6aebc849ddee40172cda0e74be4107"
},
"x86_64_windows": {
"etag": "0x8DD335FEBB4D5B6",
"checksum": "54a3fb947464388a468ade86d65ffa334d6d2c74b7982723b34ecf6ec8c213d8"
},
"aarch64_linux_gnu": {
"etag": "0x8DD335FEBC31D7D",
"checksum": "52552984965fbd125efc6be052b3cb8872fb3c69559e4ec7775cbff64ed440cf"
},
"aarch64_macos": {
"etag": "0x8DD335FEBB9B239",
"checksum": "69f25cb910de7e19777b3f93347f5e62a64c8f81709b41ba7242d00a9543573c"
}
},
"0.2.99": {
"x86_64_linux_musl": {

View File

@@ -28,13 +28,71 @@
},
"license_markdown": "[Apache-2.0 WITH LLVM-exception](https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE)",
"latest": {
"version": "28.0.0"
"version": "29.0.0"
},
"29": {
"version": "29.0.0"
},
"29.0": {
"version": "29.0.0"
},
"29.0.0": {
"x86_64_linux_gnu": {
"etag": "0x8DD3980E5BCFA27",
"checksum": "a8b199405d14a53e9d9196c556643f19b0de9bcd61664246d7511bee34cef2f7"
},
"x86_64_macos": {
"etag": "0x8DD3980E6BE06EA",
"checksum": "e5bfaa01985317039c3f57ac42bf117c693b4a1203bfbe8de741c7781a41b9dc"
},
"x86_64_windows": {
"etag": "0x8DD3980EB038D65",
"checksum": "8114c08d134e9ec845152da99c382692c7f568ae0effcef550976bdaacfb4e8e"
},
"aarch64_linux_gnu": {
"etag": "0x8DD3980DA3E93C6",
"checksum": "a1e7fb17bc929ffd02e0e847a8c109f371407afec90180ef576d554d29cff3e0"
},
"aarch64_macos": {
"etag": "0x8DD3980DB3807EC",
"checksum": "d83fe0c2d3c3c67762f84a794045e020b0bfe1f4b1c56a138d59e2bbb9a04d2f"
},
"aarch64_windows": {
"etag": "0x8DD3980DD632632",
"checksum": "60caa468edf711454ab9fd6900ef71e9fdb6d7c94f76740181e64bca2e1b3110"
}
},
"28": {
"version": "28.0.0"
"version": "28.0.1"
},
"28.0": {
"version": "28.0.0"
"version": "28.0.1"
},
"28.0.1": {
"x86_64_linux_gnu": {
"etag": "0x8DD34F2BB0BD3D7",
"checksum": "f2500c046d92d68c5db66244e8685d0ba84a0fdce4780fb0f1e78e9666d9c920"
},
"x86_64_macos": {
"etag": "0x8DD34F2BBCD5FF0",
"checksum": "872c6d078f6ac1058be6f0f5219001b0e445aa00f96fc4c1242548701d9933b5"
},
"x86_64_windows": {
"etag": "0x8DD34F2BEBC9FE0",
"checksum": "b6564429cb6a0e930465204da11ae66e717508358e737d491eaa095b4a85792e"
},
"aarch64_linux_gnu": {
"etag": "0x8DD34F2B4A33B3D",
"checksum": "d18d05ad1482b8a0fa5040e2d4a9576a06c9b61890fac2d4a2e0824e3b308a7a"
},
"aarch64_macos": {
"etag": "0x8DD34F2B555486E",
"checksum": "0dc360747b46d0632e1d9d81299ed653ce5d31f43247780c6c20af2a3f4ad67c"
},
"aarch64_windows": {
"etag": "0x8DD34F2B635AB9D",
"checksum": "db3a8bbccb56a05a62fd3dfc4936ea396558f0a1ae6ffe4eee66e7b15a6230f2"
}
},
"28.0.0": {
"x86_64_linux_gnu": {

View File

@@ -6,12 +6,12 @@ trap -- 's=$?; printf >&2 "%s\n" "${0##*/}:${LINENO}: \`${BASH_COMMAND}\` exit w
cd -- "$(dirname -- "$0")"/../..
bail() {
printf >&2 'error: %s\n' "$*"
exit 1
printf >&2 'error: %s\n' "$*"
exit 1
}
if [[ -z "${CI:-}" ]]; then
bail "this script is intended to call from release workflow on CI"
bail "this script is intended to call from release workflow on CI"
fi
git config user.name 'Taiki Endo'
@@ -21,28 +21,28 @@ set -x
has_update=''
for manifest in manifests/*.json; do
git add -N "${manifest}"
if ! git diff --exit-code -- "${manifest}"; then
name="${manifest##*/}"
name="${name%.*}"
git stash
old_version=$(jq -r '.latest.version' "${manifest}")
git stash pop
new_version=$(jq -r '.latest.version' "${manifest}")
if [[ "${old_version}" != "${new_version}" ]]; then
# TODO: If there is a line about updating the same tool in the "Unreleased" section, replace it.
msg="Update \`${name}@latest\` to ${new_version}"
sed -Ei "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n- ${msg}./" CHANGELOG.md
git add "${manifest}" CHANGELOG.md
else
msg="Update ${name} manifest"
git add "${manifest}"
fi
git commit -m "${msg}"
has_update=1
git add -N "${manifest}"
if ! git diff --exit-code -- "${manifest}"; then
name="${manifest##*/}"
name="${name%.*}"
git stash
old_version=$(jq -r '.latest.version' "${manifest}")
git stash pop
new_version=$(jq -r '.latest.version' "${manifest}")
if [[ "${old_version}" != "${new_version}" ]]; then
# TODO: If there is a line about updating the same tool in the "Unreleased" section, replace it.
msg="Update \`${name}@latest\` to ${new_version}"
sed -Ei "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n- ${msg}./" CHANGELOG.md
git add "${manifest}" CHANGELOG.md
else
msg="Update ${name} manifest"
git add "${manifest}"
fi
git commit -m "${msg}"
has_update=1
fi
done
if [[ -n "${has_update}" ]] && [[ -n "${GITHUB_OUTPUT:-}" ]]; then
printf 'success=false\n' >>"${GITHUB_OUTPUT}"
printf 'success=false\n' >>"${GITHUB_OUTPUT}"
fi

View File

@@ -8,171 +8,181 @@ cd -- "$(dirname -- "$0")"/../..
# They don't provide prebuilt binaries for musl or old glibc host.
# version `GLIBC_2.34' not found
glibc_pre_2_34_incompat=(
cargo-cyclonedx
cargo-spellcheck
wait-for-them
xbuild
cargo-cyclonedx
cargo-spellcheck
wait-for-them
xbuild
)
# version `GLIBC_2.31' not found
glibc_pre_2_31_incompat=(
"${glibc_pre_2_34_incompat[@]}"
cargo-sort
espup
zola
"${glibc_pre_2_34_incompat[@]}"
cargo-sort
espup
zola
)
# version `GLIBC_2.28' not found
glibc_pre_2_28_incompat=(
"${glibc_pre_2_31_incompat[@]}"
wasmtime
"${glibc_pre_2_31_incompat[@]}"
wasmtime
)
# version `GLIBC_2.27' not found
glibc_pre_2_27_incompat=(
"${glibc_pre_2_28_incompat[@]}"
cargo-watch
mdbook-linkcheck
protoc
valgrind
"${glibc_pre_2_28_incompat[@]}"
cargo-watch
mdbook-linkcheck
protoc
valgrind
)
# version `GLIBC_2.17' not found
glibc_pre_2_17_incompat=(
"${glibc_pre_2_27_incompat[@]}"
deepsource
"${glibc_pre_2_27_incompat[@]}"
deepsource
)
musl_incompat=(
"${glibc_pre_2_17_incompat[@]}"
"${glibc_pre_2_17_incompat[@]}"
)
win2019_gnu_incompat=(
cargo-spellcheck
cargo-spellcheck
)
incompat_tools=()
case "${1:-}" in
'') version=latest ;;
major.minor.patch | major.minor | major)
version="$1"
# Specifying the version of valgrind and cargo-binstall is not supported.
incompat_tools+=(valgrind cargo-binstall)
;;
*)
printf 'tool=%s\n', "$1"
exit 1
;;
'') version=latest ;;
major.minor.patch | major.minor | major)
version="$1"
# Specifying the version of valgrind and cargo-binstall is not supported.
incompat_tools+=(valgrind cargo-binstall)
;;
*)
printf 'tool=%s\n', "$1"
exit 1
;;
esac
runner="${2:-}"
bash="${3:-}"
case "$(uname -s)" in
Linux)
host_os=linux
ldd_version=$(ldd --version 2>&1 || true)
if grep -Fq musl <<<"${ldd_version}"; then
incompat_tools+=("${musl_incompat[@]}")
else
host_glibc_version=$(grep -E "GLIBC|GNU libc" <<<"${ldd_version}" | sed "s/.* //g")
higher_glibc_version=$(sort -Vu <<<"2.34"$'\n'"${host_glibc_version}" | tail -1)
Linux)
host_os=linux
ldd_version=$(ldd --version 2>&1 || true)
if grep -Fq musl <<<"${ldd_version}"; then
incompat_tools+=("${musl_incompat[@]}")
else
host_glibc_version=$(grep -E "GLIBC|GNU libc" <<<"${ldd_version}" | sed "s/.* //g")
higher_glibc_version=$(sort -Vu <<<"2.34"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
higher_glibc_version=$(sort -Vu <<<"2.31"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
higher_glibc_version=$(sort -Vu <<<"2.28"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
higher_glibc_version=$(sort -Vu <<<"2.27"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
higher_glibc_version=$(sort -Vu <<<"2.31"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
higher_glibc_version=$(sort -Vu <<<"2.28"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
higher_glibc_version=$(sort -Vu <<<"2.27"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
higher_glibc_version=$(sort -Vu <<<"2.17"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
incompat_tools+=("${glibc_pre_2_17_incompat[@]}")
else
incompat_tools+=("${glibc_pre_2_27_incompat[@]}")
fi
else
incompat_tools+=("${glibc_pre_2_28_incompat[@]}")
fi
else
incompat_tools+=("${glibc_pre_2_31_incompat[@]}")
fi
else
incompat_tools+=("${glibc_pre_2_34_incompat[@]}")
fi
higher_glibc_version=$(sort -Vu <<<"2.17"$'\n'"${host_glibc_version}" | tail -1)
if [[ "${higher_glibc_version}" != "${host_glibc_version}" ]]; then
incompat_tools+=("${glibc_pre_2_17_incompat[@]}")
else
incompat_tools+=("${glibc_pre_2_27_incompat[@]}")
fi
else
incompat_tools+=("${glibc_pre_2_28_incompat[@]}")
fi
else
incompat_tools+=("${glibc_pre_2_31_incompat[@]}")
fi
else
incompat_tools+=("${glibc_pre_2_34_incompat[@]}")
fi
if ! type -P snap >/dev/null; then
incompat_tools+=(valgrind)
fi
fi
if ! type -P snap >/dev/null; then
incompat_tools+=(valgrind)
fi
;;
Darwin) host_os=macos ;;
MINGW* | MSYS* | CYGWIN* | Windows_NT)
host_os=windows
case "${bash}" in
msys64 | cygwin)
if [[ "${runner}" == "windows-2019" ]]; then
incompat_tools+=("${win2019_gnu_incompat[@]}")
fi
;;
Darwin) host_os=macos ;;
MINGW* | MSYS* | CYGWIN* | Windows_NT)
host_os=windows
case "${bash}" in
msys64 | cygwin)
if [[ "${runner}" == "windows-2019" ]]; then
incompat_tools+=("${win2019_gnu_incompat[@]}")
fi
;;
esac
;;
*) bail "unrecognized OS type '$(uname -s)'" ;;
esac
;;
*) bail "unrecognized OS type '$(uname -s)'" ;;
esac
# See main.sh
case "$(uname -m)" in
aarch64 | arm64) host_arch=aarch64 ;;
xscale | arm | armv*l) bail "32-bit Arm runner is not supported yet by this action; if you need support for this platform, please submit an issue at <https://github.com/taiki-e/install-action>" ;;
*) host_arch=x86_64 ;;
esac
tools=()
for manifest in tools/codegen/base/*.json; do
tool_name="${manifest##*/}"
tool_name="${tool_name%.*}"
# cross -V requires rustc
if [[ "${tool_name}" == "cross" ]] && ! type -P rustc >/dev/null; then
tool_name="${manifest##*/}"
tool_name="${tool_name%.*}"
# cross -V requires rustc
if [[ "${tool_name}" == "cross" ]] && ! type -P rustc >/dev/null; then
continue
fi
case "${host_os}" in
linux*)
if [[ "${host_arch}" != "x86_64" ]] && [[ "$(jq -r ".platform.${host_arch}_${host_os}_gnu" "${manifest}")" == "null" ]] && [[ "$(jq -r ".platform.${host_arch}_${host_os}_musl" "${manifest}")" == "null" ]]; then
continue
fi
;;
*)
if [[ "$(jq -r ".platform.x86_64_${host_os}" "${manifest}")" == "null" ]] && [[ "$(jq -r ".platform.${host_arch}_${host_os}" "${manifest}")" == "null" ]]; then
continue
fi
;;
esac
for incompat in ${incompat_tools[@]+"${incompat_tools[@]}"}; do
if [[ "${incompat}" == "${tool_name}" ]]; then
tool_name=''
break
fi
case "${host_os}" in
linux*) ;;
*)
if [[ "$(jq -r ".platform.x86_64_${host_os}" "${manifest}")" == "null" ]]; then
continue
fi
;;
esac
for incompat in ${incompat_tools[@]+"${incompat_tools[@]}"}; do
if [[ "${incompat}" == "${tool_name}" ]]; then
tool_name=''
break
fi
done
if [[ -n "${tool_name}" ]]; then
if [[ "${version}" != "latest" ]]; then
latest_version=$(jq -r '.latest.version' "manifests/${tool_name}.json")
case "${version}" in
major.minor.patch) tool_name+="@${latest_version}" ;;
major.minor) tool_name+="@${latest_version%.*}" ;;
major) tool_name+="@${latest_version%%.*}" ;;
*) exit 1 ;;
esac
fi
if [[ "${tool_name}" != *"@0" ]] && [[ "${tool_name}" != *"@0.0" ]]; then
tools+=("${tool_name}")
fi
done
if [[ -n "${tool_name}" ]]; then
if [[ "${version}" != "latest" ]]; then
latest_version=$(jq -r '.latest.version' "manifests/${tool_name}.json")
case "${version}" in
major.minor.patch) tool_name+="@${latest_version}" ;;
major.minor) tool_name+="@${latest_version%.*}" ;;
major) tool_name+="@${latest_version%%.*}" ;;
*) exit 1 ;;
esac
fi
if [[ "${tool_name}" != *"@0" ]] && [[ "${tool_name}" != *"@0.0" ]]; then
tools+=("${tool_name}")
fi
fi
done
if [[ "${version}" != "latest" ]]; then
tools_tmp=()
for tool in "${tools[@]}"; do
tools_tmp+=("${tool}")
done
tools=("${tools_tmp[@]}")
tools_tmp=()
for tool in "${tools[@]}"; do
tools_tmp+=("${tool}")
done
tools=("${tools_tmp[@]}")
fi
# Not manifest-based
case "${host_os}" in
linux*)
# Installing snap to container is difficult...
# Specifying the version of valgrind is not supported.
if type -P snap >/dev/null && [[ "${version}" == "latest" ]]; then
tools+=(valgrind)
fi
;;
linux*)
# Installing snap to container is difficult...
# Specifying the version of valgrind is not supported.
if type -P snap >/dev/null && [[ "${version}" == "latest" ]]; then
tools+=(valgrind)
fi
;;
esac
# cargo-watch/watchexec-cli is supported by cargo-binstall (through quickinstall)
case "${version}" in
latest) tools+=(cargo-watch watchexec-cli) ;;
major.minor.patch) tools+=(cargo-watch@8.5.2 watchexec-cli@2.1.2) ;;
major.minor) tools+=(cargo-watch@8.5 watchexec-cli@2.1) ;;
major) tools+=(cargo-watch@8 watchexec-cli@2) ;;
*) exit 1 ;;
latest) tools+=(cargo-watch watchexec-cli) ;;
major.minor.patch) tools+=(cargo-watch@8.5.2 watchexec-cli@2.1.2) ;;
major.minor) tools+=(cargo-watch@8.5 watchexec-cli@2.1) ;;
major) tools+=(cargo-watch@8 watchexec-cli@2) ;;
*) exit 1 ;;
esac
# sort and dedup

View File

@@ -5,7 +5,7 @@ use std::{
collections::{BTreeMap, BTreeSet},
env,
ffi::OsStr,
io::Read,
io::Read as _,
path::Path,
sync::{LazyLock, RwLock},
time::Duration,
@@ -17,7 +17,7 @@ use install_action_internal_codegen::{
workspace_root, BaseManifest, HostPlatform, Manifest, ManifestDownloadInfo, ManifestRef,
ManifestTemplate, ManifestTemplateDownloadInfo, Manifests, Signing, SigningKind, Version,
};
use sha2::{Digest, Sha256};
use sha2::{Digest as _, Sha256};
use spdx::expression::{ExprNode, ExpressionReq, Operator};
fn main() -> Result<()> {

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::{env, fmt, io::Write, path::PathBuf};
use std::{env, fmt, io::Write as _, path::PathBuf};
use anyhow::Result;
use fs_err as fs;

View File

@@ -11,12 +11,12 @@ cd -- "$(dirname -- "$0")"/..
# ./tools/manifest.sh [PACKAGE [VERSION_REQ]]
if [[ $# -gt 0 ]]; then
cargo run --manifest-path tools/codegen/Cargo.toml --release -- "$@"
exit 0
cargo run --manifest-path tools/codegen/Cargo.toml --release -- "$@"
exit 0
fi
for manifest in tools/codegen/base/*.json; do
package="${manifest##*/}"
package="${package%.*}"
cargo run --manifest-path tools/codegen/Cargo.toml --release -- "${package}" latest
package="${manifest##*/}"
package="${package%.*}"
cargo run --manifest-path tools/codegen/Cargo.toml --release -- "${package}" latest
done

View File

@@ -14,18 +14,18 @@ cd -- "$(dirname -- "$0")"/..
# - parse-changelog <https://github.com/taiki-e/parse-changelog>
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
bail() {
printf >&2 'error: %s\n' "$*"
exit 1
printf >&2 'error: %s\n' "$*"
exit 1
}
version="${1:?}"
@@ -34,15 +34,15 @@ tag_prefix="v"
tag="${tag_prefix}${version}"
changelog="CHANGELOG.md"
if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z\.-]+)?(\+[0-9A-Za-z\.-]+)?$ ]]; then
bail "invalid version format '${version}'"
bail "invalid version format '${version}'"
fi
if [[ $# -gt 1 ]]; then
bail "invalid argument '$2'"
bail "invalid argument '$2'"
fi
if { sed --help 2>&1 || true; } | grep -Eq -e '-i extension'; then
in_place=(-i '')
in_place=(-i '')
else
in_place=(-i)
in_place=(-i)
fi
# Make sure there is no uncommitted change.
@@ -51,67 +51,67 @@ git diff --exit-code --staged
# Make sure the same release has not been created in the past.
if gh release view "${tag}" &>/dev/null; then
bail "tag '${tag}' has already been created and pushed"
bail "tag '${tag}' has already been created and pushed"
fi
# Make sure that the release was created from an allowed branch.
if ! git branch | grep -Eq '\* main$'; then
bail "current branch is not 'main'"
bail "current branch is not 'main'"
fi
if ! git remote -v | grep -F origin | grep -Eq 'github\.com[:/]taiki-e/'; then
bail "cannot publish a new release from fork repository"
bail "cannot publish a new release from fork repository"
fi
release_date=$(date -u '+%Y-%m-%d')
tags=$(git --no-pager tag | { grep -E "^${tag_prefix}[0-9]+" || true; })
if [[ -n "${tags}" ]]; then
# Make sure the same release does not exist in changelog.
if grep -Eq "^## \\[${version//./\\.}\\]" "${changelog}"; then
bail "release ${version} already exist in ${changelog}"
fi
if grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} already exist in ${changelog}"
fi
# Update changelog.
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed -E 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
prev_tag="${remote_url#*/compare/}"
remote_url="${remote_url%/compare/*}"
sed -E "${in_place[@]}" \
-e "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n## [${version}] - ${release_date}/" \
-e "s#^\[Unreleased\]: https://.*#[Unreleased]: ${remote_url}/compare/${tag}...HEAD\\n[${version}]: ${remote_url}/compare/${prev_tag}...${tag}#" "${changelog}"
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "failed to update ${changelog}"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "failed to update ${changelog}"
fi
# Make sure the same release does not exist in changelog.
if grep -Eq "^## \\[${version//./\\.}\\]" "${changelog}"; then
bail "release ${version} already exist in ${changelog}"
fi
if grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} already exist in ${changelog}"
fi
# Update changelog.
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed -E 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
prev_tag="${remote_url#*/compare/}"
remote_url="${remote_url%/compare/*}"
sed -E "${in_place[@]}" \
-e "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n## [${version}] - ${release_date}/" \
-e "s#^\[Unreleased\]: https://.*#[Unreleased]: ${remote_url}/compare/${tag}...HEAD\\n[${version}]: ${remote_url}/compare/${prev_tag}...${tag}#" "${changelog}"
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "failed to update ${changelog}"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "failed to update ${changelog}"
fi
else
# Make sure the release exists in changelog.
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "release ${version} does not exist in ${changelog} or has wrong release date"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} does not exist in ${changelog}"
fi
# Make sure the release exists in changelog.
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "release ${version} does not exist in ${changelog} or has wrong release date"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} does not exist in ${changelog}"
fi
fi
# Make sure that a valid release note for this version exists.
# https://github.com/taiki-e/parse-changelog
changes=$(parse-changelog "${changelog}" "${version}")
if [[ -z "${changes}" ]]; then
bail "changelog for ${version} has no body"
bail "changelog for ${version} has no body"
fi
printf '============== CHANGELOG ==============\n'
printf '%s\n' "${changes}"
printf '=======================================\n'
if [[ -n "${tags}" ]]; then
# Create a release commit.
(
set -x
git add "${changelog}"
git commit -m "Release ${version}"
)
# Create a release commit.
(
set -x
git add "${changelog}"
git commit -m "Release ${version}"
)
fi
set -x
@@ -124,8 +124,8 @@ major_version_tag="v${version%%.*}"
git checkout -b "${major_version_tag}"
retry git push origin refs/heads/"${major_version_tag}"
if git --no-pager tag | grep -Eq "^${major_version_tag}$"; then
git tag -d "${major_version_tag}"
retry git push --delete origin refs/tags/"${major_version_tag}"
git tag -d "${major_version_tag}"
retry git push --delete origin refs/tags/"${major_version_tag}"
fi
git tag "${major_version_tag}"
retry git push origin --tags
@@ -134,8 +134,8 @@ git branch -d "${major_version_tag}"
tools=()
for tool in tools/codegen/base/*.json; do
tool="${tool##*/}"
tools+=("${tool%.*}")
tool="${tool##*/}"
tools+=("${tool%.*}")
done
# Alias
tools+=(nextest)
@@ -143,18 +143,18 @@ tools+=(nextest)
tools+=(valgrind)
for tool in "${tools[@]}"; do
git checkout -b "${tool}"
sed -E "${in_place[@]}" "s/required: true/required: false/g" action.yml
sed -E "${in_place[@]}" "s/# default: #publish:tool/default: ${tool}/g" action.yml
git add action.yml
git commit -m "${tool}"
retry git push origin -f refs/heads/"${tool}"
if git --no-pager tag | grep -Eq "^${tool}$"; then
git tag -d "${tool}"
retry git push --delete origin refs/tags/"${tool}"
fi
git tag "${tool}"
retry git push origin --tags
git checkout main
git branch -D "${tool}"
git checkout -b "${tool}"
sed -E "${in_place[@]}" "s/required: true/required: false/g" action.yml
sed -E "${in_place[@]}" "s/# default: #publish:tool/default: ${tool}/g" action.yml
git add action.yml
git commit -m "${tool}"
retry git push origin -f refs/heads/"${tool}"
if git --no-pager tag | grep -Eq "^${tool}$"; then
git tag -d "${tool}"
retry git push --delete origin refs/tags/"${tool}"
fi
git tag "${tool}"
retry git push origin --tags
git checkout main
git branch -D "${tool}"
done

View File

@@ -25,464 +25,464 @@ trap 's=$?; echo >&2 "$0: error on line "${LINENO}": ${BASH_COMMAND}"; exit ${s}
# skipped if the corresponding files do not exist.
check_diff() {
if [[ -n "${CI:-}" ]]; then
if ! git --no-pager diff --exit-code "$@"; then
should_fail=1
fi
else
if ! git --no-pager diff --exit-code "$@" &>/dev/null; then
should_fail=1
fi
if [[ -n "${CI:-}" ]]; then
if ! git --no-pager diff --exit-code "$@"; then
should_fail=1
fi
else
if ! git --no-pager diff --exit-code "$@" &>/dev/null; then
should_fail=1
fi
fi
}
check_config() {
if [[ ! -e "$1" ]]; then
error "could not found $1 in the repository root"
fi
if [[ ! -e "$1" ]]; then
error "could not found $1 in the repository root"
fi
}
check_install() {
for tool in "$@"; do
if ! type -P "${tool}" &>/dev/null; then
if [[ "${tool}" == "python3" ]]; then
if type -P python &>/dev/null; then
continue
fi
fi
error "'${tool}' is required to run this check"
return 1
for tool in "$@"; do
if ! type -P "${tool}" &>/dev/null; then
if [[ "${tool}" == "python3" ]]; then
if type -P python &>/dev/null; then
continue
fi
done
fi
error "'${tool}' is required to run this check"
return 1
fi
done
}
info() {
echo >&2 "info: $*"
echo >&2 "info: $*"
}
error() {
if [[ -n "${GITHUB_ACTIONS:-}" ]]; then
echo "::error::$*"
else
echo >&2 "error: $*"
fi
should_fail=1
if [[ -n "${GITHUB_ACTIONS:-}" ]]; then
echo "::error::$*"
else
echo >&2 "error: $*"
fi
should_fail=1
}
venv() {
local bin="$1"
shift
"${venv_bin}/${bin}${exe}" "$@"
local bin="$1"
shift
"${venv_bin}/${bin}${exe}" "$@"
}
venv_install_yq() {
local py_suffix=''
if type -P python3 &>/dev/null; then
py_suffix='3'
fi
exe=''
venv_bin='.venv/bin'
case "$(uname -s)" in
MINGW* | MSYS* | CYGWIN* | Windows_NT)
exe='.exe'
venv_bin='.venv/Scripts'
;;
esac
if [[ ! -d .venv ]]; then
"python${py_suffix}" -m venv .venv
fi
if [[ ! -e "${venv_bin}/yq${exe}" ]]; then
info "installing yq to ./.venv using pip"
venv "pip${py_suffix}" install yq
fi
local py_suffix=''
if type -P python3 &>/dev/null; then
py_suffix='3'
fi
exe=''
venv_bin='.venv/bin'
case "$(uname -s)" in
MINGW* | MSYS* | CYGWIN* | Windows_NT)
exe='.exe'
venv_bin='.venv/Scripts'
;;
esac
if [[ ! -d .venv ]]; then
"python${py_suffix}" -m venv .venv
fi
if [[ ! -e "${venv_bin}/yq${exe}" ]]; then
info "installing yq to ./.venv using pip"
venv "pip${py_suffix}" install yq
fi
}
if [[ $# -gt 0 ]]; then
cat <<EOF
cat <<EOF
USAGE:
$0
EOF
exit 1
exit 1
fi
# Rust (if exists)
if [[ -n "$(git ls-files '*.rs')" ]]; then
info "checking Rust code style"
check_install cargo jq python3
check_config .rustfmt.toml
if check_install rustup; then
# `cargo fmt` cannot recognize files not included in the current workspace and modules
# defined inside macros, so run rustfmt directly.
# We need to use nightly rustfmt because we use the unstable formatting options of rustfmt.
rustc_version=$(rustc -vV | grep '^release:' | cut -d' ' -f2)
if [[ "${rustc_version}" == *"nightly"* ]] || [[ "${rustc_version}" == *"dev"* ]]; then
rustup component add rustfmt &>/dev/null
info "running \`rustfmt \$(git ls-files '*.rs')\`"
rustfmt $(git ls-files '*.rs')
else
rustup component add rustfmt --toolchain nightly &>/dev/null
info "running \`rustfmt +nightly \$(git ls-files '*.rs')\`"
rustfmt +nightly $(git ls-files '*.rs')
fi
check_diff $(git ls-files '*.rs')
info "checking Rust code style"
check_install cargo jq python3
check_config .rustfmt.toml
if check_install rustup; then
# `cargo fmt` cannot recognize files not included in the current workspace and modules
# defined inside macros, so run rustfmt directly.
# We need to use nightly rustfmt because we use the unstable formatting options of rustfmt.
rustc_version=$(rustc -vV | grep '^release:' | cut -d' ' -f2)
if [[ "${rustc_version}" == *"nightly"* ]] || [[ "${rustc_version}" == *"dev"* ]]; then
rustup component add rustfmt &>/dev/null
info "running \`rustfmt \$(git ls-files '*.rs')\`"
rustfmt $(git ls-files '*.rs')
else
rustup component add rustfmt --toolchain nightly &>/dev/null
info "running \`rustfmt +nightly \$(git ls-files '*.rs')\`"
rustfmt +nightly $(git ls-files '*.rs')
fi
cast_without_turbofish=$(grep -n -E '\.cast\(\)' $(git ls-files '*.rs') || true)
if [[ -n "${cast_without_turbofish}" ]]; then
error "please replace \`.cast()\` with \`.cast::<type_name>()\`:"
echo "${cast_without_turbofish}"
check_diff $(git ls-files '*.rs')
fi
cast_without_turbofish=$(grep -n -E '\.cast\(\)' $(git ls-files '*.rs') || true)
if [[ -n "${cast_without_turbofish}" ]]; then
error "please replace \`.cast()\` with \`.cast::<type_name>()\`:"
echo "${cast_without_turbofish}"
fi
# Sync readme and crate-level doc.
first='1'
for readme in $(git ls-files '*README.md'); do
if ! grep -q '^<!-- tidy:crate-doc:start -->' "${readme}"; then
continue
fi
# Sync readme and crate-level doc.
first='1'
for readme in $(git ls-files '*README.md'); do
if ! grep -q '^<!-- tidy:crate-doc:start -->' "${readme}"; then
continue
fi
lib="$(dirname "${readme}")/src/lib.rs"
if [[ -n "${first}" ]]; then
first=''
info "checking readme and crate-level doc are synchronized"
fi
if ! grep -q '^<!-- tidy:crate-doc:end -->' "${readme}"; then
bail "missing '<!-- tidy:crate-doc:end -->' comment in ${readme}"
fi
if ! grep -q '^<!-- tidy:crate-doc:start -->' "${lib}"; then
bail "missing '<!-- tidy:crate-doc:start -->' comment in ${lib}"
fi
if ! grep -q '^<!-- tidy:crate-doc:end -->' "${lib}"; then
bail "missing '<!-- tidy:crate-doc:end -->' comment in ${lib}"
fi
new=$(tr <"${readme}" '\n' '\a' | grep -o '<!-- tidy:crate-doc:start -->.*<!-- tidy:crate-doc:end -->' | sed 's/\&/\\\&/g; s/\\/\\\\/g')
new=$(tr <"${lib}" '\n' '\a' | awk -v new="${new}" 'gsub("<!-- tidy:crate-doc:start -->.*<!-- tidy:crate-doc:end -->",new)' | tr '\a' '\n')
echo "${new}" >"${lib}"
check_diff "${lib}"
done
# Make sure that public Rust crates don't contain executables and binaries.
executables=''
binaries=''
metadata=$(cargo metadata --format-version=1 --no-deps)
has_public_crate=''
has_root_crate=''
venv_install_yq
for id in $(jq <<<"${metadata}" '.workspace_members[]'); do
pkg=$(jq <<<"${metadata}" ".packages[] | select(.id == ${id})")
publish=$(jq <<<"${pkg}" -r '.publish')
manifest_path=$(jq <<<"${pkg}" -r '.manifest_path')
if [[ "$(venv tomlq -c '.lints' "${manifest_path}")" == "null" ]]; then
error "no [lints] table in ${manifest_path} please add '[lints]' with 'workspace = true'"
fi
lib="$(dirname "${readme}")/src/lib.rs"
if [[ -n "${first}" ]]; then
first=''
info "checking readme and crate-level doc are synchronized"
fi
if ! grep -q '^<!-- tidy:crate-doc:end -->' "${readme}"; then
bail "missing '<!-- tidy:crate-doc:end -->' comment in ${readme}"
fi
if ! grep -q '^<!-- tidy:crate-doc:start -->' "${lib}"; then
bail "missing '<!-- tidy:crate-doc:start -->' comment in ${lib}"
fi
if ! grep -q '^<!-- tidy:crate-doc:end -->' "${lib}"; then
bail "missing '<!-- tidy:crate-doc:end -->' comment in ${lib}"
fi
new=$(tr <"${readme}" '\n' '\a' | grep -o '<!-- tidy:crate-doc:start -->.*<!-- tidy:crate-doc:end -->' | sed 's/\&/\\\&/g; s/\\/\\\\/g')
new=$(tr <"${lib}" '\n' '\a' | awk -v new="${new}" 'gsub("<!-- tidy:crate-doc:start -->.*<!-- tidy:crate-doc:end -->",new)' | tr '\a' '\n')
echo "${new}" >"${lib}"
check_diff "${lib}"
done
# Make sure that public Rust crates don't contain executables and binaries.
executables=''
binaries=''
metadata=$(cargo metadata --format-version=1 --no-deps)
has_public_crate=''
has_root_crate=''
venv_install_yq
for id in $(jq <<<"${metadata}" '.workspace_members[]'); do
pkg=$(jq <<<"${metadata}" ".packages[] | select(.id == ${id})")
publish=$(jq <<<"${pkg}" -r '.publish')
manifest_path=$(jq <<<"${pkg}" -r '.manifest_path')
if [[ "$(venv tomlq -c '.lints' "${manifest_path}")" == "null" ]]; then
error "no [lints] table in ${manifest_path} please add '[lints]' with 'workspace = true'"
fi
# Publishing is unrestricted if null, and forbidden if an empty array.
if [[ "${publish}" == "[]" ]]; then
continue
fi
has_public_crate='1'
done
if [[ -n "${has_public_crate}" ]]; then
info "checking public crates don't contain executables and binaries"
if [[ -f Cargo.toml ]]; then
root_manifest=$(cargo locate-project --message-format=plain --manifest-path Cargo.toml)
root_pkg=$(jq <<<"${metadata}" ".packages[] | select(.manifest_path == \"${root_manifest}\")")
if [[ -n "${root_pkg}" ]]; then
publish=$(jq <<<"${root_pkg}" -r '.publish')
# Publishing is unrestricted if null, and forbidden if an empty array.
if [[ "${publish}" == "[]" ]]; then
continue
fi
has_public_crate='1'
done
if [[ -n "${has_public_crate}" ]]; then
info "checking public crates don't contain executables and binaries"
if [[ -f Cargo.toml ]]; then
root_manifest=$(cargo locate-project --message-format=plain --manifest-path Cargo.toml)
root_pkg=$(jq <<<"${metadata}" ".packages[] | select(.manifest_path == \"${root_manifest}\")")
if [[ -n "${root_pkg}" ]]; then
publish=$(jq <<<"${root_pkg}" -r '.publish')
# Publishing is unrestricted if null, and forbidden if an empty array.
if [[ "${publish}" != "[]" ]]; then
has_root_crate=1
exclude=$(venv tomlq -r '.package.exclude[]' Cargo.toml)
if ! grep <<<"${exclude}" -Eq '^/\.\*$'; then
error "top-level Cargo.toml of non-virtual workspace should have 'exclude' field with \"/.*\""
fi
if [[ -e tools ]] && ! grep <<<"${exclude}" -Eq '^/tools$'; then
error "top-level Cargo.toml of non-virtual workspace should have 'exclude' field with \"/tools\" if it exists"
fi
if [[ -e target-specs ]] && ! grep <<<"${exclude}" -Eq '^/target-specs$'; then
error "top-level Cargo.toml of non-virtual workspace should have 'exclude' field with \"/target-specs\" if it exists"
fi
fi
fi
fi
for p in $(git ls-files); do
# Skip directories.
if [[ -d "${p}" ]]; then
continue
fi
# Top-level hidden files/directories and tools/* are excluded from crates.io (ensured by the above check).
# TODO: fully respect exclude field in Cargo.toml.
case "${p}" in
.* | tools/* | target-specs/*) continue ;;
*/*) ;;
*)
# If there is no crate at root, executables at the repository root directory if always okay.
if [[ -z "${has_root_crate}" ]]; then
continue
fi
;;
esac
if [[ -x "${p}" ]]; then
executables+="${p}"$'\n'
fi
# Use diff instead of file because file treats an empty file as a binary
# https://unix.stackexchange.com/questions/275516/is-there-a-convenient-way-to-classify-files-as-binary-or-text#answer-402870
if (diff .gitattributes "${p}" || true) | grep -q '^Binary file'; then
binaries+="${p}"$'\n'
fi
done
if [[ -n "${executables}" ]]; then
error "file-permissions-check failed: executables are only allowed to be present in directories that are excluded from crates.io"
echo "======================================="
echo -n "${executables}"
echo "======================================="
fi
if [[ -n "${binaries}" ]]; then
error "file-permissions-check failed: binaries are only allowed to be present in directories that are excluded from crates.io"
echo "======================================="
echo -n "${binaries}"
echo "======================================="
if [[ "${publish}" != "[]" ]]; then
has_root_crate=1
exclude=$(venv tomlq -r '.package.exclude[]' Cargo.toml)
if ! grep <<<"${exclude}" -Eq '^/\.\*$'; then
error "top-level Cargo.toml of non-virtual workspace should have 'exclude' field with \"/.*\""
fi
if [[ -e tools ]] && ! grep <<<"${exclude}" -Eq '^/tools$'; then
error "top-level Cargo.toml of non-virtual workspace should have 'exclude' field with \"/tools\" if it exists"
fi
if [[ -e target-specs ]] && ! grep <<<"${exclude}" -Eq '^/target-specs$'; then
error "top-level Cargo.toml of non-virtual workspace should have 'exclude' field with \"/target-specs\" if it exists"
fi
fi
fi
fi
for p in $(git ls-files); do
# Skip directories.
if [[ -d "${p}" ]]; then
continue
fi
# Top-level hidden files/directories and tools/* are excluded from crates.io (ensured by the above check).
# TODO: fully respect exclude field in Cargo.toml.
case "${p}" in
.* | tools/* | target-specs/*) continue ;;
*/*) ;;
*)
# If there is no crate at root, executables at the repository root directory if always okay.
if [[ -z "${has_root_crate}" ]]; then
continue
fi
;;
esac
if [[ -x "${p}" ]]; then
executables+="${p}"$'\n'
fi
# Use diff instead of file because file treats an empty file as a binary
# https://unix.stackexchange.com/questions/275516/is-there-a-convenient-way-to-classify-files-as-binary-or-text#answer-402870
if (diff .gitattributes "${p}" || true) | grep -q '^Binary file'; then
binaries+="${p}"$'\n'
fi
done
if [[ -n "${executables}" ]]; then
error "file-permissions-check failed: executables are only allowed to be present in directories that are excluded from crates.io"
echo "======================================="
echo -n "${executables}"
echo "======================================="
fi
if [[ -n "${binaries}" ]]; then
error "file-permissions-check failed: binaries are only allowed to be present in directories that are excluded from crates.io"
echo "======================================="
echo -n "${binaries}"
echo "======================================="
fi
fi
elif [[ -e .rustfmt.toml ]]; then
error ".rustfmt.toml is unused"
error ".rustfmt.toml is unused"
fi
# C/C++ (if exists)
if [[ -n "$(git ls-files '*.c' '*.h' '*.cpp' '*.hpp')" ]]; then
info "checking C/C++ code style"
check_config .clang-format
if check_install clang-format; then
info "running \`clang-format -i \$(git ls-files '*.c' '*.h' '*.cpp' '*.hpp')\`"
clang-format -i $(git ls-files '*.c' '*.h' '*.cpp' '*.hpp')
check_diff $(git ls-files '*.c' '*.h' '*.cpp' '*.hpp')
fi
info "checking C/C++ code style"
check_config .clang-format
if check_install clang-format; then
info "running \`clang-format -i \$(git ls-files '*.c' '*.h' '*.cpp' '*.hpp')\`"
clang-format -i $(git ls-files '*.c' '*.h' '*.cpp' '*.hpp')
check_diff $(git ls-files '*.c' '*.h' '*.cpp' '*.hpp')
fi
elif [[ -e .clang-format ]]; then
error ".clang-format is unused"
error ".clang-format is unused"
fi
# YAML/JavaScript/JSON (if exists)
if [[ -n "$(git ls-files '*.yml' '*.yaml' '*.js' '*.json')" ]]; then
info "checking YAML/JavaScript/JSON code style"
check_config .editorconfig
if check_install npm; then
info "running \`npx -y prettier -l -w \$(git ls-files '*.yml' '*.yaml' '*.js' '*.json')\`"
npx -y prettier -l -w $(git ls-files '*.yml' '*.yaml' '*.js' '*.json')
check_diff $(git ls-files '*.yml' '*.yaml' '*.js' '*.json')
fi
# Check GitHub workflows.
if [[ -d .github/workflows ]]; then
info "checking GitHub workflows"
if check_install jq python3; then
venv_install_yq
for workflow in .github/workflows/*.yml; do
# The top-level permissions must be weak as they are referenced by all jobs.
permissions=$(venv yq -c '.permissions' "${workflow}")
case "${permissions}" in
'{"contents":"read"}' | '{"contents":"none"}') ;;
null) error "${workflow}: top level permissions not found; it must be 'contents: read' or weaker permissions" ;;
*) error "${workflow}: only 'contents: read' and weaker permissions are allowed at top level; if you want to use stronger permissions, please set job-level permissions" ;;
esac
# Make sure the 'needs' section is not out of date.
if grep -q '# tidy:needs' "${workflow}" && ! grep -Eq '# *needs: \[' "${workflow}"; then
# shellcheck disable=SC2207
jobs_actual=($(venv yq '.jobs' "${workflow}" | jq -r 'keys_unsorted[]'))
unset 'jobs_actual[${#jobs_actual[@]}-1]'
# shellcheck disable=SC2207
jobs_expected=($(venv yq -r '.jobs."ci-success".needs[]' "${workflow}"))
if [[ "${jobs_actual[*]}" != "${jobs_expected[*]+"${jobs_expected[*]}"}" ]]; then
printf -v jobs '%s, ' "${jobs_actual[@]}"
sed -i "s/needs: \[.*\] # tidy:needs/needs: [${jobs%, }] # tidy:needs/" "${workflow}"
check_diff "${workflow}"
error "${workflow}: please update 'needs' section in 'ci-success' job"
fi
fi
done
info "checking YAML/JavaScript/JSON code style"
check_config .editorconfig
if check_install npm; then
info "running \`npx -y prettier -l -w \$(git ls-files '*.yml' '*.yaml' '*.js' '*.json')\`"
npx -y prettier -l -w $(git ls-files '*.yml' '*.yaml' '*.js' '*.json')
check_diff $(git ls-files '*.yml' '*.yaml' '*.js' '*.json')
fi
# Check GitHub workflows.
if [[ -d .github/workflows ]]; then
info "checking GitHub workflows"
if check_install jq python3; then
venv_install_yq
for workflow in .github/workflows/*.yml; do
# The top-level permissions must be weak as they are referenced by all jobs.
permissions=$(venv yq -c '.permissions' "${workflow}")
case "${permissions}" in
'{"contents":"read"}' | '{"contents":"none"}') ;;
null) error "${workflow}: top level permissions not found; it must be 'contents: read' or weaker permissions" ;;
*) error "${workflow}: only 'contents: read' and weaker permissions are allowed at top level; if you want to use stronger permissions, please set job-level permissions" ;;
esac
# Make sure the 'needs' section is not out of date.
if grep -q '# tidy:needs' "${workflow}" && ! grep -Eq '# *needs: \[' "${workflow}"; then
# shellcheck disable=SC2207
jobs_actual=($(venv yq '.jobs' "${workflow}" | jq -r 'keys_unsorted[]'))
unset 'jobs_actual[${#jobs_actual[@]}-1]'
# shellcheck disable=SC2207
jobs_expected=($(venv yq -r '.jobs."ci-success".needs[]' "${workflow}"))
if [[ "${jobs_actual[*]}" != "${jobs_expected[*]+"${jobs_expected[*]}"}" ]]; then
printf -v jobs '%s, ' "${jobs_actual[@]}"
sed -i "s/needs: \[.*\] # tidy:needs/needs: [${jobs%, }] # tidy:needs/" "${workflow}"
check_diff "${workflow}"
error "${workflow}: please update 'needs' section in 'ci-success' job"
fi
fi
done
fi
fi
fi
if [[ -n "$(git ls-files '*.yaml' | (grep -v .markdownlint-cli2.yaml || true))" ]]; then
error "please use '.yml' instead of '.yaml' for consistency"
git ls-files '*.yaml' | (grep -v .markdownlint-cli2.yaml || true)
error "please use '.yml' instead of '.yaml' for consistency"
git ls-files '*.yaml' | (grep -v .markdownlint-cli2.yaml || true)
fi
# TOML (if exists)
if [[ -n "$(git ls-files '*.toml' | (grep -v .taplo.toml || true))" ]]; then
info "checking TOML style"
check_config .taplo.toml
if check_install npm; then
info "running \`npx -y @taplo/cli fmt \$(git ls-files '*.toml')\`"
RUST_LOG=warn npx -y @taplo/cli fmt $(git ls-files '*.toml')
check_diff $(git ls-files '*.toml')
fi
info "checking TOML style"
check_config .taplo.toml
if check_install npm; then
info "running \`npx -y @taplo/cli fmt \$(git ls-files '*.toml')\`"
RUST_LOG=warn npx -y @taplo/cli fmt $(git ls-files '*.toml')
check_diff $(git ls-files '*.toml')
fi
elif [[ -e .taplo.toml ]]; then
error ".taplo.toml is unused"
error ".taplo.toml is unused"
fi
# Markdown (if exists)
if [[ -n "$(git ls-files '*.md')" ]]; then
info "checking Markdown style"
check_config .markdownlint-cli2.yaml
if check_install npm; then
info "running \`npx -y markdownlint-cli2 \$(git ls-files '*.md')\`"
npx -y markdownlint-cli2 $(git ls-files '*.md')
fi
info "checking Markdown style"
check_config .markdownlint-cli2.yaml
if check_install npm; then
info "running \`npx -y markdownlint-cli2 \$(git ls-files '*.md')\`"
npx -y markdownlint-cli2 $(git ls-files '*.md')
fi
elif [[ -e .markdownlint-cli2.yaml ]]; then
error ".markdownlint-cli2.yaml is unused"
error ".markdownlint-cli2.yaml is unused"
fi
if [[ -n "$(git ls-files '*.markdown')" ]]; then
error "please use '.md' instead of '.markdown' for consistency"
git ls-files '*.markdown'
error "please use '.md' instead of '.markdown' for consistency"
git ls-files '*.markdown'
fi
# Shell scripts
info "checking Shell scripts"
if check_install shfmt; then
check_config .editorconfig
info "running \`shfmt -l -w \$(git ls-files '*.sh')\`"
shfmt -l -w $(git ls-files '*.sh')
check_diff $(git ls-files '*.sh')
check_config .editorconfig
info "running \`shfmt -l -w \$(git ls-files '*.sh')\`"
shfmt -l -w $(git ls-files '*.sh')
check_diff $(git ls-files '*.sh')
fi
if check_install shellcheck; then
check_config .shellcheckrc
info "running \`shellcheck \$(git ls-files '*.sh')\`"
if ! shellcheck $(git ls-files '*.sh'); then
should_fail=1
fi
if [[ -n "$(git ls-files '*Dockerfile')" ]]; then
# SC2154 doesn't seem to work on dockerfile.
info "running \`shellcheck -e SC2148,SC2154,SC2250 \$(git ls-files '*Dockerfile')\`"
if ! shellcheck -e SC2148,SC2154,SC2250 $(git ls-files '*Dockerfile'); then
should_fail=1
fi
check_config .shellcheckrc
info "running \`shellcheck \$(git ls-files '*.sh')\`"
if ! shellcheck $(git ls-files '*.sh'); then
should_fail=1
fi
if [[ -n "$(git ls-files '*Dockerfile')" ]]; then
# SC2154 doesn't seem to work on dockerfile.
info "running \`shellcheck -e SC2148,SC2154,SC2250 \$(git ls-files '*Dockerfile')\`"
if ! shellcheck -e SC2148,SC2154,SC2250 $(git ls-files '*Dockerfile'); then
should_fail=1
fi
fi
fi
# License check
# TODO: This check is still experimental and does not track all files that should be tracked.
if [[ -f tools/.tidy-check-license-headers ]]; then
info "checking license headers (experimental)"
failed_files=''
for p in $(eval $(<tools/.tidy-check-license-headers)); do
case "$(basename "${p}")" in
*.stderr | *.expanded.rs) continue ;; # generated files
*.sh | *.py | *.rb | *Dockerfile) prefix=("# ") ;;
*.rs | *.c | *.h | *.cpp | *.hpp | *.s | *.S | *.js) prefix=("// " "/* ") ;;
*.ld | *.x) prefix=("/* ") ;;
# TODO: More file types?
*) continue ;;
esac
# TODO: The exact line number is not actually important; it is important
# that it be part of the top-level comments of the file.
line="1"
if IFS= LC_ALL=C read -rn3 -d '' shebang <"${p}" && [[ "${shebang}" == '#!/' ]]; then
line="2"
elif [[ "${p}" == *"Dockerfile" ]] && IFS= LC_ALL=C read -rn9 -d '' syntax <"${p}" && [[ "${syntax}" == '# syntax=' ]]; then
line="2"
fi
header_found=''
for pre in "${prefix[@]}"; do
# TODO: check that the license is valid as SPDX and is allowed in this project.
if [[ "$(grep -E -n "${pre}SPDX-License-Identifier: " "${p}")" == "${line}:${pre}SPDX-License-Identifier: "* ]]; then
header_found='1'
break
fi
done
if [[ -z "${header_found}" ]]; then
failed_files+="${p}:${line}"$'\n'
fi
done
if [[ -n "${failed_files}" ]]; then
error "license-check failed: please add SPDX-License-Identifier to the following files"
echo "======================================="
echo -n "${failed_files}"
echo "======================================="
info "checking license headers (experimental)"
failed_files=''
for p in $(eval $(<tools/.tidy-check-license-headers)); do
case "$(basename "${p}")" in
*.stderr | *.expanded.rs) continue ;; # generated files
*.sh | *.py | *.rb | *Dockerfile) prefix=("# ") ;;
*.rs | *.c | *.h | *.cpp | *.hpp | *.s | *.S | *.js) prefix=("// " "/* ") ;;
*.ld | *.x) prefix=("/* ") ;;
# TODO: More file types?
*) continue ;;
esac
# TODO: The exact line number is not actually important; it is important
# that it be part of the top-level comments of the file.
line="1"
if IFS= LC_ALL=C read -rn3 -d '' shebang <"${p}" && [[ "${shebang}" == '#!/' ]]; then
line="2"
elif [[ "${p}" == *"Dockerfile" ]] && IFS= LC_ALL=C read -rn9 -d '' syntax <"${p}" && [[ "${syntax}" == '# syntax=' ]]; then
line="2"
fi
header_found=''
for pre in "${prefix[@]}"; do
# TODO: check that the license is valid as SPDX and is allowed in this project.
if [[ "$(grep -E -n "${pre}SPDX-License-Identifier: " "${p}")" == "${line}:${pre}SPDX-License-Identifier: "* ]]; then
header_found='1'
break
fi
done
if [[ -z "${header_found}" ]]; then
failed_files+="${p}:${line}"$'\n'
fi
done
if [[ -n "${failed_files}" ]]; then
error "license-check failed: please add SPDX-License-Identifier to the following files"
echo "======================================="
echo -n "${failed_files}"
echo "======================================="
fi
fi
# Spell check (if config exists)
if [[ -f .cspell.json ]]; then
info "spell checking"
project_dictionary=.github/.cspell/project-dictionary.txt
if check_install npm jq python3; then
has_rust=''
if [[ -n "$(git ls-files '*Cargo.toml')" ]]; then
venv_install_yq
has_rust='1'
dependencies=''
for manifest_path in $(git ls-files '*Cargo.toml'); do
if [[ "${manifest_path}" != "Cargo.toml" ]] && [[ "$(venv tomlq -c '.workspace' "${manifest_path}")" == "null" ]]; then
continue
fi
metadata=$(cargo metadata --format-version=1 --no-deps --manifest-path "${manifest_path}")
for id in $(jq <<<"${metadata}" '.workspace_members[]'); do
dependencies+="$(jq <<<"${metadata}" ".packages[] | select(.id == ${id})" | jq -r '.dependencies[].name')"$'\n'
done
done
# shellcheck disable=SC2001
dependencies=$(sed <<<"${dependencies}" 's/[0-9_-]/\n/g' | LC_ALL=C sort -f -u)
info "spell checking"
project_dictionary=.github/.cspell/project-dictionary.txt
if check_install npm jq python3; then
has_rust=''
if [[ -n "$(git ls-files '*Cargo.toml')" ]]; then
venv_install_yq
has_rust='1'
dependencies=''
for manifest_path in $(git ls-files '*Cargo.toml'); do
if [[ "${manifest_path}" != "Cargo.toml" ]] && [[ "$(venv tomlq -c '.workspace' "${manifest_path}")" == "null" ]]; then
continue
fi
config_old=$(<.cspell.json)
config_new=$(grep <<<"${config_old}" -v '^ *//' | jq 'del(.dictionaries[] | select(index("organization-dictionary") | not))' | jq 'del(.dictionaryDefinitions[] | select(.name == "organization-dictionary" | not))')
trap -- 'echo "${config_old}" >.cspell.json; echo >&2 "$0: trapped SIGINT"; exit 1' SIGINT
echo "${config_new}" >.cspell.json
if [[ -n "${has_rust}" ]]; then
dependencies_words=$(npx <<<"${dependencies}" -y cspell stdin --no-progress --no-summary --words-only --unique || true)
fi
all_words=$(npx -y cspell --no-progress --no-summary --words-only --unique $(git ls-files | (grep -v "${project_dictionary//\./\\.}" || true)) || true)
echo "${config_old}" >.cspell.json
trap - SIGINT
cat >.github/.cspell/rust-dependencies.txt <<EOF
metadata=$(cargo metadata --format-version=1 --no-deps --manifest-path "${manifest_path}")
for id in $(jq <<<"${metadata}" '.workspace_members[]'); do
dependencies+="$(jq <<<"${metadata}" ".packages[] | select(.id == ${id})" | jq -r '.dependencies[].name')"$'\n'
done
done
# shellcheck disable=SC2001
dependencies=$(sed <<<"${dependencies}" 's/[0-9_-]/\n/g' | LC_ALL=C sort -f -u)
fi
config_old=$(<.cspell.json)
config_new=$(grep <<<"${config_old}" -v '^ *//' | jq 'del(.dictionaries[] | select(index("organization-dictionary") | not))' | jq 'del(.dictionaryDefinitions[] | select(.name == "organization-dictionary" | not))')
trap -- 'echo "${config_old}" >.cspell.json; echo >&2 "$0: trapped SIGINT"; exit 1' SIGINT
echo "${config_new}" >.cspell.json
if [[ -n "${has_rust}" ]]; then
dependencies_words=$(npx <<<"${dependencies}" -y cspell stdin --no-progress --no-summary --words-only --unique || true)
fi
all_words=$(npx -y cspell --no-progress --no-summary --words-only --unique $(git ls-files | (grep -v "${project_dictionary//\./\\.}" || true)) || true)
echo "${config_old}" >.cspell.json
trap - SIGINT
cat >.github/.cspell/rust-dependencies.txt <<EOF
// This file is @generated by $(basename "$0").
// It is not intended for manual editing.
EOF
if [[ -n "${dependencies_words:-}" ]]; then
echo $'\n'"${dependencies_words}" >>.github/.cspell/rust-dependencies.txt
fi
if [[ -z "${REMOVE_UNUSED_WORDS:-}" ]]; then
check_diff .github/.cspell/rust-dependencies.txt
fi
if ! grep -Fq '.github/.cspell/rust-dependencies.txt linguist-generated' .gitattributes; then
error "you may want to mark .github/.cspell/rust-dependencies.txt linguist-generated"
fi
info "running \`npx -y cspell --no-progress --no-summary \$(git ls-files)\`"
if ! npx -y cspell --no-progress --no-summary $(git ls-files); then
error "spellcheck failed: please fix uses of above words or add to ${project_dictionary} if correct"
fi
# Make sure the project-specific dictionary does not contain duplicated words.
for dictionary in .github/.cspell/*.txt; do
if [[ "${dictionary}" == "${project_dictionary}" ]]; then
continue
fi
dup=$(sed '/^$/d' "${project_dictionary}" "${dictionary}" | LC_ALL=C sort -f | uniq -d -i | (grep -v '//.*' || true))
if [[ -n "${dup}" ]]; then
error "duplicated words in dictionaries; please remove the following words from ${project_dictionary}"
echo "======================================="
echo "${dup}"
echo "======================================="
fi
done
# Make sure the project-specific dictionary does not contain unused words.
if [[ -n "${REMOVE_UNUSED_WORDS:-}" ]]; then
grep_args=()
for word in $(grep -Ev '^//.*' "${project_dictionary}" || true); do
if ! grep -Eqi "^${word}$" <<<"${all_words}"; then
grep_args+=(-e "^${word}$")
fi
done
if [[ ${#grep_args[@]} -gt 0 ]]; then
info "removing unused words from ${project_dictionary}"
res=$(grep -Ev "${grep_args[@]}" "${project_dictionary}")
printf '%s\n' "${res}" >|"${project_dictionary}"
fi
else
unused=''
for word in $(grep -Ev '^//.*' "${project_dictionary}" || true); do
if ! grep -Eqi "^${word}$" <<<"${all_words}"; then
unused+="${word}"$'\n'
fi
done
if [[ -n "${unused}" ]]; then
error "unused words in dictionaries; please remove the following words from ${project_dictionary} or run ${0##*/} with REMOVE_UNUSED_WORDS=1"
printf '=======================================\n'
printf '%s' "${unused}"
printf '=======================================\n'
fi
fi
if [[ -n "${dependencies_words:-}" ]]; then
echo $'\n'"${dependencies_words}" >>.github/.cspell/rust-dependencies.txt
fi
if [[ -z "${REMOVE_UNUSED_WORDS:-}" ]]; then
check_diff .github/.cspell/rust-dependencies.txt
fi
if ! grep -Fq '.github/.cspell/rust-dependencies.txt linguist-generated' .gitattributes; then
error "you may want to mark .github/.cspell/rust-dependencies.txt linguist-generated"
fi
info "running \`npx -y cspell --no-progress --no-summary \$(git ls-files)\`"
if ! npx -y cspell --no-progress --no-summary $(git ls-files); then
error "spellcheck failed: please fix uses of above words or add to ${project_dictionary} if correct"
fi
# Make sure the project-specific dictionary does not contain duplicated words.
for dictionary in .github/.cspell/*.txt; do
if [[ "${dictionary}" == "${project_dictionary}" ]]; then
continue
fi
dup=$(sed '/^$/d' "${project_dictionary}" "${dictionary}" | LC_ALL=C sort -f | uniq -d -i | (grep -v '//.*' || true))
if [[ -n "${dup}" ]]; then
error "duplicated words in dictionaries; please remove the following words from ${project_dictionary}"
echo "======================================="
echo "${dup}"
echo "======================================="
fi
done
# Make sure the project-specific dictionary does not contain unused words.
if [[ -n "${REMOVE_UNUSED_WORDS:-}" ]]; then
grep_args=()
for word in $(grep -Ev '^//.*' "${project_dictionary}" || true); do
if ! grep -Eqi "^${word}$" <<<"${all_words}"; then
grep_args+=(-e "^${word}$")
fi
done
if [[ ${#grep_args[@]} -gt 0 ]]; then
info "removing unused words from ${project_dictionary}"
res=$(grep -Ev "${grep_args[@]}" "${project_dictionary}")
printf '%s\n' "${res}" >|"${project_dictionary}"
fi
else
unused=''
for word in $(grep -Ev '^//.*' "${project_dictionary}" || true); do
if ! grep -Eqi "^${word}$" <<<"${all_words}"; then
unused+="${word}"$'\n'
fi
done
if [[ -n "${unused}" ]]; then
error "unused words in dictionaries; please remove the following words from ${project_dictionary} or run ${0##*/} with REMOVE_UNUSED_WORDS=1"
printf '=======================================\n'
printf '%s' "${unused}"
printf '=======================================\n'
fi
fi
fi
fi
if [[ -n "${should_fail:-}" ]]; then
exit 1
exit 1
fi