diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c9ad291..1adf19ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,17 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com If rustup is not yet installed, this action downloads [rustup-init for the current platform](https://rust-lang.github.io/rustup/installation/other.html#manual-installation) using HTTPS with tlsv1.2+, verifies SHA256 checksum, and then installs rustup using it. + This also supports installing additional components at the same time by `+` syntax: + + ```yaml + - uses: taiki-e/install-action@v2 + with: + # Install rust stable with rustfmt component and wasm32-wasip1 target. + tool: rust+rustfmt+wasm32-wasip1 + # When installing another rust version: + # tool: rust@nightly + rustfmt + wasm32-wasip1 + ``` + ## [2.76.0] - 2026-05-04 - Support `mdbook-d2`. ([#1737](https://github.com/taiki-e/install-action/pull/1737), thanks @nhu) diff --git a/README.md b/README.md index 41d81e12..c1c97fdb 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,17 @@ You can also omit patch version. tool: cargo-hack@0.5 ``` +For some tools, we support installing additional components at the same time by `+` syntax: + +```yaml +- uses: taiki-e/install-action@v2 + with: + # Install rust stable with rustfmt component and wasm32-wasip1 target. + tool: rust+rustfmt+wasm32-wasip1 + # When installing another rust version: + # tool: rust@nightly + rustfmt + wasm32-wasip1 +``` + To install multiple tools: ```yaml @@ -73,6 +84,16 @@ Or: - uses: taiki-e/install-action@cargo-minimal-versions ``` +Tool names can also be separated with whitespaces (line, space, tab). + +```yaml +- uses: taiki-e/install-action@v2 + with: + tool: | + cargo-hack + cargo-minimal-versions +``` + ## Supported tools See [TOOLS.md](TOOLS.md) for the list of tools that are installed from manifests managed in this action. diff --git a/main.sh b/main.sh index d36573fa..0782604c 100755 --- a/main.sh +++ b/main.sh @@ -43,11 +43,11 @@ normalize_comma_or_space_separated() { if [[ "${list}" == *","* ]]; then # If a comma is contained, consider it is a comma-separated list. # Drop leading and trailing whitespaces in each element. - sed -E 's/ *, */,/g; s/^.//; s/,,$/,/' <<<",${list}," + sed -E 's/ *\+ */+/g; s/ *, */,/g; s/^.//; s/,,$/,/' <<<",${list}," else # Otherwise, consider it is a whitespace-separated list. # Convert whitespace characters into comma. - sed -E 's/ +/,/g; s/^.//' <<<" ${list} " + sed -E 's/ *\+ */+/g; s/ +/,/g; s/^.//' <<<" ${list} " fi } _sudo() { @@ -735,7 +735,12 @@ esac unsupported_tools=() for tool in "${tools[@]}"; do - if [[ "${tool}" == *"@"* ]]; then + additional='' + if [[ "${tool}" == *'+'* ]]; then + additional="${tool#*+}" + tool="${tool%%+*}" + fi + if [[ "${tool}" == *'@'* ]]; then version="${tool#*@}" tool="${tool%@*}" if [[ "${tool}" != 'rust' ]]; then @@ -749,6 +754,12 @@ for tool in "${tools[@]}"; do else version=latest fi + if [[ -n "${additional}" ]]; then + case "${tool}" in + rust) ;; + *) bail "+ syntax is not supported for ${tool}" ;; + esac + fi installed_bin=() case "${tool}" in rust) @@ -758,6 +769,28 @@ for tool in "${tools[@]}"; do info "installing ${tool}@${version}" export RUSTUP_MAX_RETRIES="${RUSTUP_MAX_RETRIES:-10}" rustup_args=(--profile minimal) + if [[ -n "${additional}" ]]; then + component='' + target='' + while read -rd+; do + case "${REPLY}" in + # Last checked: nightly-2026-05-03 + # rustup component list + # rustup target list + cargo | cargo-* | clippy | clippy-* | llvm-* | miri | miri-* | rust-* | rustc-* | rustfmt | rustfmt-*) component+=",${REPLY}" ;; + *) target+=",${REPLY}" ;; + esac + done <<<"${additional}+" + if [[ -n "${component}" ]]; then + if [[ "${component}," == *',miri,'* ]] && [[ "${component}," != *',rust-src,'* ]]; then + component+=',rust-src' + fi + rustup_args+=(--component "${component#,}") + fi + if [[ -n "${target}" ]]; then + rustup_args+=(--target "${target#,}") + fi + fi if type -P rustup >/dev/null; then # --no-self-update is necessary because the windows environment cannot self-update rustup.exe. g retry rustup toolchain add "${version}" --no-self-update "${rustup_args[@]}" diff --git a/tools/ci/tool-list.sh b/tools/ci/tool-list.sh index 95797d6a..4f3d437e 100755 --- a/tools/ci/tool-list.sh +++ b/tools/ci/tool-list.sh @@ -199,13 +199,35 @@ case "${runner}" in # requires glibc 2.17 / musl 1.2 centos:6 | alpine:3.2) ;; *) - case $((RANDOM % 5)) in - 0) tools+=(rust) ;; - 1) tools+=(rust@stable) ;; - 2) tools+=(rust@nightly) ;; - 3) tools+=(rust@1.93) ;; - 4) tools+=(rust@1.93.0) ;; + case $((RANDOM % 4)) in + 0) rust=rust ;; + 1) rust=rust@stable ;; + 2) rust=rust@nightly ;; + 3) rust=rust@1.93 ;; esac + case $((RANDOM % 3)) in + 0) ;; + 1) rust+='+thumbv6m-none-eabi' ;; + 2) rust+=' + thumbv6m-none-eabi' ;; + esac + if [[ "${rust}" == *'nightly'* ]]; then + component=miri + else + component=rustfmt + fi + case $((RANDOM % 5)) in + 0) ;; + 1) rust+="+${component}" ;; + 2) rust+=" + ${component}" ;; + 3) rust+=" +${component}" ;; + 4) rust+="+ ${component}" ;; + esac + case $((RANDOM % 3)) in + 0) ;; + 1) rust+='+thumbv7m-none-eabi' ;; + 2) rust+=' + thumbv7m-none-eabi' ;; + esac + tools+=("${rust}") ;; esac case "${host_os}" in