Generate Markdown table of tools (#473)

This commit is contained in:
John Vandenberg
2024-06-04 02:56:04 +08:00
committed by GitHub
parent 9b00020f6f
commit d7080cb663
61 changed files with 998 additions and 400 deletions

View File

@@ -4,13 +4,11 @@
(Example: [ffbd316](https://github.com/taiki-e/install-action/commit/ffbd316e0fe98cb460dae3a66cd2ef9deb398bb1))
1\. Add tool name to the table in ["Supported tools" section in `README.md`](https://github.com/taiki-e/install-action#supported-tools).
2\. Add base manifest to [`tools/codegen/base`](tools/codegen/base) directory.
1\. Add base manifest to [`tools/codegen/base`](tools/codegen/base) directory.
See JSON files in `tools/codegen/base` directory for examples of the manifest.
3\. Generate manifest with the following command (replace `<tool>` with the tool name).
2\. Generate manifest with the following command (replace `<tool>` with the tool name).
```sh
./tools/manifest.sh <tool>
@@ -23,6 +21,14 @@ See JSON files in `tools/codegen/base` directory for examples of the manifest.
> GITHUB_TOKEN=$(gh auth status --show-token 2>&1 | sed -n 's/^.*Token: \(.*\)$/\1/p') ./tools/manifest.sh <tool>
> ```
## Refresh TOOLS.md
To update `TOOLS.md`, run
```sh
./tools/update-markdown.sh
```
## Troubleshooting
If one of the CI builds fails due to a bin path or release asset_name, fix the problem in the base

View File

@@ -1,3 +1,4 @@
<!-- omit in toc -->
# install-action
[![release](https://img.shields.io/github/release/taiki-e/install-action?style=flat-square&logo=github)](https://github.com/taiki-e/install-action/releases/latest)
@@ -74,57 +75,7 @@ Or:
## Supported tools
<!--
License should use SPDX license identifiers.
https://spdx.org/licenses
-->
| Name | Where binaries will be installed | Where will it be installed from | Supported platform | License |
| ---- | -------------------------------- | ------------------------------- | ------------------ | ------- |
| [**biome**](https://biomejs.dev)| `/usr/local/bin` | [GitHub Releases](https://github.com/biomejs/biome/releases) | Linux, macOS, Windows | [MIT](https://github.com/biomejs/biome/blob/HEAD/LICENSE) |
| [**cargo-audit**](https://github.com/rustsec/rustsec/tree/HEAD/cargo-audit) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rustsec/rustsec/releases) | Linux, macOS, Windows | [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) |
| [**cargo-binstall**][cargo-binstall] | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/cargo-bins/cargo-binstall/releases) | Linux, macOS, Windows | [GPL-3.0](https://github.com/cargo-bins/cargo-binstall/blob/HEAD/crates/bin/LICENSE) |
| [**cargo-careful**](https://github.com/RalfJung/cargo-careful) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/RalfJung/cargo-careful/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/RalfJung/cargo-careful/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/RalfJung/cargo-careful/blob/HEAD/LICENSE-MIT) |
| [**cargo-cyclonedx**](https://github.com/CycloneDX/cyclonedx-rust-cargo) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/CycloneDX/cyclonedx-rust-cargo/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/CycloneDX/cyclonedx-rust-cargo/blob/HEAD/LICENSE) |
| [**cargo-deny**](https://github.com/EmbarkStudios/cargo-deny) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/EmbarkStudios/cargo-deny/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/EmbarkStudios/cargo-deny/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/EmbarkStudios/cargo-deny/blob/HEAD/LICENSE-MIT) |
| [**cargo-dinghy**](https://github.com/sonos/dinghy) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/sonos/dinghy/releases) | Linux, macOS | [Apache-2.0](https://github.com/sonos/dinghy/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/sonos/dinghy/blob/HEAD/LICENSE-MIT) |
| [**cargo-export**](https://github.com/bazhenov/cargo-export) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/bazhenov/cargo-export/releases) | Linux, macOS, Windows | [MIT](https://github.com/bazhenov/cargo-export/blob/HEAD/LICENSE) |
| [**cargo-hack**](https://github.com/taiki-e/cargo-hack) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-hack/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/taiki-e/cargo-hack/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-hack/blob/HEAD/LICENSE-MIT) |
| [**cargo-llvm-cov**](https://github.com/taiki-e/cargo-llvm-cov) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-llvm-cov/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/taiki-e/cargo-llvm-cov/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-llvm-cov/blob/HEAD/LICENSE-MIT) |
| [**cargo-machete**](https://github.com/bnjbvr/cargo-machete) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/bnjbvr/cargo-machete/releases) | Linux, macOS, Windows | [MIT](https://github.com/bnjbvr/cargo-machete/blob/HEAD/LICENSE.md) |
| [**cargo-make**](https://github.com/sagiegurari/cargo-make) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/sagiegurari/cargo-make/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/sagiegurari/cargo-make/blob/HEAD/LICENSE) |
| [**cargo-minimal-versions**](https://github.com/taiki-e/cargo-minimal-versions) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-minimal-versions/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/taiki-e/cargo-minimal-versions/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-minimal-versions/blob/HEAD/LICENSE-MIT) |
| [**cargo-no-dev-deps**](https://github.com/taiki-e/cargo-no-dev-deps) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-no-dev-deps/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/taiki-e/cargo-no-dev-deps/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-no-dev-deps/blob/HEAD/LICENSE-MIT) |
| [**cargo-rdme**](https://github.com/orium/cargo-rdme) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/orium/cargo-rdme/releases) | Linux, macOS, Windows | [MPL-2.0](https://github.com/orium/cargo-rdme/blob/HEAD/LICENSE.md) |
| [**cargo-sort**](https://github.com/DevinR528/cargo-sort) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/DevinR528/cargo-sort/releases) | Linux, macOS, Windows | [Apache-2.0 OR MIT](https://github.com/DevinR528/cargo-sort/blob/55ec89082466f6bb246d870a8d56d166a8e1f08b/Cargo.toml#L5) |
| [**cargo-spellcheck**](https://github.com/drahnr/cargo-spellcheck) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/drahnr/cargo-spellcheck/releases) | Linux and Windows | [LGPLv2.1](https://github.com/drahnr/cargo-spellcheck/blob/f60c81ad0134c12faf08715f08d14f66e749f6e7/docs/checkers.md#nlprules) |
| [**cargo-tarpaulin**](https://github.com/xd009642/tarpaulin) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/xd009642/tarpaulin/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/xd009642/tarpaulin/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/xd009642/tarpaulin/blob/HEAD/LICENSE-MIT) |
| [**cargo-udeps**](https://github.com/est31/cargo-udeps) | `$CARGO_HOME/bin` | [GitHub Release](https://github.com/est31/cargo-udeps/releases) | Linux, macOS, Windows | [Apache-2.0 OR MIT](https://github.com/est31/cargo-udeps/blob/HEAD/LICENSE) |
| [**cargo-valgrind**](https://github.com/jfrimmel/cargo-valgrind) | `$CARGO_HOME/bin` | [GitHub Release](https://github.com/jfrimmel/cargo-valgrind/releases) | Linux, macOS, Windows | [MIT](https://github.com/jfrimmel/cargo-valgrind/blob/HEAD/LICENSE-MIT) or [Apache-2.0](https://github.com/jfrimmel/cargo-valgrind/blob/HEAD/LICENSE-APACHE) |
| [**cross**](https://github.com/cross-rs/cross) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/cross-rs/cross/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/cross-rs/cross/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/cross-rs/cross/blob/HEAD/LICENSE-MIT) |
| [**dprint**](https://github.com/dprint/dprint) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/dprint/dprint/releases) | Linux, macOS, Windows | [MIT](https://github.com/dprint/dprint/blob/HEAD/LICENSE) |
| [**espup**](https://github.com/esp-rs/espup) | `$CARGO_HOME/bin` | [GitHub Release](https://github.com/esp-rs/espup/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/esp-rs/espup/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/esp-rs/espup/blob/HEAD/LICENSE-MIT) |
| [**git-cliff**](https://github.com/orhun/git-cliff) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/orhun/git-cliff/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/orhun/git-cliff/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/orhun/git-cliff/blob/HEAD/LICENSE-MIT) |
| [**grcov**](https://github.com/mozilla/grcov) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/mozilla/grcov/releases) | Linux, macOS, Windows | [MPL-2.0](https://github.com/mozilla/grcov/blob/HEAD/LICENSE-MPL-2.0) |
| [**hyperfine**](https://github.com/sharkdp/hyperfine) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/sharkdp/hyperfine/releases) | Linux, macOS, Windows | [MIT](https://github.com/sharkdp/hyperfine/blob/HEAD/LICENSE-MIT) or [Apache-2.0](https://github.com/sharkdp/hyperfine/blob/HEAD/LICENSE-APACHE) |
| [**just**](https://github.com/casey/just) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/casey/just/releases) | Linux, macOS, Windows | [CC0-1.0](https://github.com/casey/just/blob/HEAD/LICENSE) |
| [**mdbook-linkcheck**](https://github.com/Michael-F-Bryan/mdbook-linkcheck) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/Michael-F-Bryan/mdbook-linkcheck/releases) | Linux, macOS, Windows | [MIT](https://github.com/Michael-F-Bryan/mdbook-linkcheck/blob/HEAD/LICENSE) |
| [**mdbook**](https://github.com/rust-lang/mdBook) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rust-lang/mdBook/releases) | Linux, macOS, Windows | [MPL-2.0](https://github.com/rust-lang/mdBook/blob/HEAD/LICENSE) |
| [**nextest**](https://github.com/nextest-rs/nextest) (alias: `cargo-nextest`) | `$CARGO_HOME/bin` | cargo-binstall | Linux, macOS, Windows | [Apache-2.0](https://github.com/nextest-rs/nextest/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/nextest-rs/nextest/blob/HEAD/LICENSE-MIT) |
| [**osv-scanner**]( https://github.com/google/osv-scanner) | `/usr/local/bin` | [GitHub Releases]( https://github.com/google/osv-scanner/releases) | Linux, macOS, Windows | [Apache-2](https://github.com/google/osv-scanner/blob/HEAD/LICENSE) |
| [**parse-changelog**](https://github.com/taiki-e/parse-changelog) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/parse-changelog/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/taiki-e/parse-changelog/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/parse-changelog/blob/HEAD/LICENSE-MIT) |
| [**protoc**](https://github.com/protocolbuffers/protobuf) | `$HOME/.install-action/bin` | [GitHub Releases](https://github.com/protocolbuffers/protobuf/releases) | Linux, macOS, Windows | [BSD-3-Clause](https://github.com/protocolbuffers/protobuf/blob/HEAD/LICENSE) |
| [**sccache**](https://github.com/mozilla/sccache) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/mozilla/sccache/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/mozilla/sccache/blob/HEAD/LICENSE) |
| [**shellcheck**](https://www.shellcheck.net) | `/usr/local/bin` | [GitHub Releases](https://github.com/koalaman/shellcheck/releases) | Linux, macOS, Windows | [GPL-3.0-or-later](https://github.com/koalaman/shellcheck/blob/HEAD/LICENSE) |
| [**shfmt**](https://github.com/mvdan/sh) | `/usr/local/bin` | [GitHub Releases](https://github.com/mvdan/sh/releases) | Linux, macOS, Windows | [BSD-3-Clause](https://github.com/mvdan/sh/blob/HEAD/LICENSE) |
| [**syft**](https://github.com/anchore/syft) | `/usr/local/bin` | [Github Releases](https://github.com/anchore/syft/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/anchore/syft/blob/HEAD/LICENSE) |
| [**typos**](https://github.com/crate-ci/typos) | `$CARGO_HOME/bin` | [Github Releases](https://github.com/crate-ci/typos/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/crate-ci/typos/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/crate-ci/typos/blob/HEAD/LICENSE-MIT) |
| [**valgrind**](https://valgrind.org) | `/snap/bin` | [snap](https://snapcraft.io/install/valgrind/ubuntu) | Linux | [GPL-2.0-or-later](https://valgrind.org/docs/manual/license.gpl.html) |
| [**wasm-bindgen**](https://github.com/rustwasm/wasm-bindgen) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rustwasm/wasm-bindgen/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/rustwasm/wasm-bindgen/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/rustwasm/wasm-bindgen/blob/HEAD/LICENSE-MIT) |
| [**wasm-pack**](https://github.com/rustwasm/wasm-pack) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rustwasm/wasm-pack/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/rustwasm/wasm-pack/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/rustwasm/wasm-pack/blob/HEAD/LICENSE-MIT) |
| [**wasmtime**](https://github.com/bytecodealliance/wasmtime) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/bytecodealliance/wasmtime/releases) | Linux, macOS, Windows | [Apache-2.0 WITH LLVM-exception](https://github.com/bytecodealliance/wasmtime/blob/HEAD/LICENSE) |
| [**xbuild**](https://github.com/rust-mobile/xbuild) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rust-mobile/xbuild/releases) | Linux, macOS, Windows | Apache-2.0 OR MIT |
| [**zola**](https://github.com/getzola/zola) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/getzola/zola/releases) | Linux, macOS, Windows | [MIT](https://github.com/getzola/zola/blob/HEAD/LICENSE) |
See [TOOLS.md](TOOLS.md) for the list of tools that are installed from manifests managed in this action.
If `$CARGO_HOME/bin` is not available, Rust-related binaries will be installed to `$HOME/.cargo/bin`.<br>
If `$HOME/.cargo/bin` is not available, Rust-related binaries will be installed to `/usr/local/bin`.<br>

49
TOOLS.md Normal file
View File

@@ -0,0 +1,49 @@
# Tools
| Name | Where binaries will be installed | Where will it be installed from | Supported platform | License |
| ---- | -------------------------------- | ------------------------------- | ------------------ | ------- |
| [**biome**](https://biomejs.dev) | `/usr/local/bin` | [GitHub Releases](https://github.com/biomejs/biome/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/biomejs/biome/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/biomejs/biome/blob/main/LICENSE-MIT) |
| [**cargo-audit**](https://github.com/rustsec/rustsec/tree/HEAD/cargo-audit) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rustsec/rustsec/releases) | Linux, macOS, Windows | [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) |
| [**cargo-binstall**](https://github.com/cargo-bins/cargo-binstall) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/cargo-bins/cargo-binstall/releases) | Linux, macOS, Windows | [GPL-3.0](https://github.com/cargo-bins/cargo-binstall/blob/HEAD/crates/bin/LICENSE) |
| [**cargo-careful**](https://github.com/RalfJung/cargo-careful) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/RalfJung/cargo-careful/releases) | Linux, macOS, Windows | [MIT](https://github.com/RalfJung/cargo-careful/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/RalfJung/cargo-careful/blob/master/LICENSE-APACHE) |
| [**cargo-cyclonedx**](https://github.com/CycloneDX/cyclonedx-rust-cargo) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/CycloneDX/cyclonedx-rust-cargo/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/CycloneDX/cyclonedx-rust-cargo/blob/main/LICENSE) |
| [**cargo-deny**](https://github.com/EmbarkStudios/cargo-deny) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/EmbarkStudios/cargo-deny/releases) | Linux, macOS, Windows | [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) |
| [**cargo-dinghy**](https://github.com/sonos/dinghy) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/sonos/dinghy/releases) | Linux, macOS | [MIT](https://github.com/sonos/dinghy/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/sonos/dinghy/blob/main/LICENSE-APACHE) |
| [**cargo-export**](https://github.com/bazhenov/cargo-export) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/bazhenov/cargo-export/releases) | Linux, macOS, Windows | [MIT](https://github.com/bazhenov/cargo-export/blob/master/LICENSE) |
| [**cargo-hack**](https://github.com/taiki-e/cargo-hack) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-hack/releases) | Linux, macOS, Windows | [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) |
| [**cargo-llvm-cov**](https://github.com/taiki-e/cargo-llvm-cov) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-llvm-cov/releases) | Linux, macOS, Windows | [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) |
| [**cargo-machete**](https://github.com/bnjbvr/cargo-machete) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/bnjbvr/cargo-machete/releases) | Linux, macOS, Windows | [MIT](https://github.com/bnjbvr/cargo-machete/blob/main/LICENSE.md) |
| [**cargo-make**](https://github.com/sagiegurari/cargo-make) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/sagiegurari/cargo-make/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE) |
| [**cargo-minimal-versions**](https://github.com/taiki-e/cargo-minimal-versions) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-minimal-versions/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/taiki-e/cargo-minimal-versions/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-minimal-versions/blob/main/LICENSE-MIT) |
| [**cargo-no-dev-deps**](https://github.com/taiki-e/cargo-no-dev-deps) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/cargo-no-dev-deps/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/taiki-e/cargo-no-dev-deps/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-no-dev-deps/blob/main/LICENSE-MIT) |
| [**cargo-rdme**](https://github.com/orium/cargo-rdme) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/orium/cargo-rdme/releases) | Linux, macOS, Windows | [MPL-2.0](https://github.com/orium/cargo-rdme/blob/main/LICENSE.md) |
| [**cargo-sort**](https://github.com/DevinR528/cargo-sort) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/DevinR528/cargo-sort/releases) | Linux, macOS, Windows | [Apache-2.0 OR MIT](https://github.com/DevinR528/cargo-sort/blob/55ec89082466f6bb246d870a8d56d166a8e1f08b/Cargo.toml#L5) |
| [**cargo-spellcheck**](https://github.com/drahnr/cargo-spellcheck) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/drahnr/cargo-spellcheck/releases) | Linux, Windows | [LGPLv2.1](https://github.com/drahnr/cargo-spellcheck/blob/master/LICENSE-LGPL) |
| [**cargo-tarpaulin**](https://github.com/xd009642/tarpaulin) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/xd009642/tarpaulin/releases) | Linux, macOS, Windows | [MIT](https://github.com/xd009642/tarpaulin/blob/develop/LICENSE-MIT) OR [Apache-2.0](https://github.com/xd009642/tarpaulin/blob/develop/LICENSE-APACHE) |
| [**cargo-udeps**](https://github.com/est31/cargo-udeps) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/est31/cargo-udeps/releases) | Linux, macOS, Windows | [Apache-2.0 OR MIT](https://github.com/est31/cargo-udeps/blob/HEAD/LICENSE) |
| [**cargo-valgrind**](https://github.com/jfrimmel/cargo-valgrind) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/jfrimmel/cargo-valgrind/releases) | Linux, macOS, Windows | [MIT](https://github.com/jfrimmel/cargo-valgrind/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/jfrimmel/cargo-valgrind/blob/master/LICENSE-APACHE) |
| [**cross**](https://github.com/cross-rs/cross) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/cross-rs/cross/releases) | Linux, macOS, Windows | [MIT](https://github.com/cross-rs/cross/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/cross-rs/cross/blob/main/LICENSE-APACHE) |
| [**dprint**](https://github.com/dprint/dprint) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/dprint/dprint/releases) | Linux, macOS, Windows | [MIT](https://github.com/dprint/dprint/blob/main/LICENSE) |
| [**editorconfig-checker**](https://github.com/editorconfig-checker/editorconfig-checker) | `/usr/local/bin` | [GitHub Releases](https://github.com/editorconfig-checker/editorconfig-checker/releases) | Linux, macOS, Windows | [MIT](https://github.com/editorconfig-checker/editorconfig-checker/blob/main/LICENSE) |
| [**espup**](https://github.com/esp-rs/espup) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/esp-rs/espup/releases) | Linux, macOS, Windows | [MIT](https://github.com/esp-rs/espup/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/esp-rs/espup/blob/main/LICENSE-APACHE) |
| [**git-cliff**](https://github.com/orhun/git-cliff) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/orhun/git-cliff/releases) | Linux, macOS, Windows | [MIT](https://github.com/orhun/git-cliff/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/orhun/git-cliff/blob/main/LICENSE-APACHE) |
| [**grcov**](https://github.com/mozilla/grcov) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/mozilla/grcov/releases) | Linux, macOS, Windows | [MPL-2.0](https://github.com/mozilla/grcov/blob/HEAD/LICENSE-MPL-2.0) |
| [**hyperfine**](https://github.com/sharkdp/hyperfine) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/sharkdp/hyperfine/releases) | Linux, macOS, Windows | [MIT](https://github.com/sharkdp/hyperfine/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/sharkdp/hyperfine/blob/master/LICENSE-APACHE) |
| [**just**](https://github.com/casey/just) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/casey/just/releases) | Linux, macOS, Windows | [CC0-1.0](https://github.com/casey/just/blob/master/LICENSE) |
| [**mdbook**](https://github.com/rust-lang/mdBook) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rust-lang/mdBook/releases) | Linux, macOS, Windows | [MPL-2.0](https://github.com/rust-lang/mdBook/blob/master/LICENSE) |
| [**mdbook-linkcheck**](https://github.com/Michael-F-Bryan/mdbook-linkcheck) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/Michael-F-Bryan/mdbook-linkcheck/releases) | Linux, macOS, Windows | [MIT](https://github.com/Michael-F-Bryan/mdbook-linkcheck/blob/master/LICENSE) |
| [**nextest**](https://nexte.st/) (alias: `cargo-nextest`)| `$CARGO_HOME/bin` | `cargo-binstall` | Linux, macOS, Windows | [Apache-2.0](https://github.com/nextest-rs/nextest/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/nextest-rs/nextest/blob/HEAD/LICENSE-MIT) |
| [**osv-scanner**](https://github.com/google/osv-scanner) | `/usr/local/bin` | [GitHub Releases](https://github.com/google/osv-scanner/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/google/osv-scanner/blob/main/LICENSE) |
| [**parse-changelog**](https://github.com/taiki-e/parse-changelog) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/taiki-e/parse-changelog/releases) | Linux, macOS, Windows | [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) |
| [**protoc**](https://github.com/protocolbuffers/protobuf) | `/usr/local/bin` | [GitHub Releases](https://github.com/protocolbuffers/protobuf/releases) | Linux, macOS, Windows | [BSD-3-Clause](https://github.com/protocolbuffers/protobuf/blob/HEAD/LICENSE) |
| [**sccache**](https://github.com/mozilla/sccache) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/mozilla/sccache/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/mozilla/sccache/blob/main/LICENSE) |
| [**shellcheck**](https://www.shellcheck.net) | `/usr/local/bin` | [GitHub Releases](https://github.com/koalaman/shellcheck/releases) | Linux, macOS, Windows | [GPL-3.0](https://github.com/koalaman/shellcheck/blob/master/LICENSE) |
| [**shfmt**](https://github.com/mvdan/sh) | `/usr/local/bin` | [GitHub Releases](https://github.com/mvdan/sh/releases) | Linux, macOS, Windows | [BSD-3-Clause](https://github.com/mvdan/sh/blob/master/LICENSE) |
| [**syft**](https://github.com/anchore/syft) | `/usr/local/bin` | [GitHub Releases](https://github.com/anchore/syft/releases) | Linux, macOS, Windows | [Apache-2.0](https://github.com/anchore/syft/blob/main/LICENSE) |
| [**typos**](https://github.com/crate-ci/typos) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/crate-ci/typos/releases) | Linux, macOS, Windows | [MIT](https://github.com/crate-ci/typos/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/crate-ci/typos/blob/master/LICENSE-APACHE) |
| [**valgrind**](https://valgrind.org/) | `/snap/bin` | [snap](https://snapcraft.io/install/valgrind/ubuntu) | Linux | [GPL-2.0](https://sourceware.org/git/?p=valgrind.git;a=blob;f=COPYING;hb=HEAD) |
| [**wasm-bindgen**](https://github.com/rustwasm/wasm-bindgen) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rustwasm/wasm-bindgen/releases) | Linux, macOS, Windows | [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) |
| [**wasm-pack**](https://github.com/rustwasm/wasm-pack) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rustwasm/wasm-pack/releases) | Linux, macOS, Windows | [MIT](https://github.com/rustwasm/wasm-pack/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/rustwasm/wasm-pack/blob/master/LICENSE-APACHE) |
| [**wasmtime**](https://github.com/bytecodealliance/wasmtime) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/bytecodealliance/wasmtime/releases) | Linux, macOS, Windows | [Apache-2.0 WITH LLVM-exception](https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE) |
| [**xbuild**](https://github.com/rust-mobile/xbuild) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/rust-mobile/xbuild/releases) | Linux, macOS, Windows | [Apache-2.0 OR MIT](https://github.com/rust-mobile/xbuild/blob/268939a99a50d7927bce3e343e5d2ed32eb8b30e/xbuild/Cargo.toml#L7) |
| [**zola**](https://github.com/getzola/zola) | `$CARGO_HOME/bin` | [GitHub Releases](https://github.com/getzola/zola/releases) | Linux, macOS, Windows | [MIT](https://github.com/getzola/zola/blob/master/LICENSE) |

1
manifests/biome.json generated
View File

@@ -34,6 +34,7 @@
"bin": "biome.exe"
}
},
"license_markdown": "[Apache-2.0](https://github.com/biomejs/biome/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/biomejs/biome/blob/main/LICENSE-MIT)",
"latest": {
"version": "1.7.3"
},

View File

@@ -18,6 +18,7 @@
"bin": "cargo-audit-aarch64-unknown-linux-gnu-v${version}/cargo-audit"
}
},
"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.20.0"
},

View File

@@ -20,6 +20,7 @@
"url": "https://github.com/cargo-bins/cargo-binstall/releases/download/v${version}/cargo-binstall-aarch64-pc-windows-msvc.zip"
}
},
"license_markdown": "[GPL-3.0](https://github.com/cargo-bins/cargo-binstall/blob/HEAD/crates/bin/LICENSE)",
"latest": {
"version": "1.6.8"
},

View File

@@ -11,6 +11,7 @@
"url": "https://github.com/RalfJung/cargo-careful/releases/download/v${version}/cargo-careful.exe"
}
},
"license_markdown": "[MIT](https://github.com/RalfJung/cargo-careful/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/RalfJung/cargo-careful/blob/master/LICENSE-APACHE)",
"latest": {
"version": "0.4.2"
},

View File

@@ -11,6 +11,7 @@
"url": "https://github.com/CycloneDX/cyclonedx-rust-cargo/releases/download/cargo-cyclonedx-${version}/cargo-cyclonedx-Win-x86_64.zip"
}
},
"license_markdown": "[Apache-2.0](https://github.com/CycloneDX/cyclonedx-rust-cargo/blob/main/LICENSE)",
"latest": {
"version": "0.5.0"
},

View File

@@ -22,6 +22,7 @@
"bin": "cargo-deny-${version}-aarch64-apple-darwin/cargo-deny"
}
},
"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.14.24"
},

View File

@@ -10,6 +10,7 @@
"bin": "cargo-dinghy-${version}/cargo-dinghy"
}
},
"license_markdown": "[MIT](https://github.com/sonos/dinghy/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/sonos/dinghy/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.7.1"
},

View File

@@ -18,6 +18,7 @@
"bin": "cargo-export-v${version}-aarch64-apple-darwin/bin/cargo-export"
}
},
"license_markdown": "[MIT](https://github.com/bazhenov/cargo-export/blob/master/LICENSE)",
"latest": {
"version": "0.2.5"
},

View File

@@ -1,6 +1,7 @@
{
"rust_crate": "cargo-hack",
"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.28"
},

View File

@@ -17,6 +17,7 @@
"url": "https://github.com/taiki-e/cargo-llvm-cov/releases/download/v${version}/cargo-llvm-cov-aarch64-apple-darwin.tar.gz"
}
},
"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.10"
},

View File

@@ -1,6 +1,7 @@
{
"rust_crate": "cargo-machete",
"template": null,
"license_markdown": "[MIT](https://github.com/bnjbvr/cargo-machete/blob/main/LICENSE.md)",
"latest": {
"version": "0.6.2"
},

View File

@@ -18,6 +18,7 @@
"bin": "cargo-make-v${version}-aarch64-apple-darwin/cargo-make"
}
},
"license_markdown": "[Apache-2.0](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE)",
"latest": {
"version": "0.37.12"
},

View File

@@ -20,6 +20,7 @@
"url": "https://github.com/taiki-e/cargo-minimal-versions/releases/download/v${version}/cargo-minimal-versions-aarch64-pc-windows-msvc.tar.gz"
}
},
"license_markdown": "[Apache-2.0](https://github.com/taiki-e/cargo-minimal-versions/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-minimal-versions/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.1.27"
},

View File

@@ -20,6 +20,7 @@
"url": "https://github.com/taiki-e/cargo-no-dev-deps/releases/download/v${version}/cargo-no-dev-deps-aarch64-pc-windows-msvc.tar.gz"
}
},
"license_markdown": "[Apache-2.0](https://github.com/taiki-e/cargo-no-dev-deps/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/taiki-e/cargo-no-dev-deps/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.2.12"
},

View File

@@ -11,6 +11,7 @@
"url": "https://github.com/orium/cargo-rdme/releases/download/v${version}/cargo-rdme_v${version}_x86_64-pc-windows-gnu.zip"
}
},
"license_markdown": "[MPL-2.0](https://github.com/orium/cargo-rdme/blob/main/LICENSE.md)",
"latest": {
"version": "1.4.2"
},

View File

@@ -11,6 +11,7 @@
"url": "https://github.com/DevinR528/cargo-sort/releases/download/v${version}/cargo-sort-x86_64-pc-windows-msvc.zip"
}
},
"license_markdown": "[Apache-2.0 OR MIT](https://github.com/DevinR528/cargo-sort/blob/55ec89082466f6bb246d870a8d56d166a8e1f08b/Cargo.toml#L5)",
"latest": {
"version": "1.0.9"
},

View File

@@ -8,6 +8,7 @@
"url": "https://github.com/drahnr/cargo-spellcheck/releases/download/v${version}/cargo-spellcheck-v${version}-x86_64-pc-windows-gnu.exe"
}
},
"license_markdown": "[LGPLv2.1](https://github.com/drahnr/cargo-spellcheck/blob/master/LICENSE-LGPL)",
"latest": {
"version": "0.14.0"
},

View File

@@ -17,6 +17,7 @@
"url": "https://github.com/xd009642/tarpaulin/releases/download/${version}/cargo-tarpaulin-aarch64-apple-darwin.tar.gz"
}
},
"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.30.0"
},

View File

@@ -30,6 +30,7 @@
"bin": "./cargo-udeps-v${version}-aarch64-pc-windows-msvc/cargo-udeps.exe"
}
},
"license_markdown": "[Apache-2.0 OR MIT](https://github.com/est31/cargo-udeps/blob/HEAD/LICENSE)",
"latest": {
"version": "0.1.47"
},

View File

@@ -11,6 +11,7 @@
"url": "https://github.com/jfrimmel/cargo-valgrind/releases/download/v${version}/cargo-valgrind-${version}-x86_64-pc-windows-msvc.zip"
}
},
"license_markdown": "[MIT](https://github.com/jfrimmel/cargo-valgrind/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/jfrimmel/cargo-valgrind/blob/master/LICENSE-APACHE)",
"latest": {
"version": "2.1.0"
},

1
manifests/cross.json generated
View File

@@ -1,6 +1,7 @@
{
"rust_crate": "cross",
"template": null,
"license_markdown": "[MIT](https://github.com/cross-rs/cross/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/cross-rs/cross/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.2.5"
},

1
manifests/dprint.json generated
View File

@@ -23,6 +23,7 @@
"url": "https://github.com/dprint/dprint/releases/download/${version}/dprint-aarch64-apple-darwin.zip"
}
},
"license_markdown": "[MIT](https://github.com/dprint/dprint/blob/main/LICENSE)",
"latest": {
"version": "0.46.1"
},

View File

@@ -26,6 +26,7 @@
"bin": "bin/ec-windows-arm64.exe"
}
},
"license_markdown": "[MIT](https://github.com/editorconfig-checker/editorconfig-checker/blob/main/LICENSE)",
"latest": {
"version": "3.0.1"
},

1
manifests/espup.json generated
View File

@@ -17,6 +17,7 @@
"url": "https://github.com/esp-rs/espup/releases/download/v${version}/espup-aarch64-apple-darwin.zip"
}
},
"license_markdown": "[MIT](https://github.com/esp-rs/espup/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/esp-rs/espup/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.11.0"
},

View File

@@ -26,6 +26,7 @@
"bin": "git-cliff-${version}/git-cliff.exe"
}
},
"license_markdown": "[MIT](https://github.com/orhun/git-cliff/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/orhun/git-cliff/blob/main/LICENSE-APACHE)",
"latest": {
"version": "2.3.0"
},

1
manifests/grcov.json generated
View File

@@ -17,6 +17,7 @@
"url": "https://github.com/mozilla/grcov/releases/download/v${version}/grcov-aarch64-apple-darwin.tar.bz2"
}
},
"license_markdown": "[MPL-2.0](https://github.com/mozilla/grcov/blob/HEAD/LICENSE-MPL-2.0)",
"latest": {
"version": "0.8.19"
},

View File

@@ -18,6 +18,7 @@
"bin": "hyperfine-v${version}-aarch64-unknown-linux-gnu/hyperfine"
}
},
"license_markdown": "[MIT](https://github.com/sharkdp/hyperfine/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/sharkdp/hyperfine/blob/master/LICENSE-APACHE)",
"latest": {
"version": "1.18.0"
},

1
manifests/just.json generated
View File

@@ -17,6 +17,7 @@
"url": "https://github.com/casey/just/releases/download/${version}/just-${version}-aarch64-apple-darwin.tar.gz"
}
},
"license_markdown": "[CC0-1.0](https://github.com/casey/just/blob/master/LICENSE)",
"latest": {
"version": "1.27.0"
},

View File

@@ -11,6 +11,7 @@
"url": "https://github.com/Michael-F-Bryan/mdbook-linkcheck/releases/download/v${version}/mdbook-linkcheck.x86_64-pc-windows-msvc.zip"
}
},
"license_markdown": "[MIT](https://github.com/Michael-F-Bryan/mdbook-linkcheck/blob/master/LICENSE)",
"latest": {
"version": "0.7.7"
},

1
manifests/mdbook.json generated
View File

@@ -17,6 +17,7 @@
"url": "https://github.com/rust-lang/mdBook/releases/download/v${version}/mdbook-v${version}-aarch64-unknown-linux-musl.tar.gz"
}
},
"license_markdown": "[MPL-2.0](https://github.com/rust-lang/mdBook/blob/master/LICENSE)",
"latest": {
"version": "0.4.40"
},

View File

@@ -20,6 +20,7 @@
"url": "https://github.com/google/osv-scanner/releases/download/v${version}/osv-scanner_${version}_windows_arm64.exe"
}
},
"license_markdown": "[Apache-2.0](https://github.com/google/osv-scanner/blob/main/LICENSE)",
"latest": {
"version": "1.6.2"
},

View File

@@ -1,6 +1,7 @@
{
"rust_crate": "parse-changelog",
"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.8"
},

25
manifests/protoc.json generated
View File

@@ -1,6 +1,7 @@
{
"rust_crate": null,
"template": null,
"license_markdown": "[BSD-3-Clause](https://github.com/protocolbuffers/protobuf/blob/HEAD/LICENSE)",
"latest": {
"version": "3.27.0"
},
@@ -397,7 +398,29 @@
}
},
"3.22": {
"version": "3.22.4"
"version": "3.22.5"
},
"3.22.5": {
"x86_64_linux_gnu": {
"url": "https://github.com/protocolbuffers/protobuf/releases/download/v22.5/protoc-22.5-linux-x86_64.zip",
"checksum": "c11692013bbffb7c257de7f82cd02d323700ebcdb8a4923ed02fea812f70f5e3"
},
"x86_64_macos": {
"url": "https://github.com/protocolbuffers/protobuf/releases/download/v22.5/protoc-22.5-osx-x86_64.zip",
"checksum": "3edd0c65e2a8efc83f24918db27e1bbc72f3abe7618cb4cfb1842630a830b562"
},
"x86_64_windows": {
"url": "https://github.com/protocolbuffers/protobuf/releases/download/v22.5/protoc-22.5-win64.zip",
"checksum": "f99d1e9e28f7704b22d4254fab293477ea0d4ef3e5b9aa940a8fccfc99c1ce4c"
},
"aarch64_linux_gnu": {
"url": "https://github.com/protocolbuffers/protobuf/releases/download/v22.5/protoc-22.5-linux-aarch_64.zip",
"checksum": "1890f845b333fe040ec002a659a4ff7515cd93f8db0066c3885d1fce9f70b208"
},
"aarch64_macos": {
"url": "https://github.com/protocolbuffers/protobuf/releases/download/v22.5/protoc-22.5-osx-aarch_64.zip",
"checksum": "b7fc6c6099ad10149d90f8b107871537ca030980354b402d8e034055ce082b77"
}
},
"3.22.4": {
"x86_64_linux_gnu": {

View File

@@ -22,6 +22,7 @@
"bin": "sccache-v${version}-aarch64-apple-darwin/sccache"
}
},
"license_markdown": "[Apache-2.0](https://github.com/mozilla/sccache/blob/main/LICENSE)",
"latest": {
"version": "0.8.1"
},

View File

@@ -18,6 +18,7 @@
"bin": "shellcheck-v${version}/shellcheck"
}
},
"license_markdown": "[GPL-3.0](https://github.com/koalaman/shellcheck/blob/master/LICENSE)",
"latest": {
"version": "0.10.0"
},

1
manifests/shfmt.json generated
View File

@@ -17,6 +17,7 @@
"url": "https://github.com/mvdan/sh/releases/download/v${version}/shfmt_v${version}_darwin_arm64"
}
},
"license_markdown": "[BSD-3-Clause](https://github.com/mvdan/sh/blob/master/LICENSE)",
"latest": {
"version": "3.8.0"
},

1
manifests/syft.json generated
View File

@@ -22,6 +22,7 @@
"bin": "syft"
}
},
"license_markdown": "[Apache-2.0](https://github.com/anchore/syft/blob/main/LICENSE)",
"latest": {
"version": "1.5.0"
},

1
manifests/typos.json generated
View File

@@ -14,6 +14,7 @@
"url": "https://github.com/crate-ci/typos/releases/download/v${version}/typos-v${version}-aarch64-apple-darwin.tar.gz"
}
},
"license_markdown": "[MIT](https://github.com/crate-ci/typos/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/crate-ci/typos/blob/master/LICENSE-APACHE)",
"latest": {
"version": "1.22.0"
},

View File

@@ -42,6 +42,7 @@
]
}
},
"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.92"
},

View File

@@ -18,6 +18,7 @@
"bin": "wasm-pack-v${version}-aarch64-unknown-linux-musl/wasm-pack"
}
},
"license_markdown": "[MIT](https://github.com/rustwasm/wasm-pack/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/rustwasm/wasm-pack/blob/master/LICENSE-APACHE)",
"latest": {
"version": "0.12.1"
},

View File

@@ -22,6 +22,7 @@
"bin": "wasmtime-v${version}-aarch64-macos/wasmtime"
}
},
"license_markdown": "[Apache-2.0 WITH LLVM-exception](https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE)",
"latest": {
"version": "21.0.1"
},

1
manifests/xbuild.json generated
View File

@@ -14,6 +14,7 @@
"bin": "xbuild-windows-x64.exe"
}
},
"license_markdown": "[Apache-2.0 OR MIT](https://github.com/rust-mobile/xbuild/blob/268939a99a50d7927bce3e343e5d2ed32eb8b30e/xbuild/Cargo.toml#L7)",
"latest": {
"version": "0.2.0"
},

1
manifests/zola.json generated
View File

@@ -14,6 +14,7 @@
"url": "https://github.com/getzola/zola/releases/download/v${version}/zola-v${version}-aarch64-apple-darwin.tar.gz"
}
},
"license_markdown": "[MIT](https://github.com/getzola/zola/blob/master/LICENSE)",
"latest": {
"version": "0.18.0"
},

View File

@@ -1,6 +1,7 @@
[package]
name = "install-action-internal-codegen"
edition = "2021"
default-run = "generate-manifest"
[dependencies]
anyhow = "1"
@@ -12,6 +13,7 @@ serde = "1"
serde_derive = "1"
serde_json = "1"
sha2 = "0.10"
spdx = "0.10"
tar = "0.4"
toml_edit = { version = "0.22", default-features = false, features = ["parse", "serde"] }
# TODO: call curl command instead of using ureq?
@@ -19,3 +21,15 @@ ureq = { version = "2", features = ["json"] }
[lints]
workspace = true
[[bin]]
bench = false
name = "generate-manifest"
path = "src/main.rs"
test = false
[[bin]]
bench = false
name = "generate-tools-markdown"
path = "src/tools-markdown.rs"
test = false

View File

@@ -1,5 +1,7 @@
{
"repository": "https://github.com/biomejs/biome",
"website": "https://biomejs.dev",
"license_markdown": "[Apache-2.0](https://github.com/biomejs/biome/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/biomejs/biome/blob/main/LICENSE-MIT)",
"tag_prefix": "cli/v",
"bin": "${package}${exe}",
"platform": {

View File

@@ -1,5 +1,7 @@
{
"repository": "https://github.com/rustsec/rustsec",
"website": "https://github.com/rustsec/rustsec/tree/HEAD/cargo-audit",
"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)",
"tag_prefix": "cargo-audit/v",
"rust_crate": "${package}",
"asset_name": "${package}-${rust_target}-v${version}.tgz",

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/cargo-bins/cargo-binstall",
"license_markdown": "[GPL-3.0](https://github.com/cargo-bins/cargo-binstall/blob/HEAD/crates/bin/LICENSE)",
"tag_prefix": "v",
"rust_crate": "${package}",
"asset_name": "${package}-${rust_target}.zip",

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/DevinR528/cargo-sort",
"license_markdown": "[Apache-2.0 OR MIT](https://github.com/DevinR528/cargo-sort/blob/55ec89082466f6bb246d870a8d56d166a8e1f08b/Cargo.toml#L5)",
"tag_prefix": "v",
"rust_crate": "${package}",
"asset_name": "${package}-${rust_target}.tar.gz",

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/drahnr/cargo-spellcheck",
"license_markdown": "[LGPLv2.1](https://github.com/drahnr/cargo-spellcheck/blob/master/LICENSE-LGPL)",
"tag_prefix": "v",
"rust_crate": "${package}",
"asset_name": "${package}-v${version}-${rust_target}",

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/est31/cargo-udeps",
"license_markdown": "[Apache-2.0 OR MIT](https://github.com/est31/cargo-udeps/blob/HEAD/LICENSE)",
"tag_prefix": "v",
"rust_crate": "${package}",
"asset_name": "${package}-v${version}-${rust_target}.tar.gz",

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/mozilla/grcov",
"license_markdown": "[MPL-2.0](https://github.com/mozilla/grcov/blob/HEAD/LICENSE-MPL-2.0)",
"tag_prefix": "v",
"rust_crate": "${package}",
"asset_name": "${package}-${rust_target}.tar.bz2",

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/protocolbuffers/protobuf",
"license_markdown": "[BSD-3-Clause](https://github.com/protocolbuffers/protobuf/blob/HEAD/LICENSE)",
"tag_prefix": "v",
"default_major_version": "3",
"platform": {

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/koalaman/shellcheck",
"website": "https://www.shellcheck.net",
"tag_prefix": "v",
"bin": "${package}-v${version}/${package}${exe}",
"platform": {

View File

@@ -1,5 +1,6 @@
{
"repository": "https://github.com/rust-mobile/xbuild",
"license_markdown": "[Apache-2.0 OR MIT](https://github.com/rust-mobile/xbuild/blob/268939a99a50d7927bce3e343e5d2ed32eb8b30e/xbuild/Cargo.toml#L7)",
"tag_prefix": "v",
"rust_crate": "${package}",
"asset_name": "${package}-${rust_target_os}-x64${exe}",

379
tools/codegen/src/lib.rs Normal file
View File

@@ -0,0 +1,379 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::{
cmp::{self, Reverse},
collections::BTreeMap,
env, fmt,
path::{Path, PathBuf},
slice,
str::FromStr,
};
use anyhow::Result;
use serde::{
de::{self, Deserialize, Deserializer},
ser::{Serialize, Serializer},
};
use serde_derive::{Deserialize, Serialize};
#[must_use]
pub fn workspace_root() -> PathBuf {
let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
dir.pop(); // codegen
dir.pop(); // tools
dir
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Version {
pub major: Option<u64>,
pub minor: Option<u64>,
pub patch: Option<u64>,
pub pre: semver::Prerelease,
pub build: semver::BuildMetadata,
}
impl Version {
#[must_use]
pub fn omitted(major: u64, minor: Option<u64>) -> Self {
Self {
major: Some(major),
minor,
patch: None,
pre: semver::Prerelease::default(),
build: semver::BuildMetadata::default(),
}
}
#[must_use]
pub fn latest() -> Self {
Self {
major: None,
minor: None,
patch: None,
pre: semver::Prerelease::default(),
build: semver::BuildMetadata::default(),
}
}
#[must_use]
pub fn to_semver(&self) -> Option<semver::Version> {
Some(semver::Version {
major: self.major?,
minor: self.minor?,
patch: self.patch?,
pre: self.pre.clone(),
build: self.build.clone(),
})
}
}
impl From<semver::Version> for Version {
fn from(v: semver::Version) -> Self {
Self {
major: Some(v.major),
minor: Some(v.minor),
patch: Some(v.patch),
pre: v.pre,
build: v.build,
}
}
}
impl PartialOrd for Version {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Version {
fn cmp(&self, other: &Self) -> cmp::Ordering {
pub(crate) fn convert(v: &Version) -> semver::Version {
semver::Version {
major: v.major.unwrap_or(u64::MAX),
minor: v.minor.unwrap_or(u64::MAX),
patch: v.patch.unwrap_or(u64::MAX),
pre: v.pre.clone(),
build: v.build.clone(),
}
}
convert(self).cmp(&convert(other))
}
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Some(major) = self.major else {
f.write_str("latest")?;
return Ok(());
};
f.write_str(&major.to_string())?;
let Some(minor) = self.minor else {
return Ok(());
};
f.write_str(".")?;
f.write_str(&minor.to_string())?;
let Some(patch) = self.patch else {
return Ok(());
};
f.write_str(".")?;
f.write_str(&patch.to_string())?;
if !self.pre.is_empty() {
f.write_str("-")?;
f.write_str(&self.pre)?;
}
if !self.build.is_empty() {
f.write_str("+")?;
f.write_str(&self.build)?;
}
Ok(())
}
}
impl FromStr for Version {
type Err = semver::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "latest" {
return Ok(Self::latest());
}
match s.parse::<semver::Version>() {
Ok(v) => Ok(v.into()),
Err(e) => match s.parse::<semver::Comparator>() {
Ok(v) => Ok(Self {
major: Some(v.major),
minor: v.minor,
patch: v.patch,
pre: semver::Prerelease::default(),
build: semver::BuildMetadata::default(),
}),
Err(_e) => Err(e),
},
}
}
}
impl Serialize for Version {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
String::serialize(&self.to_string(), serializer)
}
}
impl<'de> Deserialize<'de> for Version {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
String::deserialize(deserializer)?.parse().map_err(de::Error::custom)
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Manifests {
pub rust_crate: Option<String>,
pub template: Option<ManifestTemplate>,
/// Markdown for the licenses.
pub license_markdown: String,
#[serde(flatten)]
pub map: BTreeMap<Reverse<Version>, ManifestRef>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ManifestRef {
Ref { version: Version },
Real(Manifest),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Manifest {
#[serde(flatten)]
pub download_info: BTreeMap<HostPlatform, ManifestDownloadInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestDownloadInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
pub checksum: String,
/// Path to binaries in archive. Default to `${tool}${exe}`.
#[serde(skip_serializing_if = "Option::is_none")]
pub bin: Option<StringOrArray>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestTemplate {
#[serde(flatten)]
pub download_info: BTreeMap<HostPlatform, ManifestTemplateDownloadInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestTemplateDownloadInfo {
pub url: String,
/// Path to binaries in archive. Default to `${tool}${exe}`.
#[serde(skip_serializing_if = "Option::is_none")]
pub bin: Option<StringOrArray>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BaseManifest {
/// Link to the GitHub repository.
pub repository: String,
/// Alternative link for the project. Automatically detected if possible.
pub website: Option<String>,
/// Markdown syntax for links to licenses. Automatically detected if possible.
pub license_markdown: Option<String>,
/// Prefix of release tag.
pub tag_prefix: String,
/// Crate name, if this is Rust crate.
pub rust_crate: Option<String>,
pub default_major_version: Option<String>,
/// Asset name patterns.
pub asset_name: Option<StringOrArray>,
/// Path to binaries in archive. Default to `${tool}${exe}`.
pub bin: Option<StringOrArray>,
pub signing: Option<Signing>,
#[serde(default)]
pub broken: Vec<semver::Version>,
pub platform: BTreeMap<HostPlatform, BaseManifestPlatformInfo>,
pub version_range: Option<String>,
}
impl BaseManifest {
/// Validate the manifest.
// The panic is an assert
#[allow(clippy::missing_panics_doc)]
pub fn validate(&self) {
for bin in self.bin.iter().chain(self.platform.values().flat_map(|m| &m.bin)) {
assert!(!bin.as_slice().is_empty());
for bin in bin.as_slice() {
let file_name = Path::new(bin).file_name().unwrap().to_str().unwrap();
if !self.repository.ends_with("/xbuild") {
assert!(
!(file_name.contains("${version") || file_name.contains("${rust")),
"{bin}"
);
}
}
}
}
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Signing {
pub kind: SigningKind,
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
#[serde(deny_unknown_fields)]
pub enum SigningKind {
/// algorithm: minisign
/// public key: package.metadata.binstall.signing.pubkey at Cargo.toml
/// <https://github.com/cargo-bins/cargo-binstall/blob/HEAD/SIGNING.md>
MinisignBinstall,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BaseManifestPlatformInfo {
/// Asset name patterns. Default to the value at `BaseManifest::asset_name`.
pub asset_name: Option<StringOrArray>,
/// Path to binaries in archive. Default to the value at `BaseManifest::bin`.
pub bin: Option<StringOrArray>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum StringOrArray {
String(String),
Array(Vec<String>),
}
impl StringOrArray {
#[must_use]
pub fn as_slice(&self) -> &[String] {
match self {
Self::String(s) => slice::from_ref(s),
Self::Array(v) => v,
}
}
#[must_use]
pub fn map(&self, mut f: impl FnMut(&String) -> String) -> Self {
match self {
Self::String(s) => Self::String(f(s)),
Self::Array(v) => Self::Array(v.iter().map(f).collect()),
}
}
}
/// GitHub Actions Runner supports Linux (x86_64, aarch64, arm), Windows (x86_64, aarch64),
/// and macOS (x86_64, aarch64).
/// https://github.com/actions/runner/blob/v2.315.0/.github/workflows/build.yml#L21
/// https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners#supported-architectures-and-operating-systems-for-self-hosted-runners
///
/// Note:
/// - Static-linked binaries compiled for linux-musl will also work on linux-gnu systems and are
/// usually preferred over linux-gnu binaries because they can avoid glibc version issues.
/// (rustc enables statically linking for linux-musl by default, except for mips.)
/// - Binaries compiled for x86_64 macOS will usually also work on aarch64 macOS.
/// - Binaries compiled for x86_64 Windows will usually also work on aarch64 Windows 11+.
/// - Ignore arm for now, as we need to consider the version and whether hard-float is supported.
/// https://github.com/rust-lang/rustup/pull/593
/// https://github.com/cross-rs/cross/pull/1018
/// Does it seem only armv7l+ is supported?
/// https://github.com/actions/runner/blob/v2.315.0/src/Misc/externals.sh#L189
/// https://github.com/actions/runner/issues/688
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum HostPlatform {
x86_64_linux_gnu,
x86_64_linux_musl,
x86_64_macos,
x86_64_windows,
aarch64_linux_gnu,
aarch64_linux_musl,
aarch64_macos,
aarch64_windows,
}
impl HostPlatform {
#[must_use]
pub fn rust_target(self) -> &'static str {
match self {
Self::x86_64_linux_gnu => "x86_64-unknown-linux-gnu",
Self::x86_64_linux_musl => "x86_64-unknown-linux-musl",
Self::x86_64_macos => "x86_64-apple-darwin",
Self::x86_64_windows => "x86_64-pc-windows-msvc",
Self::aarch64_linux_gnu => "aarch64-unknown-linux-gnu",
Self::aarch64_linux_musl => "aarch64-unknown-linux-musl",
Self::aarch64_macos => "aarch64-apple-darwin",
Self::aarch64_windows => "aarch64-pc-windows-msvc",
}
}
#[must_use]
pub fn rust_target_arch(self) -> &'static str {
match self {
Self::aarch64_linux_gnu
| Self::aarch64_linux_musl
| Self::aarch64_macos
| Self::aarch64_windows => "aarch64",
Self::x86_64_linux_gnu
| Self::x86_64_linux_musl
| Self::x86_64_macos
| Self::x86_64_windows => "x86_64",
}
}
#[must_use]
pub fn rust_target_os(self) -> &'static str {
match self {
Self::aarch64_linux_gnu
| Self::aarch64_linux_musl
| Self::x86_64_linux_gnu
| Self::x86_64_linux_musl => "linux",
Self::aarch64_macos | Self::x86_64_macos => "macos",
Self::aarch64_windows | Self::x86_64_windows => "windows",
}
}
#[must_use]
pub fn exe_suffix(self) -> &'static str {
match self {
Self::x86_64_windows | Self::aarch64_windows => ".exe",
_ => "",
}
}
}

View File

@@ -1,26 +1,23 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::{
cmp::{self, Reverse},
cmp::Reverse,
collections::{BTreeMap, BTreeSet},
env,
ffi::OsStr,
fmt,
io::Read,
path::{Path, PathBuf},
slice,
str::FromStr,
path::Path,
time::Duration,
};
use anyhow::{bail, Context as _, Result};
use fs_err as fs;
use serde::{
de::{self, Deserialize, Deserializer},
ser::{Serialize, Serializer},
use install_action_internal_codegen::{
workspace_root, BaseManifest, HostPlatform, Manifest, ManifestDownloadInfo, ManifestRef,
ManifestTemplate, ManifestTemplateDownloadInfo, Manifests, Signing, SigningKind, Version,
};
use serde_derive::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use spdx::expression::{ExprNode, ExpressionReq, Operator};
fn main() -> Result<()> {
let args: Vec<_> = env::args().skip(1).collect();
@@ -46,7 +43,12 @@ fn main() -> Result<()> {
let repo = base_info
.repository
.strip_prefix("https://github.com/")
.context("repository must be starts with https://github.com/")?;
.context("repository must start with https://github.com/")?;
eprintln!("downloading metadata from https://github.com/{repo}");
let repo_info: github::RepoMetadata =
download_github(&format!("https://api.github.com/repos/{repo}"))?.into_json()?;
eprintln!("downloading releases of https://github.com/{repo} from https://api.github.com/repos/{repo}/releases");
let mut releases: github::Releases = vec![];
@@ -82,6 +84,7 @@ fn main() -> Result<()> {
.collect();
let mut crates_io_info = None;
let mut crates_io_version_detail = None;
base_info.rust_crate = base_info
.rust_crate
.as_ref()
@@ -89,10 +92,29 @@ fn main() -> Result<()> {
.transpose()?;
if let Some(crate_name) = &base_info.rust_crate {
eprintln!("downloading crate info from https://crates.io/api/v1/crates/{crate_name}");
crates_io_info = Some(
download(&format!("https://crates.io/api/v1/crates/{crate_name}"))?
.into_json::<crates_io::Crate>()?,
let info = download(&format!("https://crates.io/api/v1/crates/{crate_name}"))?
.into_json::<crates_io::Crate>()?;
let latest_version = &info.versions[0].num;
crates_io_version_detail = Some(
download(&format!("https://crates.io/api/v1/crates/{crate_name}/{latest_version}"))?
.into_json::<crates_io::VersionMetadata>()?
.version,
);
if let Some(crate_repository) = info.crate_.repository.clone() {
// cargo-dinghy is fixed at https://github.com/sonos/dinghy/pull/231, but not yet released
if crate_name != "cargo-dinghy"
&& !crate_repository
.to_lowercase()
.starts_with(&base_info.repository.to_lowercase())
{
panic!("repository {crate_repository} from crates.io differs from base manifest");
}
} else if crate_name != "zola" {
panic!("crate metadata does not include a repository");
}
crates_io_info = Some(info);
}
let mut manifests: Manifests = Manifests::default();
@@ -130,6 +152,44 @@ fn main() -> Result<()> {
Err(e) => eprintln!("failed to load old manifest: {e}"),
}
}
// Check website
if let Some(website) = base_info.website {
if website.is_empty() || website == base_info.repository {
panic!("Please do not put the repository in website, or set website to an empty value");
}
}
// Populate license_markdown
if let Some(license_markdown) = base_info.license_markdown {
if license_markdown.is_empty() {
panic!("license_markdown can not be an empty value");
}
manifests.license_markdown = license_markdown;
} else if let Some(detail) = crates_io_version_detail {
if let Some(license) = detail.license {
eprintln!("Trying to using license '{license}' from crates.io ...");
if let Some(license_markdown) =
get_license_markdown(&license, &repo.to_string(), &repo_info.default_branch)
{
manifests.license_markdown = license_markdown;
}
}
} else if let Some(license) = repo_info.license {
if let Some(license) = license.spdx_id {
eprintln!("Trying to using license '{license}' from github.com ...");
if let Some(license_markdown) =
get_license_markdown(&license, &repo.to_string(), &repo_info.default_branch)
{
manifests.license_markdown = license_markdown;
}
}
}
if manifests.license_markdown.is_empty() {
panic!("Unable to determine license_markdown; set manually")
}
let version_req: Option<semver::VersionReq> = match args.get(1) {
_ if latest_only => {
let req = format!("={}", releases.first_key_value().unwrap().0 .0).parse()?;
@@ -488,13 +548,6 @@ fn main() -> Result<()> {
Ok(())
}
fn workspace_root() -> PathBuf {
let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
dir.pop(); // codegen
dir.pop(); // tools
dir
}
fn replace_vars(
s: &str,
package: &str,
@@ -561,6 +614,35 @@ fn download_github(url: &str) -> Result<ureq::Response> {
Err(last_error.unwrap().into())
}
#[allow(clippy::missing_panics_doc)]
pub fn github_head(url: &str) -> Result<()> {
eprintln!("fetching head of {url} ..");
let mut token = env::var("GITHUB_TOKEN").ok().filter(|v| !v.is_empty());
let mut retry = 0;
let max_retry = 2;
let mut last_error;
loop {
let mut req = ureq::head(url);
if let Some(token) = &token {
req = req.set("Authorization", token);
}
match req.call() {
Ok(_) => return Ok(()),
Err(e) => last_error = Some(e),
}
if retry == max_retry / 2 && token.is_some() {
token = None;
}
retry += 1;
if retry > max_retry {
break;
}
eprintln!("head of {url} failed; retrying after {}s ({retry}/{max_retry})", retry * 2);
std::thread::sleep(Duration::from_secs(retry * 2));
}
Err(last_error.unwrap().into())
}
/// Download without using GITHUB_TOKEN.
#[allow(clippy::missing_panics_doc)]
pub fn download(url: &str) -> Result<ureq::Response> {
@@ -583,345 +665,129 @@ pub fn download(url: &str) -> Result<ureq::Response> {
Err(last_error.unwrap().into())
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct Version {
major: Option<u64>,
minor: Option<u64>,
patch: Option<u64>,
pre: semver::Prerelease,
build: semver::BuildMetadata,
#[must_use]
fn create_github_raw_link(repository: &String, branch: &String, filename: &String) -> String {
format!("https://raw.githubusercontent.com/{repository}/{branch}/{filename}")
}
impl Version {
fn omitted(major: u64, minor: Option<u64>) -> Self {
Self {
major: Some(major),
minor,
patch: None,
pre: semver::Prerelease::default(),
build: semver::BuildMetadata::default(),
#[must_use]
fn create_github_link(repository: &String, branch: &String, filename: &String) -> String {
format!("https://github.com/{repository}/blob/{branch}/{filename}")
}
#[must_use]
fn get_license_markdown(spdx_expr: &str, repo: &String, default_branch: &String) -> Option<String> {
// TODO: use https://docs.rs/spdx/latest/spdx/expression/struct.Expression.html#method.canonicalize ?
let expr = spdx::Expression::parse_mode(spdx_expr, spdx::ParseMode::LAX).unwrap();
let mut op = None;
let mut license_ids: Vec<(&spdx::LicenseId, Option<&spdx::ExceptionId>)> = vec![];
for node in expr.iter() {
match node {
ExprNode::Req(ExpressionReq {
req:
spdx::LicenseReq {
license: spdx::LicenseItem::Spdx { id, or_later },
exception,
..
},
..
}) => {
if *or_later {
panic!("need to handle or_later");
}
if let Some(exception_id) = exception {
license_ids.push((id, Some(exception_id)));
} else {
license_ids.push((id, None));
}
}
ExprNode::Op(current_op) => {
if op.is_some() && op != Some(current_op) {
panic!("SPDX too complex");
}
op = Some(current_op);
}
ExprNode::Req(_) => {}
}
}
fn latest() -> Self {
Self {
major: None,
minor: None,
patch: None,
pre: semver::Prerelease::default(),
build: semver::BuildMetadata::default(),
}
}
fn to_semver(&self) -> Option<semver::Version> {
Some(semver::Version {
major: self.major?,
minor: self.minor?,
patch: self.patch?,
pre: self.pre.clone(),
build: self.build.clone(),
})
}
}
impl From<semver::Version> for Version {
fn from(v: semver::Version) -> Self {
Self {
major: Some(v.major),
minor: Some(v.minor),
patch: Some(v.patch),
pre: v.pre,
build: v.build,
}
}
}
impl PartialOrd for Version {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Version {
fn cmp(&self, other: &Self) -> cmp::Ordering {
fn convert(v: &Version) -> semver::Version {
semver::Version {
major: v.major.unwrap_or(u64::MAX),
minor: v.minor.unwrap_or(u64::MAX),
patch: v.patch.unwrap_or(u64::MAX),
pre: v.pre.clone(),
build: v.build.clone(),
match license_ids.len() {
0 => panic!("No licenses"),
1 => {
let (license_id, exception_id) = license_ids.first().unwrap();
let license_name = if let Some(exception_id) = exception_id {
format!("{} WITH {}", license_id.name, exception_id.name)
} else {
license_id.name.to_string()
};
let name = license_id.name.split('-').next().unwrap().to_ascii_uppercase();
for filename in
["LICENSE".to_string(), format!("LICENSE-{name}"), "LICENSE.md".to_string()]
{
let url = create_github_raw_link(repo, default_branch, &filename);
if github_head(&url).is_ok() {
let url = create_github_link(repo, default_branch, &filename);
return Some(format!("[{license_name}]({url})"));
}
}
}
convert(self).cmp(&convert(other))
}
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Some(major) = self.major else {
f.write_str("latest")?;
return Ok(());
};
f.write_str(&major.to_string())?;
let Some(minor) = self.minor else {
return Ok(());
};
f.write_str(".")?;
f.write_str(&minor.to_string())?;
let Some(patch) = self.patch else {
return Ok(());
};
f.write_str(".")?;
f.write_str(&patch.to_string())?;
if !self.pre.is_empty() {
f.write_str("-")?;
f.write_str(&self.pre)?;
}
if !self.build.is_empty() {
f.write_str("+")?;
f.write_str(&self.build)?;
}
Ok(())
}
}
impl FromStr for Version {
type Err = semver::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "latest" {
return Ok(Self::latest());
}
match s.parse::<semver::Version>() {
Ok(v) => Ok(v.into()),
Err(e) => match s.parse::<semver::Comparator>() {
Ok(v) => Ok(Self {
major: Some(v.major),
minor: v.minor,
patch: v.patch,
pre: semver::Prerelease::default(),
build: semver::BuildMetadata::default(),
}),
Err(_e) => Err(e),
},
}
}
}
impl Serialize for Version {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
String::serialize(&self.to_string(), serializer)
}
}
impl<'de> Deserialize<'de> for Version {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
String::deserialize(deserializer)?.parse().map_err(de::Error::custom)
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
struct Manifests {
rust_crate: Option<String>,
template: Option<ManifestTemplate>,
#[serde(flatten)]
map: BTreeMap<Reverse<Version>, ManifestRef>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
enum ManifestRef {
Ref { version: Version },
Real(Manifest),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Manifest {
#[serde(flatten)]
download_info: BTreeMap<HostPlatform, ManifestDownloadInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ManifestDownloadInfo {
#[serde(skip_serializing_if = "Option::is_none")]
url: Option<String>,
checksum: String,
/// Path to binaries in archive. Default to `${tool}${exe}`.
#[serde(skip_serializing_if = "Option::is_none")]
bin: Option<StringOrArray>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ManifestTemplate {
#[serde(flatten)]
download_info: BTreeMap<HostPlatform, ManifestTemplateDownloadInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ManifestTemplateDownloadInfo {
url: String,
/// Path to binaries in archive. Default to `${tool}${exe}`.
#[serde(skip_serializing_if = "Option::is_none")]
bin: Option<StringOrArray>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct BaseManifest {
/// Link to the GitHub repository.
repository: String,
/// Prefix of release tag.
tag_prefix: String,
/// Crate name, if this is Rust crate.
rust_crate: Option<String>,
default_major_version: Option<String>,
/// Asset name patterns.
asset_name: Option<StringOrArray>,
/// Path to binaries in archive. Default to `${tool}${exe}`.
bin: Option<StringOrArray>,
signing: Option<Signing>,
#[serde(default)]
broken: Vec<semver::Version>,
platform: BTreeMap<HostPlatform, BaseManifestPlatformInfo>,
version_range: Option<String>,
}
impl BaseManifest {
fn validate(&self) {
for bin in self.bin.iter().chain(self.platform.values().flat_map(|m| &m.bin)) {
assert!(!bin.as_slice().is_empty());
for bin in bin.as_slice() {
let file_name = Path::new(bin).file_name().unwrap().to_str().unwrap();
if !self.repository.ends_with("/xbuild") {
assert!(
!(file_name.contains("${version") || file_name.contains("${rust")),
"{bin}"
);
len => {
let mut license_markdowns: Vec<String> = vec![];
for (license_id, exception_id) in &license_ids {
let name = license_id.name.split('-').next().unwrap().to_ascii_uppercase();
let filename = format!("LICENSE-{name}");
let url = create_github_raw_link(repo, default_branch, &filename);
let license_name = if let Some(exception_id) = exception_id {
format!("{} WITH {}", license_id.name, exception_id.name)
} else {
license_id.name.to_string()
};
if github_head(&url).is_ok() {
let url = create_github_link(repo, default_branch, &filename);
license_markdowns.push(format!("[{license_name}]({url})"));
}
}
if license_markdowns.is_empty() {
panic!("Unable to find any license files in the repo for licenses {license_ids:?}");
}
if license_markdowns.len() != len {
panic!("Unable to find license files in the repo for all licenses {license_ids:?}; found {license_markdowns:?}");
}
match op {
None => panic!("op expected"),
Some(Operator::Or) => {
return Some(license_markdowns.join(" OR "));
}
Some(Operator::And) => {
return Some(license_markdowns.join(" AND "));
}
}
}
}
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct Signing {
kind: SigningKind,
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
#[serde(deny_unknown_fields)]
enum SigningKind {
/// algorithm: minisign
/// public key: package.metadata.binstall.signing.pubkey at Cargo.toml
/// <https://github.com/cargo-bins/cargo-binstall/blob/HEAD/SIGNING.md>
MinisignBinstall,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct BaseManifestPlatformInfo {
/// Asset name patterns. Default to the value at `BaseManifest::asset_name`.
asset_name: Option<StringOrArray>,
/// Path to binaries in archive. Default to the value at `BaseManifest::bin`.
bin: Option<StringOrArray>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum StringOrArray {
String(String),
Array(Vec<String>),
}
impl StringOrArray {
fn as_slice(&self) -> &[String] {
match self {
Self::String(s) => slice::from_ref(s),
Self::Array(v) => v,
}
}
fn map(&self, mut f: impl FnMut(&String) -> String) -> Self {
match self {
Self::String(s) => Self::String(f(s)),
Self::Array(v) => Self::Array(v.iter().map(f).collect()),
}
}
}
/// GitHub Actions Runner supports Linux (x86_64, aarch64, arm), Windows (x86_64, aarch64),
/// and macOS (x86_64, aarch64).
/// https://github.com/actions/runner/blob/v2.315.0/.github/workflows/build.yml#L21
/// https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners#supported-architectures-and-operating-systems-for-self-hosted-runners
///
/// Note:
/// - Static-linked binaries compiled for linux-musl will also work on linux-gnu systems and are
/// usually preferred over linux-gnu binaries because they can avoid glibc version issues.
/// (rustc enables statically linking for linux-musl by default, except for mips.)
/// - Binaries compiled for x86_64 macOS will usually also work on aarch64 macOS.
/// - Binaries compiled for x86_64 Windows will usually also work on aarch64 Windows 11+.
/// - Ignore arm for now, as we need to consider the version and whether hard-float is supported.
/// https://github.com/rust-lang/rustup/pull/593
/// https://github.com/cross-rs/cross/pull/1018
/// Does it seem only armv7l+ is supported?
/// https://github.com/actions/runner/blob/v2.315.0/src/Misc/externals.sh#L189
/// https://github.com/actions/runner/issues/688
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
enum HostPlatform {
x86_64_linux_gnu,
x86_64_linux_musl,
x86_64_macos,
x86_64_windows,
aarch64_linux_gnu,
aarch64_linux_musl,
aarch64_macos,
aarch64_windows,
}
impl HostPlatform {
fn rust_target(self) -> &'static str {
match self {
Self::x86_64_linux_gnu => "x86_64-unknown-linux-gnu",
Self::x86_64_linux_musl => "x86_64-unknown-linux-musl",
Self::x86_64_macos => "x86_64-apple-darwin",
Self::x86_64_windows => "x86_64-pc-windows-msvc",
Self::aarch64_linux_gnu => "aarch64-unknown-linux-gnu",
Self::aarch64_linux_musl => "aarch64-unknown-linux-musl",
Self::aarch64_macos => "aarch64-apple-darwin",
Self::aarch64_windows => "aarch64-pc-windows-msvc",
}
}
fn rust_target_arch(self) -> &'static str {
match self {
Self::aarch64_linux_gnu
| Self::aarch64_linux_musl
| Self::aarch64_macos
| Self::aarch64_windows => "aarch64",
Self::x86_64_linux_gnu
| Self::x86_64_linux_musl
| Self::x86_64_macos
| Self::x86_64_windows => "x86_64",
}
}
fn rust_target_os(self) -> &'static str {
match self {
Self::aarch64_linux_gnu
| Self::aarch64_linux_musl
| Self::x86_64_linux_gnu
| Self::x86_64_linux_musl => "linux",
Self::aarch64_macos | Self::x86_64_macos => "macos",
Self::aarch64_windows | Self::x86_64_windows => "windows",
}
}
fn exe_suffix(self) -> &'static str {
match self {
Self::x86_64_windows | Self::aarch64_windows => ".exe",
_ => "",
}
}
None
}
mod github {
use serde_derive::Deserialize;
// https://api.github.com/repos/<repo>
#[derive(Debug, Deserialize)]
pub(crate) struct RepoMetadata {
#[serde(default)]
#[allow(dead_code)]
pub(crate) homepage: Option<String>,
#[serde(default)]
pub(crate) license: Option<RepoLicense>,
pub(crate) default_branch: String,
}
#[derive(Debug, Deserialize)]
pub(crate) struct RepoLicense {
#[serde(default)]
pub(crate) spdx_id: Option<String>,
}
// https://api.github.com/repos/<repo>/releases
pub(crate) type Releases = Vec<Release>;
@@ -948,6 +814,8 @@ mod crates_io {
#[derive(Debug, Deserialize)]
pub(crate) struct Crate {
pub(crate) versions: Vec<Version>,
#[serde(rename = "crate")]
pub(crate) crate_: CrateMetadata,
}
#[derive(Debug, Deserialize)]
@@ -957,6 +825,24 @@ mod crates_io {
pub(crate) num: semver::Version,
pub(crate) yanked: bool,
}
#[derive(Debug, Deserialize)]
pub(crate) struct CrateMetadata {
#[allow(dead_code)]
pub(crate) homepage: Option<String>,
pub(crate) repository: Option<String>,
}
// https://crates.io/api/v1/crates/<crate>/<version>
#[derive(Debug, Deserialize)]
pub(crate) struct VersionMetadata {
pub(crate) version: VersionMetadataDetail,
}
#[derive(Debug, Deserialize)]
pub(crate) struct VersionMetadataDetail {
pub(crate) license: Option<String>,
}
}
mod cargo_manifest {

View File

@@ -0,0 +1,224 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::{env, fmt, io::Write, path::PathBuf};
use anyhow::Result;
use fs_err as fs;
use install_action_internal_codegen::{workspace_root, BaseManifest, Manifests};
fn main() -> Result<()> {
let args: Vec<_> = env::args().skip(1).collect();
if !args.is_empty() || args.iter().any(|arg| arg.starts_with('-')) {
println!(
"USAGE: cargo run --manifest-path tools/codegen/Cargo.toml --bin generate-tools-markdown --release"
);
std::process::exit(1);
}
let workspace_root = workspace_root();
let mut manifest_dir = workspace_root.clone();
manifest_dir.push("manifests");
let mut base_info_dir = workspace_root.clone();
base_info_dir.push("tools");
base_info_dir.push("codegen");
base_info_dir.push("base");
let mut paths: Vec<_> =
fs::read_dir(manifest_dir.clone()).unwrap().map(|r| r.unwrap()).collect();
paths.sort_by_key(fs_err::DirEntry::path);
let mut tools = vec![
MarkdownEntry {
name: "nextest".to_string(),
alias: "cargo-nextest".to_string().into(),
website: "https://nexte.st/".to_string(),
installed_to: InstalledTo::Cargo,
installed_from: InstalledFrom::Binstall,
platforms: Platforms::all(),
repository: "https://github.com/nextest-rs/nextest".to_string(),
license_markdown: "[Apache-2.0](https://github.com/nextest-rs/nextest/blob/HEAD/LICENSE-APACHE) OR [MIT](https://github.com/nextest-rs/nextest/blob/HEAD/LICENSE-MIT)".to_string()
},
MarkdownEntry {
name: "valgrind".to_string(),
alias: None,
website: "https://valgrind.org/".to_string(),
installed_to: InstalledTo::Snap,
installed_from: InstalledFrom::Snap,
platforms: Platforms {
linux: true,
..Default::default()
},
repository: "https://sourceware.org/git/valgrind.git".to_string(),
license_markdown: "[GPL-2.0](https://sourceware.org/git/?p=valgrind.git;a=blob;f=COPYING;hb=HEAD)".to_string()
}
];
for path in paths {
let file_name = path.file_name();
let mut name = PathBuf::from(file_name.clone());
name.set_extension("");
let name = name.to_string_lossy().to_string();
let base_info: BaseManifest =
serde_json::from_slice(&fs::read(base_info_dir.join(file_name.clone()))?)?;
let manifests: Manifests =
serde_json::from_slice(&fs::read(manifest_dir.join(file_name))?)?;
let website = match base_info.website {
Some(website) => website,
None => base_info.repository.clone(),
};
let repository = base_info.repository;
let installed_to =
if manifests.rust_crate.is_some() { InstalledTo::Cargo } else { InstalledTo::UsrLocal };
let installed_from = InstalledFrom::GitHubRelease;
let mut platforms = Platforms::default();
for platform in base_info.platform.keys() {
match platform.rust_target_os() {
"linux" => platforms.linux = true,
"macos" => platforms.macos = true,
"windows" => platforms.windows = true,
&_ => todo!(),
}
}
let license_markdown = manifests.license_markdown;
let readme_entry = MarkdownEntry {
name,
website,
repository,
installed_to,
installed_from,
platforms,
license_markdown,
alias: None,
};
tools.push(readme_entry);
}
tools.sort_by(|x, y| x.name.cmp(&y.name));
let mut markdown_file = workspace_root.clone();
markdown_file.push("TOOLS.md");
let file = std::fs::File::create(markdown_file).expect("Unable to create file");
let mut file = std::io::BufWriter::new(file);
let header = "# Tools
| Name | Where binaries will be installed | Where will it be installed from | Supported platform | License |
| ---- | -------------------------------- | ------------------------------- | ------------------ | ------- |
";
file.write_all(header.as_bytes()).expect("Unable to write header");
for tool in tools {
file.write_all(tool.to_string().as_bytes()).expect("Unable to write entry");
}
Ok(())
}
#[derive(Debug)]
struct MarkdownEntry {
name: String,
alias: Option<String>,
website: String,
repository: String,
installed_to: InstalledTo,
installed_from: InstalledFrom,
platforms: Platforms,
license_markdown: String,
}
#[derive(Debug, Eq, PartialEq)]
enum InstalledFrom {
Binstall,
GitHubRelease,
Snap,
}
#[derive(Debug, Default, Eq, PartialEq)]
struct Platforms {
linux: bool,
macos: bool,
windows: bool,
}
impl Platforms {
fn all() -> Self {
Self { linux: true, macos: true, windows: true }
}
}
impl fmt::Display for Platforms {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut platform_names: Vec<&str> = vec![];
if self.linux {
platform_names.push("Linux");
}
if self.macos {
platform_names.push("macOS");
}
if self.windows {
platform_names.push("Windows");
}
let name = platform_names.join(", ");
f.write_str(&name)?;
Ok(())
}
}
#[derive(Debug, Eq, PartialEq)]
enum InstalledTo {
Cargo,
Snap,
UsrLocal,
}
impl fmt::Display for InstalledTo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InstalledTo::Cargo => f.write_str("`$CARGO_HOME/bin`")?,
InstalledTo::Snap => f.write_str("`/snap/bin`")?,
InstalledTo::UsrLocal => f.write_str("`/usr/local/bin`")?,
}
Ok(())
}
}
impl fmt::Display for MarkdownEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = format!("| [**{}**]({}) ", self.name, self.website);
f.write_str(&name)?;
if let Some(alias) = self.alias.clone() {
let alias = format!("(alias: `{alias}`)");
f.write_str(&alias)?;
}
f.write_str(&format!("| {} ", self.installed_to))?;
match self.installed_from {
InstalledFrom::GitHubRelease => {
let markdown = format!("| [GitHub Releases]({}/releases) ", self.repository);
f.write_str(&markdown)?;
}
InstalledFrom::Binstall => f.write_str("| `cargo-binstall` ")?,
InstalledFrom::Snap => {
let markdown =
format!("| [snap](https://snapcraft.io/install/{}/ubuntu) ", self.name);
f.write_str(&markdown)?;
}
}
f.write_str(&format!("| {} ", self.platforms))?;
f.write_str(&format!("| {} |\n", self.license_markdown))?;
Ok(())
}
}

12
tools/update-markdown.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0 OR MIT
set -eEuo pipefail
IFS=$'\n\t'
cd "$(dirname "$0")"/..
# Update markdown
#
# USAGE:
# ./tools/update-markdown.sh
cargo run --manifest-path tools/codegen/Cargo.toml --bin generate-tools-markdown --release