2023-02-24 01:44:48 +09:00
#!/usr/bin/env bash
2023-06-05 22:58:32 +09:00
# SPDX-License-Identifier: Apache-2.0 OR MIT
2025-02-04 01:28:26 +09:00
set -CeEuo pipefail
2021-12-30 17:33:20 +09:00
IFS = $'\n\t'
2023-09-04 05:46:18 -07:00
rx( ) {
2021-12-30 17:33:20 +09:00
(
set -x
2025-02-04 01:28:26 +09:00
" $@ "
2021-12-30 17:33:20 +09:00
)
}
2026-05-05 02:03:07 +09:00
g( ) {
IFS = ' '
local cmd = " $* "
IFS = $'\n\t'
printf '::group::%s\n' " ${ cmd #retry } "
" $@ "
printf '::endgroup::\n'
}
2021-12-30 17:33:20 +09:00
retry( ) {
2023-01-15 19:55:57 +09:00
for i in { 1..10} ; do
2021-12-30 17:33:20 +09:00
if " $@ " ; then
return 0
else
sleep " ${ i } "
fi
done
" $@ "
}
bail( ) {
2025-02-04 01:28:26 +09:00
printf '::error::%s\n' " $* "
2021-12-30 17:33:20 +09:00
exit 1
}
warn( ) {
2025-02-04 01:28:26 +09:00
printf '::warning::%s\n' " $* "
2021-12-30 17:33:20 +09:00
}
info( ) {
2025-02-04 01:28:26 +09:00
printf >& 2 'info: %s\n' " $* "
2021-12-30 17:33:20 +09:00
}
2025-12-17 19:46:38 +09:00
normalize_comma_or_space_separated( ) {
# Normalize whitespace characters into space because it's hard to handle single input contains lines with POSIX sed alone.
local list = " ${ 1 //[ $'\r\n\t' ]/ } "
if [ [ " ${ list } " = = *"," * ] ] ; then
# If a comma is contained, consider it is a comma-separated list.
# Drop leading and trailing whitespaces in each element.
2026-04-04 22:08:16 +09:00
sed -E 's/ *, */,/g; s/^.//; s/,,$/,/' <<< " , ${ list } , "
2025-12-17 19:46:38 +09:00
else
# Otherwise, consider it is a whitespace-separated list.
# Convert whitespace characters into comma.
sed -E 's/ +/,/g; s/^.//' <<< " ${ list } "
fi
}
2024-04-13 21:29:09 +09:00
_sudo( ) {
2025-02-04 01:28:26 +09:00
if type -P sudo >/dev/null; then
2024-04-13 21:29:09 +09:00
sudo " $@ "
else
" $@ "
fi
}
2022-12-24 21:49:18 +09:00
download_and_checksum( ) {
2022-07-25 19:26:13 +09:00
local url = " $1 "
2022-12-24 21:49:18 +09:00
local checksum = " $2 "
if [ [ -z " ${ enable_checksum } " ] ] ; then
2025-02-04 01:28:26 +09:00
checksum = ''
2022-12-24 21:49:18 +09:00
fi
info " downloading ${ url } "
2026-04-05 16:37:04 +09:00
retry curl --proto '=https' --tlsv1.2 -fsSL --retry 10 -o tmp " ${ url } "
2022-12-24 21:49:18 +09:00
if [ [ -n " ${ checksum } " ] ] ; then
2025-02-04 01:28:26 +09:00
info " verifying sha256 checksum for $( basename -- " ${ url } " ) "
if type -P sha256sum >/dev/null; then
2024-08-12 04:31:50 +09:00
sha256sum -c - >/dev/null <<< " ${ checksum } *tmp "
2025-02-04 01:28:26 +09:00
elif type -P shasum >/dev/null; then
2022-12-24 21:49:18 +09:00
# GitHub-hosted macOS runner does not install GNU Coreutils by default.
# https://github.com/actions/runner-images/issues/90
2024-08-12 04:31:50 +09:00
shasum -a 256 -c - >/dev/null <<< " ${ checksum } *tmp "
2022-12-24 21:49:18 +09:00
else
bail "checksum requires 'sha256sum' or 'shasum' command; consider installing one of them or setting 'checksum' input option to 'false'"
fi
2025-01-17 16:44:56 +09:00
fi
2022-12-24 21:49:18 +09:00
}
download_and_extract( ) {
local url = " $1 "
2024-03-02 15:24:02 +01:00
shift
local checksum = " $1 "
shift
local bin_dir = " $1 "
shift
local bin_in_archive = ( " $@ " ) # path to bin in archive
2023-09-16 22:26:41 +09:00
if [ [ " ${ bin_dir } " = = " ${ install_action_dir } /bin " ] ] ; then
init_install_action_bin_dir
2022-08-01 17:23:02 +09:00
fi
2023-09-04 05:46:18 -07:00
2024-03-02 15:24:02 +01:00
installed_bin = ( )
local tmp
2023-09-04 05:46:18 -07:00
case " ${ tool } " in
2024-03-02 15:24:02 +01:00
# xbuild's binary name is "x", as opposed to the usual crate name
2024-04-01 08:01:27 +08:00
xbuild) installed_bin = ( " ${ bin_dir } /x ${ exe } " ) ; ;
# editorconfig-checker's binary name is renamed below
editorconfig-checker) installed_bin = ( " ${ bin_dir } / ${ tool } ${ exe } " ) ; ;
2024-03-02 15:24:02 +01:00
*)
for tmp in " ${ bin_in_archive [@] } " ; do
2025-02-04 01:28:26 +09:00
installed_bin += ( " ${ bin_dir } / $( basename -- " ${ tmp } " ) " )
2024-03-02 15:24:02 +01:00
done
; ;
2023-09-04 05:46:18 -07:00
esac
2022-12-24 21:49:18 +09:00
2022-07-25 19:26:13 +09:00
local tar_args = ( )
case " ${ url } " in
2024-04-19 21:35:52 +09:00
*.tar.gz | *.tgz)
2025-02-04 01:28:26 +09:00
tar_args += ( 'xzf' )
if ! type -P gzip >/dev/null; then
2024-04-19 21:35:52 +09:00
case " ${ base_distro } " in
debian | fedora | suse | arch | alpine)
2025-02-04 01:28:26 +09:00
printf '::group::Install packages required for installation (gzip)\n'
2024-04-19 21:35:52 +09:00
sys_install gzip
2025-02-04 01:28:26 +09:00
printf '::endgroup::\n'
2024-04-19 21:35:52 +09:00
; ;
2025-01-17 16:44:56 +09:00
esac
fi
; ;
2025-04-21 20:54:48 +02:00
*.gz)
if ! type -P gzip >/dev/null; then
case " ${ base_distro } " in
debian | fedora | suse | arch | alpine)
printf '::group::Install packages required for installation (gzip)\n'
sys_install gzip
printf '::endgroup::\n'
; ;
esac
fi
; ;
2022-12-14 11:24:22 +09:00
*.tar.bz2 | *.tbz2)
2025-02-04 01:28:26 +09:00
tar_args += ( 'xjf' )
if ! type -P bzip2 >/dev/null; then
2022-12-14 11:24:22 +09:00
case " ${ base_distro } " in
2024-04-19 21:35:52 +09:00
debian | fedora | suse | arch | alpine)
2025-02-04 01:28:26 +09:00
printf '::group::Install packages required for installation (bzip2)\n'
2023-07-31 23:09:15 +09:00
sys_install bzip2
2025-02-04 01:28:26 +09:00
printf '::endgroup::\n'
2022-12-14 11:24:22 +09:00
; ;
2025-01-17 16:44:56 +09:00
esac
fi
; ;
2022-12-14 11:24:22 +09:00
*.tar.xz | *.txz)
2025-02-04 01:28:26 +09:00
tar_args += ( 'xJf' )
if ! type -P xz >/dev/null; then
2022-12-14 11:24:22 +09:00
case " ${ base_distro } " in
2023-07-31 23:09:15 +09:00
debian)
2025-02-04 01:28:26 +09:00
printf '::group::Install packages required for installation (xz-utils)\n'
2023-07-31 23:09:15 +09:00
sys_install xz-utils
2025-02-04 01:28:26 +09:00
printf '::endgroup::\n'
2022-12-14 11:24:22 +09:00
; ;
2024-04-19 21:35:52 +09:00
fedora | suse | arch | alpine)
2025-02-04 01:28:26 +09:00
printf '::group::Install packages required for installation (xz)\n'
2023-07-31 23:09:15 +09:00
sys_install xz
2025-02-04 01:28:26 +09:00
printf '::endgroup::\n'
2022-07-25 19:26:13 +09:00
; ;
esac
2024-03-02 15:24:02 +01:00
fi
2024-04-01 08:01:27 +08:00
; ;
2022-12-24 21:49:18 +09:00
*.zip)
2025-02-04 01:28:26 +09:00
if ! type -P unzip >/dev/null; then
2025-01-10 00:04:25 +09:00
case " ${ base_distro } " in
debian | fedora | suse | arch | alpine)
2025-02-04 01:28:26 +09:00
printf '::group::Install packages required for installation (unzip)\n'
2024-03-02 15:24:02 +01:00
sys_install unzip
2025-02-04 01:28:26 +09:00
printf '::endgroup::\n'
2022-12-24 21:49:18 +09:00
; ;
esac
2025-01-17 16:44:56 +09:00
fi
; ;
2026-04-05 17:16:30 +09:00
*.deb)
if ! type -P dpkg-deb >/dev/null; then
case " ${ base_distro } " in
debian | fedora | suse | arch | alpine)
printf '::group::Install packages required for installation (dpkg)\n'
sys_install dpkg
printf '::endgroup::\n'
; ;
esac
fi
; ;
2022-12-24 21:49:18 +09:00
esac
2025-01-17 16:44:56 +09:00
2025-02-04 01:28:26 +09:00
mkdir -p -- " ${ tmp_dir } "
2025-01-17 16:44:56 +09:00
(
2025-02-04 01:28:26 +09:00
cd -- " ${ tmp_dir } "
2023-09-16 22:26:41 +09:00
download_and_checksum " ${ url } " " ${ checksum } "
if [ [ ${# tar_args [@] } -gt 0 ] ] ; then
tar_args += ( "tmp" )
2024-03-02 15:24:02 +01:00
tar " ${ tar_args [@] } "
for tmp in " ${ bin_in_archive [@] } " ; do
2023-09-16 22:26:41 +09:00
case " ${ tool } " in
2025-02-04 01:28:26 +09:00
editorconfig-checker) mv -- " ${ tmp } " " ${ bin_dir } / ${ tool } ${ exe } " ; ;
*) mv -- " ${ tmp } " " ${ bin_dir } / " ; ;
2022-12-27 01:18:59 +09:00
esac
done
else
2024-06-08 17:38:41 +09:00
case " ${ url } " in
2025-01-17 16:44:56 +09:00
*.zip)
2026-03-29 01:12:24 +09:00
unzip -q tmp
2024-06-08 17:38:41 +09:00
for tmp in " ${ bin_in_archive [@] } " ; do
case " ${ tool } " in
2025-02-04 01:28:26 +09:00
editorconfig-checker) mv -- " ${ tmp } " " ${ bin_dir } / ${ tool } ${ exe } " ; ;
*) mv -- " ${ tmp } " " ${ bin_dir } / " ; ;
2024-06-08 17:38:41 +09:00
esac
2025-01-17 16:44:56 +09:00
done
; ;
2025-04-21 20:54:48 +02:00
*.gz)
mv -- tmp " ${ bin_in_archive # \. / } .gz "
gzip -d " ${ bin_in_archive # \. / } .gz "
for tmp in " ${ bin_in_archive [@] } " ; do
mv -- " ${ tmp } " " ${ bin_dir } / "
done
; ;
2026-04-05 17:16:30 +09:00
*.deb)
dpkg-deb -x tmp .
for tmp in " ${ bin_in_archive [@] } " ; do
mv -- " ${ tmp } " " ${ bin_dir } / "
done
; ;
2025-01-17 16:44:56 +09:00
*)
2024-06-08 17:38:41 +09:00
for tmp in " ${ installed_bin [@] } " ; do
2025-02-04 01:28:26 +09:00
mv -- tmp " ${ tmp } "
2025-01-17 16:44:56 +09:00
done
; ;
esac
2022-12-27 01:18:59 +09:00
fi
2025-01-17 16:44:56 +09:00
)
2025-02-04 01:28:26 +09:00
rm -rf -- " ${ tmp_dir } "
2024-06-08 17:38:41 +09:00
2022-12-24 21:49:18 +09:00
case " ${ host_os } " in
linux | macos)
for tmp in " ${ installed_bin [@] } " ; do
if [ [ ! -x " ${ tmp } " ] ] ; then
chmod +x " ${ tmp } "
2025-01-17 16:44:56 +09:00
fi
2022-12-24 21:49:18 +09:00
done
2025-01-17 16:44:56 +09:00
; ;
2022-12-24 21:49:18 +09:00
esac
2025-01-17 16:44:56 +09:00
}
2022-12-24 21:49:18 +09:00
read_manifest( ) {
local tool = " $1 "
local version = " $2 "
local manifest
2025-02-04 01:28:26 +09:00
rust_crate = $( jq -r '.rust_crate' " ${ manifest_dir } / ${ tool } .json " )
2026-04-10 13:12:36 +09:00
manifest = $( jq -r --arg version " ${ version } " '.[$version]' " ${ manifest_dir } / ${ tool } .json " )
2022-12-24 21:49:18 +09:00
if [ [ " ${ manifest } " = = "null" ] ] ; then
download_info = "null"
return 0
2025-01-17 16:44:56 +09:00
fi
2025-02-04 01:28:26 +09:00
exact_version = $( jq -r '.version' <<< " ${ manifest } " )
2022-12-24 21:49:18 +09:00
if [ [ " ${ exact_version } " = = "null" ] ] ; then
2022-12-27 00:21:55 +09:00
exact_version = " ${ version } "
2025-01-17 16:44:56 +09:00
else
2026-04-10 13:12:36 +09:00
manifest = $( jq -r --arg version " ${ exact_version } " '.[$version]' " ${ manifest_dir } / ${ tool } .json " )
2024-06-08 17:38:41 +09:00
if [ [ " ${ rust_crate } " != "null" ] ] ; then
# TODO: don't hardcode tool name and use 'immediate_yank_reflection' field in base manifest.
case " ${ tool } " in
2025-09-06 01:46:45 +09:00
cargo-nextest)
2026-04-05 16:37:04 +09:00
crate_info = $( retry curl --user-agent " ${ ACTION_USER_AGENT } " --proto '=https' --tlsv1.2 -fsSL --retry 10 " https://crates.io/api/v1/crates/ ${ rust_crate } " || true )
2025-06-18 21:45:27 +09:00
if [ [ -n " ${ crate_info } " ] ] ; then
while true; do
2026-04-10 13:12:36 +09:00
yanked = $( jq -r --arg version " ${ exact_version } " '.versions[] | select(.num == $version) | .yanked' <<< " ${ crate_info } " )
2025-06-18 21:45:27 +09:00
if [ [ " ${ yanked } " != "true" ] ] ; then
break
fi
previous_stable_version = $( jq -r '.previous_stable_version' <<< " ${ manifest } " )
if [ [ " ${ previous_stable_version } " = = "null" ] ] ; then
break
fi
info " ${ tool } @ ${ exact_version } is yanked; downgrade to ${ previous_stable_version } "
exact_version = " ${ previous_stable_version } "
2026-04-10 13:12:36 +09:00
manifest = $( jq -r --arg version " ${ exact_version } " '.[$version]' " ${ manifest_dir } / ${ tool } .json " )
2025-06-18 21:45:27 +09:00
done
fi
2025-01-17 16:44:56 +09:00
; ;
esac
fi
fi
2024-11-20 04:05:49 +09:00
case " ${ host_os } " in
2025-01-17 16:44:56 +09:00
linux)
2024-11-20 04:05:49 +09:00
# 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.
2022-12-27 00:21:55 +09:00
# (rustc enables statically linking for linux-musl by default, except for mips.)
host_platform = " ${ host_arch } _linux_musl "
2026-04-10 15:42:08 +09:00
download_info = $( jq -r --arg p " ${ host_platform } " '.[$p]' <<< " ${ manifest } " )
2022-12-24 21:49:18 +09:00
if [ [ " ${ download_info } " = = "null" ] ] ; then
# Even if host_env is musl, we won't issue an error here because it seems that in
# some cases linux-gnu binaries will work on linux-musl hosts.
# https://wiki.alpinelinux.org/wiki/Running_glibc_programs
# TODO: However, a warning may make sense.
2022-12-27 00:21:55 +09:00
host_platform = " ${ host_arch } _linux_gnu "
2026-04-10 15:42:08 +09:00
download_info = $( jq -r --arg p " ${ host_platform } " '.[$p]' <<< " ${ manifest } " )
2024-06-11 23:16:51 +09:00
elif [ [ " ${ host_env } " = = "gnu" ] ] ; then
2024-06-08 17:38:41 +09:00
# TODO: don't hardcode tool name and use 'prefer_linux_gnu' field in base manifest.
case " ${ tool } " in
2025-09-06 01:46:45 +09:00
cargo-nextest)
2024-06-08 17:38:41 +09:00
# TODO: don't hardcode required glibc version
required_glibc_version = 2.27
2025-02-04 01:28:26 +09:00
higher_glibc_version = $( LC_ALL = C sort -Vu <<< " ${ required_glibc_version } " $'\n' " ${ host_glibc_version } " | tail -1)
2024-06-08 17:38:41 +09:00
if [ [ " ${ higher_glibc_version } " = = " ${ host_glibc_version } " ] ] ; then
# musl build of nextest is slow, so use glibc build if host_env is gnu.
# https://github.com/taiki-e/install-action/issues/13
host_platform = " ${ host_arch } _linux_gnu "
2026-04-10 15:42:08 +09:00
download_info = $( jq -r --arg p " ${ host_platform } " '.[$p]' <<< " ${ manifest } " )
2022-12-24 21:49:18 +09:00
fi
; ;
2025-01-17 16:44:56 +09:00
esac
fi
; ;
2022-12-24 21:49:18 +09:00
macos | windows)
2024-11-20 04:05:49 +09:00
# 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+.
2023-09-16 22:26:41 +09:00
host_platform = " ${ host_arch } _ ${ host_os } "
2026-04-10 15:42:08 +09:00
download_info = $( jq -r --arg p " ${ host_platform } " '.[$p]' <<< " ${ manifest } " )
2022-12-24 21:49:18 +09:00
if [ [ " ${ download_info } " = = "null" ] ] && [ [ " ${ host_arch } " != "x86_64" ] ] ; then
2023-09-16 22:26:41 +09:00
host_platform = " x86_64_ ${ host_os } "
2026-04-10 15:42:08 +09:00
download_info = $( jq -r --arg p " ${ host_platform } " '.[$p]' <<< " ${ manifest } " )
2025-01-17 16:44:56 +09:00
fi
; ;
2022-12-24 21:49:18 +09:00
*) bail " unsupported OS type ' ${ host_os } ' for ${ tool } " ; ;
esac
2023-02-11 02:31:05 +09:00
}
read_download_info( ) {
local tool = " $1 "
local version = " $2 "
2022-12-24 21:49:18 +09:00
if [ [ " ${ download_info } " = = "null" ] ] ; then
bail " ${ tool } @ ${ version } for ' ${ host_os } ' is not supported "
2022-07-25 19:26:13 +09:00
fi
2026-03-21 03:42:14 +09:00
checksum = $( jq -r '.hash' <<< " ${ download_info } " )
2025-02-04 01:28:26 +09:00
url = $( jq -r '.url' <<< " ${ download_info } " )
2024-03-02 15:24:02 +01:00
local tmp
bin_in_archive = ( )
2022-12-27 00:21:55 +09:00
if [ [ " ${ url } " = = "null" ] ] ; then
local template
2026-04-10 15:42:08 +09:00
template = $( jq -c --arg p " ${ host_platform } " '.template[$p]' " ${ manifest_dir } / ${ tool } .json " )
2025-02-11 18:55:50 +09:00
template = " ${ template // \$ \{ version \} / ${ exact_version } } "
2025-02-04 01:28:26 +09:00
url = $( jq -r '.url' <<< " ${ template } " )
2025-02-11 18:55:50 +09:00
tmp = $( jq -r '.bin' <<< " ${ template } " )
2024-03-02 15:24:02 +01:00
if [ [ " ${ tmp } " = = *"[" * ] ] ; then
# shellcheck disable=SC2207
2025-02-11 18:55:50 +09:00
bin_in_archive = ( $( jq -r '.bin[]' <<< " ${ template } " ) )
2024-03-02 15:24:02 +01:00
fi
2025-01-17 16:44:56 +09:00
else
2025-02-04 01:28:26 +09:00
tmp = $( jq -r '.bin' <<< " ${ download_info } " )
2024-03-02 15:24:02 +01:00
if [ [ " ${ tmp } " = = *"[" * ] ] ; then
# shellcheck disable=SC2207
2025-02-04 01:28:26 +09:00
bin_in_archive = ( $( jq -r '.bin[]' <<< " ${ download_info } " ) )
2022-12-27 00:21:55 +09:00
fi
2025-01-17 16:44:56 +09:00
fi
2024-03-02 15:24:02 +01:00
if [ [ ${# bin_in_archive [@] } -eq 0 ] ] ; then
2023-08-04 21:58:05 +09:00
if [ [ " ${ tmp } " = = "null" ] ] ; then
2024-06-19 10:57:30 +09:00
bin_in_archive = ( " ${ tool } ${ exe } " )
2023-08-04 21:58:05 +09:00
else
2022-12-24 21:49:18 +09:00
bin_in_archive = ( " ${ tmp } " )
fi
2025-01-17 16:44:56 +09:00
fi
2023-08-04 21:58:05 +09:00
if [ [ " ${ rust_crate } " = = "null" ] ] ; then
2024-06-19 10:57:30 +09:00
# Moving files to /usr/local/bin requires sudo in some environments, so do not use it: https://github.com/taiki-e/install-action/issues/543
2023-09-16 22:26:41 +09:00
bin_dir = " ${ install_action_dir } /bin "
2025-01-17 16:44:56 +09:00
else
2024-06-11 23:16:51 +09:00
bin_dir = " ${ cargo_bin } "
2025-01-17 16:44:56 +09:00
fi
2022-12-24 21:49:18 +09:00
}
download_from_manifest( ) {
read_manifest " $@ "
2023-02-11 02:31:05 +09:00
download_from_download_info " $@ "
}
download_from_download_info( ) {
read_download_info " $@ "
2024-03-02 15:24:02 +01:00
download_and_extract " ${ url } " " ${ checksum } " " ${ bin_dir } " " ${ bin_in_archive [@] } "
2022-07-25 19:26:13 +09:00
}
2022-06-10 23:19:55 +10:00
install_cargo_binstall( ) {
2022-12-24 21:49:18 +09:00
local binstall_version
2025-02-04 01:28:26 +09:00
binstall_version = $( jq -r '.latest.version' " ${ manifest_dir } /cargo-binstall.json " )
local install_binstall = 1
_binstall_version = $( " cargo-binstall ${ exe } " binstall -V 2>/dev/null || true )
2023-09-16 22:26:41 +09:00
if [ [ -n " ${ _binstall_version } " ] ] ; then
if [ [ " ${ _binstall_version } " = = " ${ binstall_version } " ] ] ; then
2023-01-15 21:38:36 +09:00
info " cargo-binstall already installed at ${ cargo_bin } /cargo-binstall ${ exe } "
2022-09-25 17:08:12 +09:00
install_binstall = ''
else
2023-01-15 21:38:36 +09:00
info " cargo-binstall already installed at ${ cargo_bin } /cargo-binstall ${ exe } , but is not compatible version with install-action, upgrading "
2025-02-04 01:28:26 +09:00
rm -- " ${ cargo_bin } /cargo-binstall ${ exe } "
2022-09-25 17:08:12 +09:00
fi
2025-01-17 16:44:56 +09:00
fi
2022-09-25 17:12:29 +10:00
2022-09-25 17:08:12 +09:00
if [ [ -n " ${ install_binstall } " ] ] ; then
2023-09-16 22:26:41 +09:00
info " installing cargo-binstall@latest ( ${ binstall_version } ) "
2022-12-24 21:49:18 +09:00
download_from_manifest "cargo-binstall" "latest"
2025-02-04 01:28:26 +09:00
installed_at = $( type -P " cargo-binstall ${ exe } " || true )
2023-09-16 22:26:41 +09:00
if [ [ -n " ${ installed_at } " ] ] ; then
info " cargo-binstall installed at ${ installed_at } "
else
warn " cargo-binstall should be installed at ${ bin_dir :- } /cargo-binstall ${ exe } ; but cargo-binstall ${ exe } not found in path "
2022-06-10 23:19:55 +10:00
fi
2023-09-16 22:26:41 +09:00
rx " cargo-binstall ${ exe } " binstall -V
2025-01-17 16:44:56 +09:00
fi
2022-06-10 23:19:55 +10:00
}
2022-12-11 16:22:13 +09:00
apt_update( ) {
2024-04-13 21:29:09 +09:00
retry _sudo apt-get -o Acquire::Retries= 10 -qq update
2022-12-14 11:24:22 +09:00
apt_updated = 1
2022-12-11 16:22:13 +09:00
}
apt_install( ) {
2022-12-14 11:24:22 +09:00
if [ [ -z " ${ apt_updated :- } " ] ] ; then
apt_update
fi
2024-04-13 21:29:09 +09:00
retry _sudo apt-get -o Acquire::Retries= 10 -o Dpkg::Use-Pty= 0 install -y --no-install-recommends " $@ "
2022-12-11 16:22:13 +09:00
}
apt_remove( ) {
2024-04-13 21:29:09 +09:00
_sudo apt-get -qq -o Dpkg::Use-Pty= 0 remove -y " $@ "
2022-12-11 16:22:13 +09:00
}
snap_install( ) {
2024-04-13 21:29:09 +09:00
retry _sudo snap install " $@ "
2022-12-11 16:22:13 +09:00
}
2024-04-19 21:35:52 +09:00
dnf_install( ) {
retry _sudo " ${ dnf } " install -y " $@ "
}
zypper_install( ) {
retry _sudo zypper install -y " $@ "
}
pacman_install( ) {
retry _sudo pacman -Sy --noconfirm " $@ "
}
2022-12-14 11:24:22 +09:00
apk_install( ) {
2025-02-04 01:28:26 +09:00
if type -P sudo >/dev/null; then
2024-08-12 04:26:20 +09:00
retry sudo apk --no-cache add " $@ "
2025-02-04 01:28:26 +09:00
elif type -P doas >/dev/null; then
2024-08-12 04:26:20 +09:00
retry doas apk --no-cache add " $@ "
2022-12-14 11:24:22 +09:00
else
2024-08-12 04:26:20 +09:00
retry apk --no-cache add " $@ "
2022-12-14 11:24:22 +09:00
fi
}
sys_install( ) {
case " ${ base_distro } " in
debian) apt_install " $@ " ; ;
2022-12-14 22:40:45 +09:00
fedora) dnf_install " $@ " ; ;
2024-04-19 21:35:52 +09:00
suse) zypper_install " $@ " ; ;
arch) pacman_install " $@ " ; ;
alpine) apk_install " $@ " ; ;
2022-12-14 11:24:22 +09:00
esac
}
2023-09-16 22:26:41 +09:00
init_install_action_bin_dir( ) {
if [ [ -z " ${ init_install_action_bin :- } " ] ] ; then
init_install_action_bin = 1
2025-02-04 01:28:26 +09:00
mkdir -p -- " ${ bin_dir } "
2023-09-16 22:26:41 +09:00
export PATH = " ${ PATH } : ${ bin_dir } "
local _bin_dir
_bin_dir = $( canonicalize_windows_path " ${ bin_dir } " )
# TODO: avoid this when already added
info " adding ' ${ _bin_dir } ' to PATH "
2025-02-04 01:28:26 +09:00
printf '%s\n' " ${ _bin_dir } " >>" ${ GITHUB_PATH } "
2023-09-16 22:26:41 +09:00
fi
}
2023-02-08 15:28:23 +09:00
canonicalize_windows_path( ) {
case " ${ host_os } " in
2026-05-04 19:56:56 +09:00
windows)
local t = " $1 "
if [ [ " ${ t } " = = '/cygdrive/' * ] ] ; then
t = " ${ t #/cygdrive } "
fi
if [ [ " ${ t } " = = '/c/' * ] ] ; then
t = " ${ t / \/ c \/ /C : \\ } "
fi
printf '%s\n' " ${ t // \/ / \\ } "
; ;
2025-02-04 01:28:26 +09:00
*) printf '%s\n' " $1 " ; ;
2023-02-08 15:28:23 +09:00
esac
}
2021-12-30 17:33:20 +09:00
2026-04-19 01:15:15 +09:00
if [ [ $# -gt 0 ] ] ; then
bail " invalid argument ' $1 ' "
fi
# Inputs
tool = " ${ INPUT_TOOL :- } "
tools = ( )
if [ [ -n " ${ tool } " ] ] ; then
while read -rd,; do
tools += ( " ${ REPLY } " )
done < <( normalize_comma_or_space_separated " ${ tool } " )
fi
if [ [ ${# tools [@] } -eq 0 ] ] ; then
warn "no tool specified; this could be caused by a dependabot bug where @<tool_name> tags on this action are replaced by @<version> tags"
# Exit with 0 for backward compatibility.
# TODO: We want to reject it in the next major release.
exit 0
fi
enable_checksum = " ${ INPUT_CHECKSUM :- } "
case " ${ enable_checksum } " in
true ) ; ;
false )
enable_checksum = ''
warn "checksums have been disabled by 'checksum' input option; this is strongly discouraged for security reasons"
; ;
*) bail " 'checksum' input option must be 'true' or 'false': ' ${ enable_checksum } ' " ; ;
esac
fallback = " ${ INPUT_FALLBACK :- } "
case " ${ fallback } " in
none | cargo-binstall | cargo-install) ; ;
*) bail " 'fallback' input option must be 'none', 'cargo-binstall', or 'cargo-install': ' ${ fallback } ' " ; ;
esac
# Unlike gh command, cargo-binstall reads GITHUB_TOKEN first via cli parser, and then reads GH_TOKEN.
# https://github.com/cargo-bins/cargo-binstall/blob/v1.17.9/crates/bin/src/args.rs#L704
token = " ${ GITHUB_TOKEN :- " ${ GH_TOKEN :- " ${ DEFAULT_GITHUB_TOKEN :- } " } " } "
# This prevents tokens from being exposed to subprocesses via environment variables.
# Since the tokens remain in memory, setting `fallback: none` (which prevents the tokens from being
# set in the first place) remains the best practice from a security standpoint, as readme says.
2026-04-19 01:15:51 +09:00
# Note that this does not prevent token leaks via reading `/proc/*/environ` on Linux or
# via `ps -Eww` on macOS. It only reduces the risk of leaks.
2026-04-19 01:15:15 +09:00
unset GITHUB_TOKEN GH_TOKEN DEFAULT_GITHUB_TOKEN
2022-12-15 00:16:20 +09:00
# Refs: https://github.com/rust-lang/rustup/blob/HEAD/rustup-init.sh
2025-02-04 01:28:26 +09:00
base_distro = ''
exe = ''
2022-12-24 21:49:18 +09:00
case " $( uname -s) " in
Linux)
host_os = linux
2024-06-08 17:38:41 +09:00
ldd_version = $( ldd --version 2>& 1 || true )
2026-04-04 22:10:53 +09:00
if [ [ " ${ ldd_version } " = = *'musl' * ] ] ; then
2025-02-04 01:28:26 +09:00
host_env = musl
2024-06-08 17:38:41 +09:00
else
2025-02-04 01:28:26 +09:00
host_env = gnu
2026-04-15 21:24:40 +09:00
host_glibc_version = $( grep -E "GLIBC|GNU libc" <<< " ${ ldd_version } " )
host_glibc_version = " ${ host_glibc_version ##* } "
2024-06-08 17:38:41 +09:00
fi
2026-04-07 00:55:49 +09:00
if [ [ -e /etc/redhat-release ] ] ; then
# /etc/os-release is available on RHEL/CentOS 7+
base_distro = fedora
elif [ [ -e /etc/debian_version ] ] ; then
# /etc/os-release is available on Debian 7+
base_distro = debian
elif [ [ -e /etc/os-release ] ] ; then
2024-07-16 00:11:38 +09:00
if grep -Eq '^ID_LIKE=' /etc/os-release; then
base_distro = $( grep -E '^ID_LIKE=' /etc/os-release | cut -d= -f2)
2022-12-14 22:40:45 +09:00
case " ${ base_distro } " in
*debian*) base_distro = debian ; ;
*fedora*) base_distro = fedora ; ;
*suse*) base_distro = suse ; ;
*arch*) base_distro = arch ; ;
*alpine*) base_distro = alpine ; ;
esac
2025-01-17 16:44:56 +09:00
else
2024-07-16 00:11:38 +09:00
base_distro = $( grep -E '^ID=' /etc/os-release | cut -d= -f2)
2025-01-17 16:44:56 +09:00
fi
2025-02-04 01:28:26 +09:00
base_distro = " ${ base_distro // \" / } "
2025-01-17 16:44:56 +09:00
fi
2022-12-14 22:40:45 +09:00
case " ${ base_distro } " in
2025-01-17 16:44:56 +09:00
fedora)
dnf = dnf
2025-02-04 01:28:26 +09:00
if ! type -P dnf >/dev/null; then
if type -P microdnf >/dev/null; then
2022-12-14 22:40:45 +09:00
# fedora-based distributions have "minimal" images that
# use microdnf instead of dnf.
dnf = microdnf
2025-01-17 16:44:56 +09:00
else
2022-12-14 22:40:45 +09:00
# If neither dnf nor microdnf is available, it is
# probably an RHEL7-based distribution that does not
# have dnf installed by default.
2025-01-17 16:44:56 +09:00
dnf = yum
fi
fi
2022-12-14 10:47:48 +09:00
; ;
2025-01-17 16:44:56 +09:00
esac
; ;
2022-12-24 21:49:18 +09:00
Darwin) host_os = macos ; ;
MINGW* | MSYS* | CYGWIN* | Windows_NT)
host_os = windows
2025-02-04 01:28:26 +09:00
exe = .exe
2022-12-24 21:49:18 +09:00
; ;
*) bail " unrecognized OS type ' $( uname -s) ' " ; ;
2022-07-25 19:26:13 +09:00
esac
2025-09-08 23:17:50 +09:00
# NB: Sync with tools/ci/tool-list.sh.
2023-01-15 18:38:19 +09:00
case " $( uname -m) " in
2025-02-04 01:28:26 +09:00
aarch64 | arm64) host_arch = aarch64 ; ;
2026-03-19 20:29:37 +09:00
# Ignore 32-bit Arm for now, as we need to consider the version and whether hard-float is supported.
2025-09-08 23:17:50 +09:00
# https://github.com/rust-lang/rustup/pull/593
# https://github.com/cross-rs/cross/pull/1018
2026-03-19 20:29:37 +09:00
# And support for 32-bit Arm will be removed in near future.
# https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/#removal-of-operating-system-support-with-node24
2025-09-08 23:17:50 +09:00
# Does it seem only armv7l+ is supported?
# https://github.com/actions/runner/blob/v2.321.0/src/Misc/externals.sh#L178
# https://github.com/actions/runner/issues/688
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>" ; ;
ppc64le) host_arch = powerpc64le ; ;
riscv64) host_arch = riscv64 ; ;
s390x) host_arch = s390x ; ;
# Very few tools provide prebuilt binaries for these.
# TODO: fallback to `cargo install`? (binstall fallback is not good idea here as cargo-binstall doesn't provide prebuilt binaries for these.)
loongarch64 | mips | mips64 | ppc | ppc64 | sun4v) bail " $( uname -m) 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> " ; ;
2026-03-19 20:29:37 +09:00
# GitHub Actions Runner supports x86_64/AArch64/Arm Linux and x86_64/AArch64 Windows/macOS.
# https://github.com/actions/runner/blob/v2.332.0/.github/workflows/build.yml#L24
2025-09-08 23:17:50 +09:00
# https://docs.github.com/en/actions/reference/runners/self-hosted-runners#supported-processor-architectures
# And IBM provides runners for powerpc64le/s390x Linux.
# https://github.com/IBM/actionspz
# So we can assume x86_64 unless it has a known non-x86_64 uname -m result.
# TODO: uname -m on windows-11-arm returns "x86_64"
*) host_arch = x86_64 ; ;
2023-01-15 18:38:19 +09:00
esac
2023-09-16 22:26:41 +09:00
info " host platform: ${ host_arch } _ ${ host_os } "
2022-07-25 19:26:13 +09:00
2025-09-08 23:17:50 +09:00
home = " ${ HOME :- } "
if [ [ -z " ${ home } " ] ] ; then
# https://github.com/IBM/actionspz/issues/30
home = $( realpath ~)
export HOME = " ${ home } "
fi
2024-06-11 23:16:51 +09:00
if [ [ " ${ host_os } " = = "windows" ] ] ; then
2024-06-12 00:58:48 +09:00
if [ [ " ${ home } " = = "/home/" * ] ] ; then
2025-02-09 02:54:13 +09:00
if [ [ -d " ${ home / \/ home \/ //c/Users/ } " ] ] ; then
2024-06-12 00:58:48 +09:00
# MSYS2 https://github.com/taiki-e/install-action/pull/518#issuecomment-2160736760
2025-02-09 02:54:13 +09:00
home = " ${ home / \/ home \/ //c/Users/ } "
elif [ [ -d " ${ home / \/ home \/ //cygdrive/c/Users/ } " ] ] ; then
2024-06-12 01:48:03 +09:00
# Cygwin https://github.com/taiki-e/install-action/issues/224#issuecomment-1720196288
2025-02-09 02:54:13 +09:00
home = " ${ home / \/ home \/ //cygdrive/c/Users/ } "
2024-06-12 00:58:48 +09:00
else
warn " \$HOME starting /home/ ( ${ home } ) on Windows bash is usually fake path, this may cause installation issue "
fi
2025-01-17 16:44:56 +09:00
fi
2024-06-11 23:16:51 +09:00
fi
install_action_dir = " ${ home } /.install-action "
2023-09-16 22:26:41 +09:00
tmp_dir = " ${ install_action_dir } /tmp "
2024-06-11 23:16:51 +09:00
cargo_bin = " ${ CARGO_HOME :- " ${ home } /.cargo " } /bin "
2026-04-15 21:04:29 +09:00
cargo_path = $( type -P cargo || true )
2023-02-08 15:28:23 +09:00
# If $CARGO_HOME does not exist, or cargo installed outside of $CARGO_HOME/bin
# is used ($CARGO_HOME/bin is most likely not included in the PATH), fallback to
2024-06-19 10:57:30 +09:00
# $install_action_dir/bin.
2024-06-11 23:16:51 +09:00
if [ [ " ${ host_os } " = = "windows" ] ] ; then
2026-04-02 20:36:38 +09:00
mkdir -p -- " ${ install_action_dir } "
# See action.yml.
2026-04-19 10:07:01 +09:00
printf '' >| " ${ install_action_dir } " /init
2026-04-15 21:04:29 +09:00
if [ [ -n " ${ cargo_path } " ] ] ; then
info " cargo is located at ${ cargo_path } "
cargo_bin = " ${ cargo_path %/* } "
2024-06-11 23:16:51 +09:00
else
2024-06-19 10:57:30 +09:00
cargo_bin = " ${ install_action_dir } /bin "
2025-01-17 16:44:56 +09:00
fi
2026-04-15 21:04:29 +09:00
elif [ [ ! -e " ${ cargo_bin } " ] ] || [ [ " ${ cargo_path } " != " ${ cargo_bin } /cargo " * ] ] ; then
if [ [ -n " ${ cargo_path } " ] ] ; then
info " cargo is located at ${ cargo_path } "
2025-01-17 16:44:56 +09:00
fi
2024-06-19 10:57:30 +09:00
# Moving files to /usr/local/bin requires sudo in some environments, so do not use it: https://github.com/taiki-e/install-action/issues/543
cargo_bin = " ${ install_action_dir } /bin "
2022-07-25 20:00:53 +09:00
fi
2022-07-25 19:26:13 +09:00
2026-04-02 20:36:38 +09:00
# cargo-binstall may call `cargo install` on their fallback: https://github.com/taiki-e/install-action/pull/54#issuecomment-1383140833
# cross calls rustup on `cross --version` if the current directly is cargo workspace.
export CARGO_NET_RETRY = 10
export RUSTUP_MAX_RETRIES = 10
export DEBIAN_FRONTEND = noninteractive
2026-04-15 21:04:29 +09:00
manifest_dir = " ${ GITHUB_ACTION_PATH } /manifests "
2026-04-02 20:36:38 +09:00
2023-09-16 22:26:41 +09:00
case " ${ host_os } " in
linux)
2025-02-04 01:28:26 +09:00
if ! type -P jq >/dev/null || ! type -P curl >/dev/null || ! type -P tar >/dev/null; then
2023-09-16 22:26:41 +09:00
case " ${ base_distro } " in
2024-04-19 21:35:52 +09:00
debian | fedora | suse | arch | alpine)
2025-02-04 01:28:26 +09:00
printf '::group::Install packages required for installation (jq, curl, and/or tar)\n'
2023-09-16 22:26:41 +09:00
sys_packages = ( )
2025-02-04 01:28:26 +09:00
if ! type -P curl >/dev/null; then
2023-09-16 22:26:41 +09:00
sys_packages += ( ca-certificates curl)
fi
2025-02-04 01:28:26 +09:00
if ! type -P tar >/dev/null; then
2023-09-16 22:26:41 +09:00
sys_packages += ( tar)
fi
if [ [ " ${ dnf :- } " = = "yum" ] ] ; then
# On RHEL7-based distribution jq requires EPEL
2025-02-04 01:28:26 +09:00
if ! type -P jq >/dev/null; then
2023-09-16 22:26:41 +09:00
sys_packages += ( epel-release)
sys_install " ${ sys_packages [@] } "
sys_install jq --enablerepo= epel
else
sys_install " ${ sys_packages [@] } "
fi
else
2025-02-04 01:28:26 +09:00
if ! type -P jq >/dev/null; then
2023-09-16 22:26:41 +09:00
# https://github.com/taiki-e/install-action/issues/521
if [ [ " ${ base_distro } " = = "arch" ] ] ; then
2024-06-09 09:49:06 +08:00
sys_packages += ( glibc)
2025-01-17 16:44:56 +09:00
fi
2023-09-16 22:26:41 +09:00
sys_packages += ( jq)
2025-01-17 16:44:56 +09:00
fi
2023-09-16 22:26:41 +09:00
sys_install " ${ sys_packages [@] } "
2025-01-17 16:44:56 +09:00
fi
2025-02-04 01:28:26 +09:00
printf '::endgroup::\n'
2023-09-16 22:54:11 +09:00
; ;
*) warn "install-action requires at least jq and curl on non-Debian/Fedora/SUSE/Arch/Alpine-based Linux" ; ;
2025-01-17 16:44:56 +09:00
esac
fi
; ;
macos)
2025-02-04 01:28:26 +09:00
if ! type -P jq >/dev/null || ! type -P curl >/dev/null; then
2023-09-16 22:54:11 +09:00
warn "install-action requires at least jq and curl on macOS"
2025-01-17 16:44:56 +09:00
fi
; ;
2023-12-24 17:21:00 +09:00
windows)
2025-02-04 01:28:26 +09:00
if ! type -P curl >/dev/null; then
2023-09-16 22:54:11 +09:00
warn "install-action requires at least curl on Windows"
2023-09-16 22:26:41 +09:00
fi
2025-02-05 21:24:56 +09:00
if [ [ -f " ${ install_action_dir } /jq/bin/jq.exe " ] ] ; then
jq( ) { " ${ install_action_dir } /jq/bin/jq.exe " -b " $@ " ; }
elif type -P jq >/dev/null; then
2025-02-04 01:28:26 +09:00
# https://github.com/jqlang/jq/issues/1854
2026-01-10 21:19:19 +09:00
_tmp = $( jq -r .a <<< '{}' | wc -c)
if [ [ " ${ _tmp } " != 5 ] ] ; then
_tmp = $( { jq -b -r .a 2>/dev/null <<< '{}' || true; } | wc -c)
if [ [ " ${ _tmp } " = = 5 ] ] ; then
2025-02-04 01:28:26 +09:00
jq( ) { command jq -b " $@ " ; }
else
jq( ) { command jq " $@ " | tr -d '\r' ; }
fi
fi
2025-02-05 21:24:56 +09:00
else
printf '::group::Install packages required for installation (jq)\n'
mkdir -p -- " ${ install_action_dir } /jq/bin "
2025-07-06 11:36:24 +09:00
url = 'https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-windows-amd64.exe'
checksum = '23cb60a1354eed6bcc8d9b9735e8c7b388cd1fdcb75726b93bc299ef22dd9334'
2025-02-05 21:24:56 +09:00
(
cd -- " ${ install_action_dir } /jq/bin "
download_and_checksum " ${ url } " " ${ checksum } "
mv -- tmp jq.exe
)
printf '::endgroup::\n'
jq( ) { " ${ install_action_dir } /jq/bin/jq.exe " -b " $@ " ; }
2023-09-16 22:26:41 +09:00
fi
2025-01-17 16:44:56 +09:00
; ;
2023-09-16 22:26:41 +09:00
*) bail " unsupported host OS ' ${ host_os } ' " ; ;
2025-01-17 16:44:56 +09:00
esac
2022-12-14 11:24:22 +09:00
2023-01-16 19:56:58 +09:00
unsupported_tools = ( )
2021-12-30 17:33:20 +09:00
for tool in " ${ tools [@] } " ; do
if [ [ " ${ tool } " = = *"@" * ] ] ; then
version = " ${ tool #*@ } "
2023-01-14 00:02:02 +09:00
tool = " ${ tool %@* } "
2026-05-05 02:03:07 +09:00
if [ [ " ${ tool } " != 'rust' ] ] ; then
if [ [ ! " ${ version } " = ~ ^( [ 1-9] [ 0-9] *( \. [ 0-9] +( \. [ 0-9] +) ?) ?| 0\. [ 1-9] [ 0-9] *( \. [ 0-9] +) ?| ^0\. 0\. [ 0-9] +) ( -[ 0-9A-Za-z\. -] +) ?$| ^latest$ ] ] ; then
if [ [ ! " ${ version } " = ~ ^( [ 1-9] [ 0-9] *( \. [ 0-9] +( \. [ 0-9] +) ?) ?| 0\. [ 1-9] [ 0-9] *( \. [ 0-9] +) ?| ^0\. 0\. [ 0-9] +) ( -[ 0-9A-Za-z\. -] +) ?( \+ [ 0-9A-Za-z\. -] +) ?$| ^latest$ ] ] ; then
bail " install-action does not support semver operators: ' ${ version } ' "
fi
bail " install-action v2 does not support semver build-metadata: ' ${ version } '; if you need these supports again, please submit an issue at <https://github.com/taiki-e/install-action> "
2022-12-25 00:33:00 +09:00
fi
2021-12-30 17:33:20 +09:00
fi
2025-01-17 16:44:56 +09:00
else
2025-02-04 01:28:26 +09:00
version = latest
2025-01-17 16:44:56 +09:00
fi
2024-03-02 15:24:02 +01:00
installed_bin = ( )
2022-12-14 11:24:22 +09:00
case " ${ tool } " in
2026-05-05 02:03:07 +09:00
rust)
if [ [ " ${ version } " = = 'latest' ] ] ; then
version = stable
fi
info " installing ${ tool } @ ${ version } "
export RUSTUP_MAX_RETRIES = " ${ RUSTUP_MAX_RETRIES :- 10 } "
rustup_args = ( --profile minimal)
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 [@] } "
g rustup default " ${ version } "
else
# https://github.com/rust-lang/rustup/tags
# Run tools/rustup-hash.sh to get sha256 hash.
rustup_version = 1.29.0
# https://rust-lang.github.io/rustup/installation/other.html#manual-installation
rust_target = ''
checksum = ''
case " ${ host_os } " in
linux)
rust_target = " ${ host_arch } -unknown- ${ host_os } - ${ host_env } "
case " ${ host_arch } " in
x86_64)
case " ${ host_env } " in
gnu) checksum = 4acc9acc76d5079515b46346a485974457b5a79893cfb01112423c89aeb5aa10 ; ;
musl) checksum = 9cd3fda5fd293890e36ab271af6a786ee22084b5f6c2b83fd8323cec6f0992c1 ; ;
esac
; ;
aarch64)
case " ${ host_env } " in
gnu) checksum = 9732d6c5e2a098d3521fca8145d826ae0aaa067ef2385ead08e6feac88fa5792 ; ;
musl) checksum = 88761caacddb92cd79b0b1f939f3990ba1997d701a38b3e8dd6746a562f2a759 ; ;
esac
; ;
powerpc64le)
case " ${ host_env } " in
gnu) checksum = 4bfff85bd3967d988e14567aa9cc6ab0ea386f0ffeff0f9f14d23f0103bf1f97 ; ;
musl) checksum = e15d033af90b7a55d170aac2d82cc28ddd96dbfcdda7c6d4eb8cb064a99c4646 ; ;
esac
; ;
riscv64)
rust_target = " ${ host_arch } gc-unknown- ${ host_os } - ${ host_env } "
# riscv64gc-unknown-linux-musl is tier 2 without host tools
case " ${ host_env } " in
gnu) checksum = 7e43f2b2e6307d61da17a4dff61e6bceef408b8189822df64e1094590d2a70f9 ; ;
esac
; ;
s390x)
# s390x-unknown-linux-musl is tier 3
case " ${ host_env } " in
gnu) checksum = 66c2c132428b6b77803facb02cbdf33b89d20c00bd20da142be8cb651f2e7cd8 ; ;
esac
; ;
esac
; ;
macos)
rust_target = " ${ host_arch } -apple-darwin "
case " ${ host_arch } " in
x86_64) checksum = 33cf85df9142bc6d29cbc62fa5ca1d4c29622cddb55213a4c1a43c457fb9b2d7 ; ;
aarch64) checksum = aeb4105778ca1bd3c6b0e75768f581c656633cd51368fa61289b6a71696ac7e1 ; ;
esac
; ;
windows)
rust_target = " ${ host_arch } -pc-windows-msvc "
case " ${ host_arch } " in
x86_64) checksum = 86478e53f769379d7f0ebfa7c9aa97cb76ca92233f79aa2cc0dbee2efaac73c7 ; ;
aarch64) checksum = 3af309e6c3062aa11df0e932954f69d13b734d8a431e593812f3ecd9ff9e6ef6 ; ;
esac
; ;
esac
if [ [ -z " ${ rust_target } " ] ] || [ [ -z " ${ checksum } " ] ] ; then
bail " unsupported host platform ${ host_arch } _ ${ host_os } for ${ tool } "
fi
url = " https://static.rust-lang.org/rustup/archive/ ${ rustup_version } / ${ rust_target } /rustup-init ${ exe } "
mkdir -p -- " ${ tmp_dir } "
(
cd -- " ${ tmp_dir } "
download_and_checksum " ${ url } " " ${ checksum } "
mv -- tmp rustup-init
case " ${ host_os } " in
linux | macos) chmod +x ./rustup-init ; ;
esac
g retry ./rustup-init -y --default-toolchain " ${ version } " --no-modify-path " ${ rustup_args [@] } "
)
rm -rf -- " ${ tmp_dir } "
cargo_bin_dir = " ${ CARGO_HOME :- " ${ home } /.cargo " } /bin "
export PATH = " ${ PATH } : ${ cargo_bin_dir } "
cargo_bin_dir = $( canonicalize_windows_path " ${ cargo_bin_dir } " )
info " adding ' ${ cargo_bin_dir } ' to PATH "
printf '%s\n' " ${ cargo_bin_dir } " >>" ${ GITHUB_PATH } "
cargo_path = $( type -P cargo || true )
fi
installed_bin = ( " rustc ${ exe } " " cargo ${ exe } " )
; ;
2023-07-31 23:09:15 +09:00
protoc)
info " installing ${ tool } @ ${ version } "
2022-12-24 21:49:18 +09:00
read_manifest "protoc" " ${ version } "
read_download_info "protoc" " ${ version } "
2022-08-01 18:07:53 +09:00
# Copying files to /usr/local/include requires sudo, so do not use it.
bin_dir = " ${ install_action_dir } /bin "
2022-09-10 20:47:43 +09:00
include_dir = " ${ install_action_dir } /include "
init_install_action_bin_dir
2022-08-01 19:43:41 +09:00
if [ [ ! -e " ${ include_dir } " ] ] ; then
2025-02-04 01:28:26 +09:00
mkdir -p -- " ${ include_dir } "
2025-01-17 16:44:56 +09:00
fi
2025-02-04 01:28:26 +09:00
if ! type -P unzip >/dev/null; then
2022-12-24 21:49:18 +09:00
case " ${ base_distro } " in
debian | fedora | suse | arch | alpine)
2025-02-04 01:28:26 +09:00
printf '::group::Install packages required for installation (unzip)\n'
2022-01-09 18:23:50 +09:00
sys_install unzip
2025-02-04 01:28:26 +09:00
printf '::endgroup::\n'
2022-07-26 12:03:09 +09:00
; ;
2025-01-17 16:44:56 +09:00
esac
fi
2025-02-04 01:28:26 +09:00
mkdir -p -- " ${ tmp_dir } "
2025-01-17 16:44:56 +09:00
(
2025-02-04 01:28:26 +09:00
cd -- " ${ tmp_dir } "
2023-09-16 22:54:11 +09:00
download_and_checksum " ${ url } " " ${ checksum } "
2023-07-18 23:51:08 +09:00
unzip -q tmp
2025-02-04 01:28:26 +09:00
mv -- " bin/protoc ${ exe } " " ${ bin_dir } / "
mkdir -p -- " ${ include_dir } / "
cp -r -- include/. " ${ include_dir } / "
2024-12-04 23:02:01 +09:00
if [ [ -z " ${ PROTOC :- } " ] ] ; then
2023-09-16 22:26:41 +09:00
_bin_dir = $( canonicalize_windows_path " ${ bin_dir } " )
info " setting PROTOC environment variable to ' ${ _bin_dir } /protoc ${ exe } ' "
2025-02-04 01:28:26 +09:00
printf '%s\n' " PROTOC= ${ _bin_dir } /protoc ${ exe } " >>" ${ GITHUB_ENV } "
2025-01-17 16:44:56 +09:00
fi
)
2025-02-04 01:28:26 +09:00
rm -rf -- " ${ tmp_dir } "
2024-03-02 15:24:02 +01:00
installed_bin = ( " ${ tool } ${ exe } " )
2025-01-17 16:44:56 +09:00
; ;
2022-01-09 18:23:50 +09:00
valgrind)
2023-01-16 19:56:58 +09:00
info " installing ${ tool } @ ${ version } "
2022-08-01 21:12:54 +09:00
case " ${ version } " in
latest) ; ;
2022-06-10 22:28:13 +09:00
*) warn " specifying the version of ${ tool } is not supported yet by this action " ; ;
2025-01-17 16:44:56 +09:00
esac
2022-12-24 21:49:18 +09:00
case " ${ host_os } " in
linux) ; ;
2025-02-04 01:28:26 +09:00
macos | windows) bail " ${ tool } for non-Linux is not supported yet by this action " ; ;
2022-12-24 21:49:18 +09:00
*) bail " unsupported host OS ' ${ host_os } ' for ${ tool } " ; ;
2025-01-17 16:44:56 +09:00
esac
2022-01-09 18:23:50 +09:00
# libc6-dbg is needed to run Valgrind
2022-12-11 16:22:13 +09:00
apt_install libc6-dbg
2022-01-09 18:23:50 +09:00
# Use snap to install the latest Valgrind
# https://snapcraft.io/install/valgrind/ubuntu
2022-12-11 16:22:13 +09:00
snap_install valgrind --classic
2024-03-02 15:24:02 +01:00
installed_bin = ( " ${ tool } ${ exe } " )
2025-01-17 16:44:56 +09:00
; ;
2022-12-24 21:49:18 +09:00
cargo-binstall)
2022-08-01 21:12:54 +09:00
case " ${ version } " in
2022-12-24 21:49:18 +09:00
latest) ; ;
*) warn " specifying the version of ${ tool } is not supported by this action " ; ;
2025-01-17 16:44:56 +09:00
esac
2022-07-26 12:03:09 +09:00
install_cargo_binstall
2025-02-04 01:28:26 +09:00
printf '\n'
2025-01-17 16:44:56 +09:00
continue
; ;
*)
2025-09-06 01:46:45 +09:00
# Handle aliases.
2026-03-27 23:22:50 +09:00
# NB: Update alias list in .github/workflows/release.yml, tool input option in test-alias in .github/workflows/ci.yml,
2026-03-21 05:53:02 +09:00
# and match for alias for tools/codegen/src/tools-markdown.rs.
2025-09-07 23:50:01 +09:00
# TODO(codegen): auto-detect cases where crate name and tool name are different.
2022-12-24 21:49:18 +09:00
case " ${ tool } " in
2025-09-06 01:46:45 +09:00
nextest) tool = cargo-nextest ; ;
2025-09-07 23:50:01 +09:00
taplo-cli | typos-cli | wasm-bindgen-cli | wasmtime-cli) tool = " ${ tool %-cli } " ; ;
2022-12-24 21:49:18 +09:00
esac
# Use cargo-binstall fallback if tool is not available.
if [ [ ! -f " ${ manifest_dir } / ${ tool } .json " ] ] ; then
2023-01-16 19:56:58 +09:00
case " ${ version } " in
latest) unsupported_tools += ( " ${ tool } " ) ; ;
*) unsupported_tools += ( " ${ tool } @ ${ version } " ) ; ;
esac
2022-12-24 21:49:18 +09:00
continue
fi
2023-02-11 02:31:05 +09:00
# Use cargo-binstall fallback if tool is available but the specified version not available.
read_manifest " ${ tool } " " ${ version } "
if [ [ " ${ download_info } " = = "null" ] ] ; then
2025-09-08 23:17:50 +09:00
if [ [ " ${ rust_crate } " = = "null" ] ] || [ [ " ${ fallback } " = = "none" ] ] ; then
2025-01-17 16:35:45 +09:00
bail " ${ tool } @ ${ version } for ' ${ host_arch } _ ${ host_os } ' is not supported "
2023-08-04 21:58:05 +09:00
fi
2025-09-08 23:17:50 +09:00
warn " ${ tool } @ ${ version } for ' ${ host_arch } _ ${ host_os } ' is not supported; fallback to ${ fallback } "
2023-02-11 02:31:05 +09:00
case " ${ version } " in
2023-08-04 21:58:05 +09:00
latest) unsupported_tools += ( " ${ rust_crate } " ) ; ;
*) unsupported_tools += ( " ${ rust_crate } @ ${ version } " ) ; ;
2023-02-11 02:31:05 +09:00
esac
continue
fi
2023-01-16 19:56:58 +09:00
info " installing ${ tool } @ ${ version } "
2022-12-24 21:49:18 +09:00
# Pre-install
case " ${ tool } " in
shellcheck)
case " ${ host_os } " in
linux)
2025-02-04 01:28:26 +09:00
if type -P shellcheck >/dev/null; then
2022-12-24 21:49:18 +09:00
apt_remove -y shellcheck
fi
; ;
esac
; ;
2025-06-19 19:55:47 +08:00
cyclonedx)
case " ${ host_os } " in
linux)
apt_install libicu-dev
; ;
esac
; ;
2022-12-24 21:49:18 +09:00
esac
2023-02-11 02:31:05 +09:00
download_from_download_info " ${ tool } " " ${ version } "
2022-06-10 22:28:13 +09:00
; ;
esac
2024-03-02 15:24:02 +01:00
tool_bin_stems = ( )
for tool_bin in " ${ installed_bin [@] } " ; do
2025-02-04 01:28:26 +09:00
tool_bin = $( basename -- " ${ tool_bin } " )
2024-03-02 15:24:02 +01:00
tool_bin_stem = " ${ tool_bin %.exe } "
2025-02-04 01:28:26 +09:00
installed_at = $( type -P " ${ tool_bin } " || true )
2024-03-02 15:24:02 +01:00
if [ [ -z " ${ installed_at } " ] ] ; then
tool_bin = " ${ tool_bin_stem } "
2025-02-04 01:28:26 +09:00
installed_at = $( type -P " ${ tool_bin } " || true )
2024-03-02 15:24:02 +01:00
fi
if [ [ -n " ${ installed_at } " ] ] ; then
info " ${ tool_bin_stem } installed at ${ installed_at } "
else
warn " ${ tool_bin_stem } should be installed at ${ bin_dir : + " ${ bin_dir } / " } ${ tool_bin } ${ exe } ; but ${ tool_bin } ${ exe } not found in path "
fi
tool_bin_stems += ( " ${ tool_bin_stem } " )
done
for tool_bin_stem in " ${ tool_bin_stems [@] } " ; do
# cargo-udeps 0.1.30 and wasm-pack 0.12.0 do not support --version flag.
case " ${ tool_bin_stem } " in
# biome up to 1.2.2 exits with 1 on both --version and --help flags.
# cargo-machete up to 0.6.0 does not support --version flag.
2024-11-08 00:41:35 +09:00
# wait-for-them up to 0.4.0 does not support --version flag.
2026-02-16 17:31:19 +00:00
# gungraun-runner up to 0.17.1 (exclusive) does not support --version flag.
biome | cargo-machete | wait-for-them | gungraun-runner) rx " ${ tool_bin_stem } " --version || true ; ;
2024-03-02 15:24:02 +01:00
# these packages support neither --version nor --help flag.
2026-05-04 14:05:27 +02:00
cargo-auditable | cargo-careful | wasm-bindgen-test-runner | cargo-apple-runner) ; ;
2024-03-02 15:24:02 +01:00
# wasm2es6js does not support --version flag and --help flag doesn't contains version info.
wasm2es6js) ; ;
2025-08-06 12:44:53 +02:00
# iai-callgrind-runner --version works only with iai-callgrind in nearby Cargo.toml.
iai-callgrind-runner) ; ;
2025-12-20 06:00:03 +01:00
# cargo-zigbuild/cargo-insta has no --version flag on `cargo $tool_bin_stem` subcommand.
cargo-zigbuild | cargo-insta) rx " ${ tool_bin_stem } " --version ; ;
2026-04-08 00:10:16 +09:00
# these packages have version command instead of --version flag.
cosign | deepsource | vacuum) rx " ${ tool_bin_stem } " version ; ;
2025-01-17 16:44:56 +09:00
cargo-*)
2024-03-02 15:24:02 +01:00
case " ${ tool_bin_stem } " in
# cargo-valgrind 2.1.0's --version flag just calls cargo's --version flag
cargo-valgrind) rx " ${ tool_bin_stem } " " ${ tool_bin_stem #cargo- } " --help ; ;
*)
if ! rx " ${ tool_bin_stem } " " ${ tool_bin_stem #cargo- } " --version; then
rx " ${ tool_bin_stem } " " ${ tool_bin_stem #cargo- } " --help
fi
; ;
esac
2025-01-17 16:44:56 +09:00
; ;
*)
2024-03-02 15:24:02 +01:00
if ! rx " ${ tool_bin_stem } " --version; then
rx " ${ tool_bin_stem } " --help
2025-01-17 16:44:56 +09:00
fi
; ;
esac
2024-03-02 15:24:02 +01:00
done
2025-02-04 01:28:26 +09:00
printf '\n'
2021-12-30 17:33:20 +09:00
done
2023-01-16 19:56:58 +09:00
if [ [ ${# unsupported_tools [@] } -gt 0 ] ] ; then
2023-09-16 23:11:00 +09:00
IFS = ','
2024-06-08 16:33:32 +09:00
case " ${ fallback } " in
none) bail " install-action does not support ${ unsupported_tools [*] } (fallback is disabled by 'fallback: none' input option) " ; ;
2025-09-08 23:17:50 +09:00
cargo-binstall)
case " ${ host_arch } " in
2026-05-04 20:39:44 +09:00
x86_64 | aarch64 | riscv64) ; ;
2025-09-08 23:17:50 +09:00
*)
info " cargo-binstall does not provide prebuilt binaries for this platform ( ${ host_arch } ); use 'cargo-install' fallback instead "
fallback = cargo-install
; ;
esac
; ;
2024-06-08 16:33:32 +09:00
esac
2025-09-08 23:17:50 +09:00
info " install-action does not support ${ unsupported_tools [*] } ; fallback to ${ fallback } "
IFS = $'\n\t'
2025-09-08 00:22:36 +09:00
case " ${ fallback } " in
cargo-binstall)
install_cargo_binstall
# By default, cargo-binstall enforce downloads over secure transports only.
# As a result, http will be disabled, and it will also set
# min tls version to be 1.2
2026-04-13 17:24:14 +09:00
binstall_args = (
--force
--no-confirm
--locked
# Since the build script can access the token when `cargo install` is called
# within `cargo-binstall`, disables building from source in cargo-binstall
# and fallback to `cargo install` which doesn't need the token.
2026-04-13 18:23:13 +09:00
# TODO: once https://github.com/cargo-bins/cargo-binstall/pull/2533 merged,
# we can remove this and use batch install again.
2026-04-13 17:24:14 +09:00
--disable-strategies compile
)
unsupported_tools2 = ( )
for tool in " ${ unsupported_tools [@] } " ; do
if [ [ -n " ${ token } " ] ] ; then
if ! GITHUB_TOKEN = " ${ token } " cargo-binstall binstall " ${ binstall_args [@] } " " ${ tool } " ; then
warn " cargo-binstall fallback does not support prebuilt binaries for ${ tool } on this platform ( ${ host_arch } ); use 'cargo-install' fallback instead "
unsupported_tools2 += ( " ${ tool } " )
fi
else
if ! cargo-binstall binstall " ${ binstall_args [@] } " " ${ tool } " ; then
warn " cargo-binstall fallback does not support prebuilt binaries for ${ tool } on this platform ( ${ host_arch } ); use 'cargo-install' fallback instead "
unsupported_tools2 += ( " ${ tool } " )
fi
fi
done
if [ [ ${# unsupported_tools2 [@] } -gt 0 ] ] ; then
for tool in " ${ unsupported_tools2 [@] } " ; do
2026-04-13 17:54:45 +09:00
# This logic is from cache-cargo-install-action.
2026-04-13 17:24:14 +09:00
cargo_args = ( --locked)
if [ [ " ${ tool } " = = *"@" * ] ] ; then
version = " ${ tool #*@ } "
tool = " ${ tool %@* } "
if [ [ ! " ${ version } " = ~ ^( [ 1-9] [ 0-9] *\. [ 0-9] +\. [ 0-9] +| 0\. [ 1-9] [ 0-9] *\. [ 0-9] +| ^0\. 0\. [ 0-9] +) ( -[ 0-9A-Za-z\. -] +) ?( \+ [ 0-9A-Za-z\. -] +) ?$| ^latest$ ] ] ; then
if [ [ ! " ${ version } " = ~ ^( [ 1-9] [ 0-9] *( \. [ 0-9] +( \. [ 0-9] +) ?) ?| 0\. [ 1-9] [ 0-9] *( \. [ 0-9] +) ?| ^0\. 0\. [ 0-9] +) ( -[ 0-9A-Za-z\. -] +) ?( \+ [ 0-9A-Za-z\. -] +) ?$| ^latest$ ] ] ; then
bail " install-action does not support non-semver version: ' ${ version } ' "
fi
crate_info = $( retry curl --user-agent " ${ ACTION_USER_AGENT } " --proto '=https' --tlsv1.2 -fsSL --retry 10 " https://crates.io/api/v1/crates/ ${ tool } " )
if [ [ ! " ${ version } " = ~ ^[ 0-9] +( \. [ 0-9] +) ?$ ] ] ; then
bail " install-action does not support non-semver version: ' ${ version } ' "
fi
# shellcheck disable=SC2207
versions = ( $( jq -r --arg start " ${ version } . " '.versions[] | select(.num | startswith($start)) | select(.yanked == false) | .num' <<< " ${ crate_info } " ) )
full_version = ''
for v in ${ versions [@]+ " ${ versions [@] } " } ; do
if [ [ " ${ v } " = ~ ^[ 0-9] +\. [ 0-9] +\. [ 0-9] +( \+ [ 0-9A-Za-z\. -] +) ?$ ] ] ; then
full_version = " ${ v } "
break
fi
done
if [ [ -z " ${ full_version } " ] ] ; then
2026-04-13 17:31:06 +09:00
bail " no stable version found for ${ tool } that match with ' ${ version } .*'; if you want to install a pre-release version, please specify the full version "
2026-04-13 17:24:14 +09:00
fi
version = " ${ full_version } "
fi
cargo_args += ( --version " ${ version } " )
fi
cargo install " ${ cargo_args [@] } " " ${ tool } "
done
2026-04-10 14:47:32 +09:00
fi
2026-04-15 21:04:29 +09:00
if [ [ -z " ${ cargo_path } " ] ] ; then
2025-09-08 00:22:36 +09:00
_bin_dir = $( canonicalize_windows_path " ${ home } /.cargo/bin " )
info " adding ' ${ _bin_dir } ' to PATH "
printf '%s\n' " ${ _bin_dir } " >>" ${ GITHUB_PATH } "
fi
; ;
cargo-install)
cargo install --locked " ${ unsupported_tools [@] } "
; ;
*) bail " unhandled fallback ${ fallback } " ; ;
esac
2023-01-16 19:56:58 +09:00
fi