From f3aed679e4365d08b7533e6de53cbef70eb85130 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 17:50:18 +0000 Subject: [PATCH 1/6] Initial plan From 28f29145c6df468a1566d7fae054569f188d973f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 17:53:12 +0000 Subject: [PATCH 2/6] fix: remove gettext-base/envsubst dependency from astral.sh-uv and opencode.ai Co-authored-by: sebst <592313+sebst@users.noreply.github.com> --- src/astral.sh-uv/install.sh | 16 +++++----------- src/opencode.ai/install.sh | 13 ++++--------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/astral.sh-uv/install.sh b/src/astral.sh-uv/install.sh index 9b5eb09..0defa3c 100755 --- a/src/astral.sh-uv/install.sh +++ b/src/astral.sh-uv/install.sh @@ -8,8 +8,6 @@ readonly githubRepository='astral-sh/uv' readonly binaryName='uv' readonly versionArgument='--version' readonly os="unknown-linux-musl" -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${version}/${binaryName}-${architecture}-${os}.tar.gz' -readonly downloadUrlLatestTemplate='https://github.com/${githubRepository}/releases/latest/download/${binaryName}-${architecture}-${os}.tar.gz' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" readonly AUTOCOMPLETION="${SHELLAUTOCOMPLETION:-"true"}" @@ -29,7 +27,7 @@ apt_get_cleanup() { apt-get clean rm -rf /var/lib/apt/lists/* } -check_curl_envsubst_file_untar_installed() { +check_curl_file_untar_installed() { declare -a requiredAptPackagesMissing=() if ! [ -r '/etc/ssl/certs/ca-certificates.crt' ]; then requiredAptPackagesMissing+=('ca-certificates') @@ -37,9 +35,6 @@ check_curl_envsubst_file_untar_installed() { if ! command -v curl >/dev/null 2>&1; then requiredAptPackagesMissing+=('curl') fi - if ! command -v envsubst >/dev/null 2>&1; then - requiredAptPackagesMissing+=('gettext-base') - fi if ! command -v file >/dev/null 2>&1; then requiredAptPackagesMissing+=('file') fi @@ -130,22 +125,21 @@ enable_autocompletion() { } install() { utils_check_version "$VERSION" - check_curl_envsubst_file_untar_installed + check_curl_file_untar_installed readonly architecture="$(debian_get_arch)" - readonly binaryTargetPathTemplate='${binaryTargetFolder}/${binaryName}' if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then # Avoid GitHub API rate limits by using the latest/download URL - readonly downloadUrl="$(echo -n "$downloadUrlLatestTemplate" | envsubst)" + readonly downloadUrl="https://github.com/${githubRepository}/releases/latest/download/${binaryName}-${architecture}-${os}.tar.gz" else readonly version="${VERSION:?}" - readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/${version}/${binaryName}-${architecture}-${os}.tar.gz" fi curl_check_url "$downloadUrl" # The archive contains files under a directory: uv-${architecture}-${os}/ readonly uvPathInArchive="uv-${architecture}-${os}/$binaryName" readonly uvxPathInArchive="uv-${architecture}-${os}/uvx" readonly stripComponents="$(echo -n "$uvPathInArchive" | awk -F'/' '{print NF-1}')" - readonly binaryTargetPath="$(echo -n "$binaryTargetPathTemplate" | envsubst)" + readonly binaryTargetPath="${binaryTargetFolder}/${binaryName}" readonly uvxTargetPath="${binaryTargetFolder}/uvx" # Extract uv and uvx in a single download/untar curl_download_untar "$downloadUrl" "$stripComponents" "$binaryTargetFolder" "$uvPathInArchive" "$uvxPathInArchive" diff --git a/src/opencode.ai/install.sh b/src/opencode.ai/install.sh index 12ddd64..5629008 100755 --- a/src/opencode.ai/install.sh +++ b/src/opencode.ai/install.sh @@ -7,7 +7,6 @@ set -o allexport readonly githubRepository='sst/opencode' readonly binaryName='opencode' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-linux-${architecture}.tar.gz' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" apt_get_update() { @@ -26,7 +25,7 @@ apt_get_cleanup() { apt-get clean rm -rf /var/lib/apt/lists/* } -check_curl_envsubst_file_unzip_installed() { +check_curl_file_unzip_installed() { declare -a requiredAptPackagesMissing=() if ! [ -r '/etc/ssl/certs/ca-certificates.crt' ]; then requiredAptPackagesMissing+=('ca-certificates') @@ -34,9 +33,6 @@ check_curl_envsubst_file_unzip_installed() { if ! command -v curl >/dev/null 2>&1; then requiredAptPackagesMissing+=('curl') fi - if ! command -v envsubst >/dev/null 2>&1; then - requiredAptPackagesMissing+=('gettext-base') - fi if ! command -v file >/dev/null 2>&1; then requiredAptPackagesMissing+=('file') fi @@ -116,16 +112,15 @@ utils_check_version() { } install() { utils_check_version "$VERSION" - check_curl_envsubst_file_unzip_installed + check_curl_file_unzip_installed readonly architecture="$(debian_get_arch)" - readonly binaryTargetPathTemplate='${binaryTargetFolder}/${binaryName}' if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" - readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/v${version}/${name}-linux-${architecture}.tar.gz" curl_check_url "$downloadUrl" - readonly binaryTargetPath="$(echo -n "$binaryTargetPathTemplate" | envsubst)" + readonly binaryTargetPath="${binaryTargetFolder}/${binaryName}" curl_download_tarball "$downloadUrl" "$binaryTargetFolder" chmod 755 "$binaryTargetPath" } From ac4900e9bc759ca220f392b210ceebcba3757698 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:43:04 +0000 Subject: [PATCH 3/6] fix: remove gettext-base/envsubst dependency from btop and atuin; fix btop URL format Co-authored-by: sebst <592313+sebst@users.noreply.github.com> --- src/atuin.sh/install.sh | 16 +++++----------- src/btop/install.sh | 16 +++++----------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/atuin.sh/install.sh b/src/atuin.sh/install.sh index d1916b6..428f78b 100755 --- a/src/atuin.sh/install.sh +++ b/src/atuin.sh/install.sh @@ -7,8 +7,6 @@ set -o allexport readonly githubRepository='atuinsh/atuin' readonly binaryName='atuin' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-gnu.tar.gz' -readonly binaryPathInArchiveTemplate='${name}-${architecture}-unknown-linux-gnu/${binaryName}' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" apt_get_cleanup() { @@ -27,7 +25,7 @@ apt_get_checkinstall() { DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends --no-install-suggests --option 'Debug::pkgProblemResolver=true' --option 'Debug::pkgAcquire::Worker=1' "$@" fi } -check_curl_envsubst_file_tar_installed() { +check_curl_file_tar_installed() { declare -a requiredAptPackagesMissing=() if ! [ -r '/etc/ssl/certs/ca-certificates.crt' ]; then requiredAptPackagesMissing+=('ca-certificates') @@ -35,9 +33,6 @@ check_curl_envsubst_file_tar_installed() { if ! command -v curl >/dev/null 2>&1; then requiredAptPackagesMissing+=('curl') fi - if ! command -v envsubst >/dev/null 2>&1; then - requiredAptPackagesMissing+=('gettext-base') - fi if ! command -v file >/dev/null 2>&1; then requiredAptPackagesMissing+=('file') fi @@ -123,18 +118,17 @@ utils_check_version() { } install() { utils_check_version "$VERSION" - check_curl_envsubst_file_tar_installed + check_curl_file_tar_installed readonly architecture="$(debian_get_target_arch)" - readonly binaryTargetPathTemplate='${binaryTargetFolder}/${binaryName}' if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" - readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-gnu.tar.gz" curl_check_url "$downloadUrl" - readonly binaryPathInArchive="$(echo -n "$binaryPathInArchiveTemplate" | envsubst)" + readonly binaryPathInArchive="${name}-${architecture}-unknown-linux-gnu/${binaryName}" readonly stripComponents="$(echo -n "$binaryPathInArchive" | awk -F'/' '{print NF-1}')" - readonly binaryTargetPath="$(echo -n "$binaryTargetPathTemplate" | envsubst)" + readonly binaryTargetPath="${binaryTargetFolder}/${binaryName}" curl_download_untar "$downloadUrl" "$stripComponents" "$binaryTargetFolder" "$binaryPathInArchive" chmod 755 "$binaryTargetPath" apt_get_cleanup diff --git a/src/btop/install.sh b/src/btop/install.sh index c93eafc..3ad38d9 100755 --- a/src/btop/install.sh +++ b/src/btop/install.sh @@ -7,8 +7,6 @@ set -o allexport readonly githubRepository='aristocratos/btop' readonly binaryName='btop' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-linux-musl.tbz' -readonly binaryPathInArchiveTemplate='./btop/bin/${binaryName}' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" apt_get_update() { @@ -27,7 +25,7 @@ apt_get_cleanup() { apt-get clean rm -rf /var/lib/apt/lists/* } -check_curl_envsubst_file_tar_installed() { +check_curl_file_tar_installed() { declare -a requiredAptPackagesMissing=() if ! [ -r '/etc/ssl/certs/ca-certificates.crt' ]; then requiredAptPackagesMissing+=('ca-certificates') @@ -35,9 +33,6 @@ check_curl_envsubst_file_tar_installed() { if ! command -v curl >/dev/null 2>&1; then requiredAptPackagesMissing+=('curl') fi - if ! command -v envsubst >/dev/null 2>&1; then - requiredAptPackagesMissing+=('gettext-base') - fi if ! command -v file >/dev/null 2>&1; then requiredAptPackagesMissing+=('file') fi @@ -123,19 +118,18 @@ utils_check_version() { } install() { utils_check_version "$VERSION" - check_curl_envsubst_file_tar_installed + check_curl_file_tar_installed apt_get_checkinstall bzip2 readonly architecture="$(debian_get_target_arch)" - readonly binaryTargetPathTemplate='${binaryTargetFolder}/${binaryName}' if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" - readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-musl.tbz" curl_check_url "$downloadUrl" - readonly binaryPathInArchive="$(echo -n "$binaryPathInArchiveTemplate" | envsubst)" + readonly binaryPathInArchive="./btop/bin/${binaryName}" readonly stripComponents="$(echo -n "$binaryPathInArchive" | awk -F'/' '{print NF-1}')" - readonly binaryTargetPath="$(echo -n "$binaryTargetPathTemplate" | envsubst)" + readonly binaryTargetPath="${binaryTargetFolder}/${binaryName}" curl_download_untarj "$downloadUrl" "$stripComponents" "$binaryTargetFolder" "$binaryPathInArchive" chmod 755 "$binaryTargetPath" apt_get_cleanup From 98ad2a0726212d350b3390b339cc577cb16ee338 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 14:03:19 +0000 Subject: [PATCH 4/6] fix: sync asdf-vm.com with main branch updates (PRs #80-#83) Co-authored-by: sebst <592313+sebst@users.noreply.github.com> --- src/asdf-vm.com/devcontainer-feature.json | 6 +- src/asdf-vm.com/install.sh | 77 ++++++++++++++++++----- 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/asdf-vm.com/devcontainer-feature.json b/src/asdf-vm.com/devcontainer-feature.json index 8fe3191..444d72c 100644 --- a/src/asdf-vm.com/devcontainer-feature.json +++ b/src/asdf-vm.com/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "asdf-vm.com", "id": "asdf-vm.com", - "version": "1.0.1", + "version": "1.0.2", "description": "Install \"asdf\" binary to the HOME folder of the REMOTE user", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/asdf-vm.com", "options": { @@ -9,7 +9,9 @@ "type": "string", "default": "latest", "proposals": [ - "latest" + "latest", + "0.18.1", + "0.18.0" ], "description": "Version of \"asdf\" to install." } diff --git a/src/asdf-vm.com/install.sh b/src/asdf-vm.com/install.sh index da3d967..26a4d8a 100755 --- a/src/asdf-vm.com/install.sh +++ b/src/asdf-vm.com/install.sh @@ -26,21 +26,15 @@ echo_banner() { local text="$1" echo -e "\e[1m\e[97m\e[41m$text\e[0m" } -github_list_releases() { - if [ -z "$1" ]; then - echo "Usage: list_github_releases " - return 1 - fi - local repo="$1" - local url="https://api.github.com/repos/$repo/releases" - curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | sed 's/^v//' -} github_get_latest_release() { if [ -z "$1" ]; then echo "Usage: get_latest_github_release " return 1 fi - github_list_releases "$1" | head -n 1 + local repo="$1" + curl -s -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/$repo/releases/latest" | \ + sed -n 's/.*"tag_name": "\([^"]*\)".*/\1/p' | sed 's/^v//' } utils_check_version() { local version=$1 @@ -50,17 +44,70 @@ utils_check_version() { exit 1 fi } -install() { - utils_check_version "$VERSION" +detect_os() { + local os + os="$(uname -s | tr '[:upper:]' '[:lower:]')" + case "$os" in + linux) echo "linux" ;; + darwin) echo "darwin" ;; + *) echo >&2 "Unsupported OS: $os"; exit 1 ;; + esac +} +detect_arch() { + local arch + arch="$(uname -m)" + case "$arch" in + x86_64 | amd64) echo "amd64" ;; + aarch64 | arm64) echo "arm64" ;; + i386 | i686) echo "386" ;; + *) echo >&2 "Unsupported architecture: $arch"; exit 1 ;; + esac +} +version_lte() { + # Returns 0 (true) if $1 <= $2 + [ "$1" = "$(printf '%s\n%s' "$1" "$2" | sort -V | head -n1)" ] +} +install_legacy() { + # Legacy installation via git clone for versions <= 0.16.0 apt_get_checkinstall git curl ca-certificates - if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then - VERSION=$(github_get_latest_release "$githubRepository") - fi su $_REMOTE_USER -c "git clone https://github.com/$githubRepository.git $_REMOTE_USER_HOME/.asdf --branch v$VERSION" apt_get_cleanup echo '. "$HOME/.asdf/asdf.sh"' >>"$_REMOTE_USER_HOME/.bashrc" echo '. "$HOME/.asdf/completions/asdf.bash"' >>"$_REMOTE_USER_HOME/.bashrc" } +install_binary() { + # Binary installation for versions > 0.15.0 + apt_get_checkinstall curl ca-certificates + local os arch asset_name download_url install_dir + os="$(detect_os)" + arch="$(detect_arch)" + asset_name="asdf-v${VERSION}-${os}-${arch}.tar.gz" + download_url="https://github.com/${githubRepository}/releases/download/v${VERSION}/${asset_name}" + install_dir="$_REMOTE_USER_HOME/.asdf" + echo "Downloading $asset_name..." + mkdir -p "$install_dir/bin" + curl -fsSL "$download_url" | tar -xz -C "$install_dir/bin" + chown -R "$_REMOTE_USER:$_REMOTE_USER" "$install_dir" + apt_get_cleanup + # Add asdf to PATH in shell config + echo 'export PATH="$HOME/.asdf/bin:$PATH"' >>"$_REMOTE_USER_HOME/.bashrc" +} +install() { + utils_check_version "$VERSION" + if ! command -v curl >/dev/null 2>&1; then + apt_get_checkinstall curl ca-certificates + fi + if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then + VERSION=$(github_get_latest_release "$githubRepository") + fi + if version_lte "$VERSION" "0.16.0"; then + echo "Installing legacy bash version (v$VERSION)..." + install_legacy + else + echo "Installing binary version (v$VERSION)..." + install_binary + fi +} echo_banner "devcontainer.community" echo "Installing $name..." install "$@" From 6a549f93e44075c948b92349bcc931c37ae54d30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 14:29:47 +0000 Subject: [PATCH 5/6] fix: resolve merge conflicts - incorporate main's changes and remove envsubst dependency Co-authored-by: sebst <592313+sebst@users.noreply.github.com> --- src/astral.sh-uv/devcontainer-feature.json | 2 +- src/atuin.sh/devcontainer-feature.json | 2 +- src/atuin.sh/install.sh | 19 +++++++++++- src/aws-cli/README.md | 30 +++++++++++++++++++ src/btop/devcontainer-feature.json | 2 +- src/btop/install.sh | 19 +++++++++++- .../devcontainer-feature.json | 2 +- src/charmbracelet-gum/install.sh | 19 +++++++++++- src/chezmoi.io/devcontainer-feature.json | 2 +- src/chezmoi.io/install.sh | 19 +++++++++++- src/jj-vcs.dev/devcontainer-feature.json | 2 +- src/jj-vcs.dev/install.sh | 19 +++++++++++- src/opencode.ai/devcontainer-feature.json | 2 +- src/opencode.ai/install.sh | 21 +++++++++++-- src/smallstep.com/devcontainer-feature.json | 2 +- src/smallstep.com/install.sh | 19 +++++++++++- src/starship.rs/devcontainer-feature.json | 2 +- src/starship.rs/install.sh | 19 +++++++++++- src/zellij.dev/devcontainer-feature.json | 2 +- src/zellij.dev/install.sh | 19 +++++++++++- src/zyedidia-eget/devcontainer-feature.json | 2 +- src/zyedidia-eget/install.sh | 19 +++++++++++- 22 files changed, 222 insertions(+), 22 deletions(-) create mode 100644 src/aws-cli/README.md diff --git a/src/astral.sh-uv/devcontainer-feature.json b/src/astral.sh-uv/devcontainer-feature.json index 1a1da8b..f1e4ba1 100644 --- a/src/astral.sh-uv/devcontainer-feature.json +++ b/src/astral.sh-uv/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "astral.sh/uv", "id": "astral.sh-uv", - "version": "1.0.1", + "version": "1.0.2", "description": "Install \"uv\" and \"uvx\" binaries", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/astral.sh-uv", "options": { diff --git a/src/atuin.sh/devcontainer-feature.json b/src/atuin.sh/devcontainer-feature.json index f94bc83..2d9b055 100644 --- a/src/atuin.sh/devcontainer-feature.json +++ b/src/atuin.sh/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "atuin.sh", "id": "atuin.sh", - "version": "1.0.0", + "version": "1.0.2", "description": "Install \"atuin\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/atuin.sh", "options": { diff --git a/src/atuin.sh/install.sh b/src/atuin.sh/install.sh index 428f78b..a15b164 100755 --- a/src/atuin.sh/install.sh +++ b/src/atuin.sh/install.sh @@ -108,6 +108,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -124,7 +136,12 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" - readonly downloadUrl="https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-gnu.tar.gz" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-${architecture}-unknown-linux-gnu.tar.gz" curl_check_url "$downloadUrl" readonly binaryPathInArchive="${name}-${architecture}-unknown-linux-gnu/${binaryName}" readonly stripComponents="$(echo -n "$binaryPathInArchive" | awk -F'/' '{print NF-1}')" diff --git a/src/aws-cli/README.md b/src/aws-cli/README.md new file mode 100644 index 0000000..4de1ed8 --- /dev/null +++ b/src/aws-cli/README.md @@ -0,0 +1,30 @@ + +# AWS CLI (aws-cli) + +Installs the AWS CLI along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg. + +## Example Usage + +```json +"features": { + "ghcr.io/devcontainer-community/devcontainer-features/aws-cli:1": {} +} +``` + +## Options + +| Options Id | Description | Type | Default Value | +|-----|-----|-----|-----| +| version | Select or enter an AWS CLI version. | string | latest | + +Available versions of the AWS CLI can be found here: https://github.com/aws/aws-cli/blob/v2/CHANGELOG.rst. + +## OS Support + +This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed. + +`bash` is required to execute the `install.sh` script. + +--- + +_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainer-community/devcontainer-features/blob/main/src/aws-cli/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ diff --git a/src/btop/devcontainer-feature.json b/src/btop/devcontainer-feature.json index 78228d0..15c63a2 100644 --- a/src/btop/devcontainer-feature.json +++ b/src/btop/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "btop", "id": "btop", - "version": "1.0.0", + "version": "1.0.2", "description": "Install \"btop\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/btop", "options": { diff --git a/src/btop/install.sh b/src/btop/install.sh index 3ad38d9..b637a4b 100755 --- a/src/btop/install.sh +++ b/src/btop/install.sh @@ -108,6 +108,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -125,7 +137,12 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" - readonly downloadUrl="https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-musl.tbz" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-${architecture}-unknown-linux-musl.tbz" curl_check_url "$downloadUrl" readonly binaryPathInArchive="./btop/bin/${binaryName}" readonly stripComponents="$(echo -n "$binaryPathInArchive" | awk -F'/' '{print NF-1}')" diff --git a/src/charmbracelet-gum/devcontainer-feature.json b/src/charmbracelet-gum/devcontainer-feature.json index aea9d45..fc8852b 100644 --- a/src/charmbracelet-gum/devcontainer-feature.json +++ b/src/charmbracelet-gum/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "charmbracelet/gum", "id": "charmbracelet-gum", - "version": "1.0.2", + "version": "1.0.3", "description": "Install \"gum\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/charmbracelet-gum", "options": { diff --git a/src/charmbracelet-gum/install.sh b/src/charmbracelet-gum/install.sh index 6d221ea..c5c7689 100755 --- a/src/charmbracelet-gum/install.sh +++ b/src/charmbracelet-gum/install.sh @@ -7,7 +7,7 @@ set -o allexport readonly githubRepository='charmbracelet/gum' readonly binaryName='gum' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}_${version}_Linux_${architecture}.tar.gz' +readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}_${version}_Linux_${architecture}.tar.gz' readonly binaryPathInArchiveTemplate='${name}_${version}_Linux_${architecture}/${binaryName}' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" @@ -111,6 +111,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -128,6 +140,11 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" curl_check_url "$downloadUrl" readonly binaryPathInArchive="$(echo -n "$binaryPathInArchiveTemplate" | envsubst)" diff --git a/src/chezmoi.io/devcontainer-feature.json b/src/chezmoi.io/devcontainer-feature.json index 1358fbc..c725721 100644 --- a/src/chezmoi.io/devcontainer-feature.json +++ b/src/chezmoi.io/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "chezmoi.io", "id": "chezmoi.io", - "version": "1.0.0", + "version": "1.0.1", "description": "Install \"chezmoi\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/chezmoi.io", "options": { diff --git a/src/chezmoi.io/install.sh b/src/chezmoi.io/install.sh index da51ead..f04c3f1 100755 --- a/src/chezmoi.io/install.sh +++ b/src/chezmoi.io/install.sh @@ -7,7 +7,7 @@ set -o allexport readonly githubRepository='twpayne/chezmoi' readonly binaryName='chezmoi' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}_${version}_linux_${architecture}.tar.gz' +readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}_${version}_linux_${architecture}.tar.gz' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" apt_get_update() { @@ -103,6 +103,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -120,6 +132,11 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" curl_check_url "$downloadUrl" readonly binaryPathInArchive="$binaryName" diff --git a/src/jj-vcs.dev/devcontainer-feature.json b/src/jj-vcs.dev/devcontainer-feature.json index fe2f756..231c620 100644 --- a/src/jj-vcs.dev/devcontainer-feature.json +++ b/src/jj-vcs.dev/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "jj-vcs.dev", "id": "jj-vcs.dev", - "version": "1.0.0", + "version": "1.0.1", "description": "Install \"jj\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/jj-vcs.dev", "options": { diff --git a/src/jj-vcs.dev/install.sh b/src/jj-vcs.dev/install.sh index b39a046..daf4b11 100755 --- a/src/jj-vcs.dev/install.sh +++ b/src/jj-vcs.dev/install.sh @@ -7,7 +7,7 @@ set -o allexport readonly githubRepository='jj-vcs/jj' readonly binaryName='jj' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-v${version}-${architecture}-unknown-linux-musl.tar.gz' +readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-${releaseTag}-${architecture}-unknown-linux-musl.tar.gz' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" apt_get_update() { @@ -112,6 +112,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -129,6 +141,11 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" curl_check_url "$downloadUrl" readonly binaryPathInArchive="./$binaryName" diff --git a/src/opencode.ai/devcontainer-feature.json b/src/opencode.ai/devcontainer-feature.json index 55fb5fd..90d517c 100644 --- a/src/opencode.ai/devcontainer-feature.json +++ b/src/opencode.ai/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "opencode.ai", "id": "opencode.ai", - "version": "1.0.1", + "version": "1.0.3", "description": "Install \"opencode\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/opencode.ai", "options": { diff --git a/src/opencode.ai/install.sh b/src/opencode.ai/install.sh index 5629008..0b032bb 100755 --- a/src/opencode.ai/install.sh +++ b/src/opencode.ai/install.sh @@ -4,7 +4,7 @@ set -o pipefail set -o noclobber set -o nounset set -o allexport -readonly githubRepository='sst/opencode' +readonly githubRepository='anomalyco/opencode' readonly binaryName='opencode' readonly versionArgument='--version' readonly binaryTargetFolder='/usr/local/bin' @@ -102,6 +102,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -118,7 +130,12 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" - readonly downloadUrl="https://github.com/${githubRepository}/releases/download/v${version}/${name}-linux-${architecture}.tar.gz" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-linux-${architecture}.tar.gz" curl_check_url "$downloadUrl" readonly binaryTargetPath="${binaryTargetFolder}/${binaryName}" curl_download_tarball "$downloadUrl" "$binaryTargetFolder" diff --git a/src/smallstep.com/devcontainer-feature.json b/src/smallstep.com/devcontainer-feature.json index 42a62f8..ff4905d 100644 --- a/src/smallstep.com/devcontainer-feature.json +++ b/src/smallstep.com/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "smallstep.com", "id": "smallstep.com", - "version": "1.0.0", + "version": "1.0.1", "description": "Install \"step\" cli binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/smallstep.com", "options": { diff --git a/src/smallstep.com/install.sh b/src/smallstep.com/install.sh index 9ab3b56..70819b6 100755 --- a/src/smallstep.com/install.sh +++ b/src/smallstep.com/install.sh @@ -7,7 +7,7 @@ set -o allexport readonly githubRepository='smallstep/cli' readonly binaryName='step' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/step_linux_${version}_${architecture}.tar.gz' +readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${releaseTag}/step_linux_${version}_${architecture}.tar.gz' readonly binaryPathInArchiveTemplate='step_${version}/bin/${binaryName}' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" @@ -108,6 +108,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -125,6 +137,11 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" curl_check_url "$downloadUrl" readonly binaryPathInArchive="$(echo -n "$binaryPathInArchiveTemplate" | envsubst)" diff --git a/src/starship.rs/devcontainer-feature.json b/src/starship.rs/devcontainer-feature.json index f6182af..432bf68 100644 --- a/src/starship.rs/devcontainer-feature.json +++ b/src/starship.rs/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "starship.rs", "id": "starship.rs", - "version": "1.0.0", + "version": "1.0.1", "description": "Install \"starship\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/starship.rs", "options": { diff --git a/src/starship.rs/install.sh b/src/starship.rs/install.sh index 134987b..6effbc9 100755 --- a/src/starship.rs/install.sh +++ b/src/starship.rs/install.sh @@ -7,7 +7,7 @@ set -o allexport readonly githubRepository='starship/starship' readonly binaryName='starship' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-musl.tar.gz' +readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-${architecture}-unknown-linux-musl.tar.gz' readonly binaryPathInArchiveTemplate='${binaryName}' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" @@ -113,6 +113,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -130,6 +142,11 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" curl_check_url "$downloadUrl" readonly binaryPathInArchive="$(echo -n "$binaryPathInArchiveTemplate" | envsubst)" diff --git a/src/zellij.dev/devcontainer-feature.json b/src/zellij.dev/devcontainer-feature.json index 62035a8..5ecfebf 100644 --- a/src/zellij.dev/devcontainer-feature.json +++ b/src/zellij.dev/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "zellij.dev", "id": "zellij.dev", - "version": "1.0.0", + "version": "1.0.1", "description": "Install \"zellij\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/zellij.dev", "options": { diff --git a/src/zellij.dev/install.sh b/src/zellij.dev/install.sh index 2d44771..6b8858d 100755 --- a/src/zellij.dev/install.sh +++ b/src/zellij.dev/install.sh @@ -7,7 +7,7 @@ set -o allexport readonly githubRepository='zellij-org/zellij' readonly binaryName='zellij' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-musl.tar.gz' +readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-${architecture}-unknown-linux-musl.tar.gz' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" apt_get_update() { @@ -112,6 +112,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -129,6 +141,11 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" curl_check_url "$downloadUrl" readonly binaryPathInArchive="$binaryName" diff --git a/src/zyedidia-eget/devcontainer-feature.json b/src/zyedidia-eget/devcontainer-feature.json index 80fe0fe..1b366e6 100644 --- a/src/zyedidia-eget/devcontainer-feature.json +++ b/src/zyedidia-eget/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "zyedidia/eget", "id": "zyedidia-eget", - "version": "1.0.0", + "version": "1.0.1", "description": "Install \"eget\" binary", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/zyedidia-eget", "options": { diff --git a/src/zyedidia-eget/install.sh b/src/zyedidia-eget/install.sh index 05d958e..66f722a 100755 --- a/src/zyedidia-eget/install.sh +++ b/src/zyedidia-eget/install.sh @@ -7,7 +7,7 @@ set -o allexport readonly githubRepository='zyedidia/eget' readonly binaryName='eget' readonly versionArgument='--version' -readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-${version}-linux_${architecture}.tar.gz' +readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-${version}-linux_${architecture}.tar.gz' readonly binaryPathInArchiveTemplate='${name}-${version}-linux_${architecture}/${binaryName}' readonly binaryTargetFolder='/usr/local/bin' readonly name="${githubRepository##*/}" @@ -111,6 +111,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -128,6 +140,11 @@ install() { VERSION=$(github_get_latest_release "$githubRepository") fi readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)" curl_check_url "$downloadUrl" readonly binaryPathInArchive="$(echo -n "$binaryPathInArchiveTemplate" | envsubst)" From 92d33a7b1948f64df515ec1350435a676af6d6f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 14:50:02 +0000 Subject: [PATCH 6/6] Update branch Co-authored-by: sebst <592313+sebst@users.noreply.github.com> --- src/astral.sh-uv/devcontainer-feature.json | 2 +- src/astral.sh-uv/install.sh | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/astral.sh-uv/devcontainer-feature.json b/src/astral.sh-uv/devcontainer-feature.json index f1e4ba1..3135b58 100644 --- a/src/astral.sh-uv/devcontainer-feature.json +++ b/src/astral.sh-uv/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "astral.sh/uv", "id": "astral.sh-uv", - "version": "1.0.2", + "version": "1.0.3", "description": "Install \"uv\" and \"uvx\" binaries", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/astral.sh-uv", "options": { diff --git a/src/astral.sh-uv/install.sh b/src/astral.sh-uv/install.sh index 0defa3c..18ed1f5 100755 --- a/src/astral.sh-uv/install.sh +++ b/src/astral.sh-uv/install.sh @@ -109,6 +109,18 @@ github_get_latest_release() { fi github_list_releases "$1" | head -n 1 } +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^v?${escaped_version}$" | head -n 1 +} utils_check_version() { local version=$1 if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then @@ -132,7 +144,12 @@ install() { readonly downloadUrl="https://github.com/${githubRepository}/releases/latest/download/${binaryName}-${architecture}-${os}.tar.gz" else readonly version="${VERSION:?}" - readonly downloadUrl="https://github.com/${githubRepository}/releases/download/${version}/${binaryName}-${architecture}-${os}.tar.gz" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/${releaseTag}/${binaryName}-${architecture}-${os}.tar.gz" fi curl_check_url "$downloadUrl" # The archive contains files under a directory: uv-${architecture}-${os}/