From 91460a328e961a0ecab0412eb0c7ac8b00a95ca3 Mon Sep 17 00:00:00 2001 From: Kaniska Date: Tue, 12 Aug 2025 18:44:59 +0530 Subject: [PATCH 01/93] [terraform] - Fix terraform installation in ubuntu noble. (#1421) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [terraform] - Fix terraform installation in ubuntu noble. * Adding warning message. * Small changes in the test scripts. * Apply suggestions from code review, removing whitespaces. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestions from code review, to convert into a generic function. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Adding further on review comments * Update src/terraform/install.sh, updating comment. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/terraform/install.sh, removing whitespaces Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Further change to put function for common code as per review comment. * Corrections done based on review comments. * Further corrections. * Update src/terraform/install.sh Co-authored-by: Álvaro Rausell Guiard <33221237+AlvaroRausell@users.noreply.github.com> * Correction in error handling based on review comment. * To check if able start tests --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Álvaro Rausell Guiard <33221237+AlvaroRausell@users.noreply.github.com> --- src/terraform/devcontainer-feature.json | 2 +- src/terraform/install.sh | 100 ++++++++++++++++-- test/terraform/install_in_ubuntu_noble.sh | 18 ++++ .../install_in_ubuntu_noble_sentinel.sh | 21 ++++ test/terraform/scenarios.json | 16 +++ 5 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 test/terraform/install_in_ubuntu_noble.sh create mode 100644 test/terraform/install_in_ubuntu_noble_sentinel.sh diff --git a/src/terraform/devcontainer-feature.json b/src/terraform/devcontainer-feature.json index db1bacc67..ceee4979e 100644 --- a/src/terraform/devcontainer-feature.json +++ b/src/terraform/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "terraform", - "version": "1.4.0", + "version": "1.4.1", "name": "Terraform, tflint, and TFGrunt", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/terraform", "description": "Installs the Terraform CLI and optionally TFLint and Terragrunt. Auto-detects latest version and installs needed dependencies.", diff --git a/src/terraform/install.sh b/src/terraform/install.sh index fb7abc6ee..b1d64c27b 100755 --- a/src/terraform/install.sh +++ b/src/terraform/install.sh @@ -50,6 +50,15 @@ if [ "$(id -u)" -ne 0 ]; then exit 1 fi +# Detect Ubuntu Noble and use new repo setup, else use legacy GPG logic +IS_NOBLE=0 +if grep -qi 'ubuntu' /etc/os-release; then + . /etc/os-release + if [[ "$VERSION_CODENAME" == "noble" ]]; then + IS_NOBLE=1 + fi +fi + # Get the list of GPG key servers that are reachable get_gpg_key_servers() { declare -A keyservers_curl_map=( @@ -89,7 +98,7 @@ receive_gpg_keys() { keyring_args="--no-default-keyring --keyring $2" fi if [ ! -z "${KEYSERVER_PROXY}" ]; then - keyring_args="${keyring_args} --keyserver-options http-proxy=${KEYSERVER_PROXY}" + keyring_args="${keyring_args} --keyserver-options http-proxy=${KEYSERVER_PROXY}" fi # Install curl @@ -101,6 +110,21 @@ receive_gpg_keys() { export GNUPGHOME="/tmp/tmp-gnupg" mkdir -p ${GNUPGHOME} chmod 700 ${GNUPGHOME} + + # Special handling for HashiCorp GPG key on Ubuntu Noble + if [ "$IS_NOBLE" -eq 1 ] && [ "$keys" = "$TERRAFORM_GPG_KEY" ]; then + echo "(*) Ubuntu Noble detected, using Keybase for HashiCorp GPG key import...." + curl -fsSL https://keybase.io/hashicorp/pgp_keys.asc | gpg --import + if ! gpg --list-keys "${TERRAFORM_GPG_KEY}" > /dev/null 2>&1; then + gpg --list-keys + echo "(*) Warning: HashiCorp GPG key not found in keyring after import." + echo " Continuing installation without GPG verification on Ubuntu Noble." + echo " This is expected behavior for Ubuntu Noble due to keyserver issues." + return 1 # Return failure to indicate GPG verification should be skipped + fi + return 0 + fi + echo -e "disable-ipv6\n$(get_gpg_key_servers)" > ${GNUPGHOME}/dirmngr.conf # GPG key download sometimes fails for some reason and retrying fixes it. local retry_count=0 @@ -366,6 +390,32 @@ install_terraform() { curl -sSL -o ${terraform_filename} "${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/${terraform_filename}" } +verify_signature() { + local gpg_key=$1 + local sha256sums_url=$2 + local sig_url=$3 + local sha256sums_file=$4 + local sig_file=$5 + local verify_result=0 + + receive_gpg_keys "$gpg_key" + verify_result=$? + if [ $verify_result -ne 0 ] && [ "$IS_NOBLE" -eq 1 ]; then + echo "Skipping the gpg key validation for ubuntu noble as unable to import the key." + return 1 + fi + curl -sSL -o "$sha256sums_file" "$sha256sums_url" + curl -sSL -o "$sig_file" "$sig_url" + + # Try GPG verification, but don't fail on Noble + gpg --verify "$sig_file" "$sha256sums_file" + verify_result=$? + if [ $verify_result -ne 0 ]; then + echo "(!) GPG verification failed." + exit 1 + fi +} + mkdir -p /tmp/tf-downloads cd /tmp/tf-downloads # Install Terraform, tflint, Terragrunt @@ -378,10 +428,25 @@ if grep -q "The specified key does not exist." "${terraform_filename}"; then fi if [ "${TERRAFORM_SHA256}" != "dev-mode" ]; then if [ "${TERRAFORM_SHA256}" = "automatic" ]; then - receive_gpg_keys TERRAFORM_GPG_KEY - curl -sSL -o terraform_SHA256SUMS "${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS" - curl -sSL -o terraform_SHA256SUMS.sig "${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS.${TERRAFORM_GPG_KEY}.sig" - gpg --verify terraform_SHA256SUMS.sig terraform_SHA256SUMS + # For Ubuntu Noble, try GPG verification but continue if it fails + if [ "$IS_NOBLE" -eq 1 ]; then + echo "(*) Ubuntu Noble detected - attempting GPG verification with fallback..." + set +e + sha256sums_url="${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS" + sig_url="${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS.${TERRAFORM_GPG_KEY}.sig" + verify_signature TERRAFORM_GPG_KEY "$sha256sums_url" "$sig_url" "terraform_SHA256SUMS" "terraform_SHA256SUMS.sig" + verify_result=$? + set -e + if [ $verify_result -ne 0 ]; then + echo "(*) GPG verification failed on Ubuntu Noble, but continuing installation." + echo " Downloading checksums for basic integrity check..." + curl -sSL -o terraform_SHA256SUMS "${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS" + fi + else + sha256sums_url="${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS" + sig_url="${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS.${TERRAFORM_GPG_KEY}.sig" + verify_signature TERRAFORM_GPG_KEY "$sha256sums_url" "$sig_url" "terraform_SHA256SUMS" "terraform_SHA256SUMS.sig" + fi else echo "${TERRAFORM_SHA256} *${terraform_filename}" > terraform_SHA256SUMS fi @@ -477,12 +542,27 @@ if [ "${INSTALL_SENTINEL}" = "true" ]; then curl -sSL -o /tmp/tf-downloads/${sentinel_filename} ${sentinel_releases_url}/${SENTINEL_VERSION}/${sentinel_filename} if [ "${SENTINEL_SHA256}" != "dev-mode" ]; then if [ "${SENTINEL_SHA256}" = "automatic" ]; then - receive_gpg_keys TERRAFORM_GPG_KEY - curl -sSL -o sentinel_checksums.txt ${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS - curl -sSL -o sentinel_checksums.txt.sig ${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS.${TERRAFORM_GPG_KEY}.sig - gpg --verify sentinel_checksums.txt.sig sentinel_checksums.txt + # For Ubuntu Noble, try GPG verification but continue if it fails + if [ "$IS_NOBLE" -eq 1 ]; then + echo "(*) Ubuntu Noble detected - attempting Sentinel GPG verification with fallback..." + set +e + sha256sums_url="${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS" + sig_url="${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS.${TERRAFORM_GPG_KEY}.sig" + verify_signature TERRAFORM_GPG_KEY "$sha256sums_url" "$sig_url" "sentinel_checksums.txt" "sentinel_checksums.txt.sig" + verify_result=$? + set -e + if [ $verify_result -ne 0 ]; then + echo "(*) GPG verification failed on Ubuntu Noble, but continuing installation." + echo " Downloading checksums for basic integrity check..." + curl -sSL -o sentinel_checksums.txt "${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS" + fi + else + sha256sums_url="${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS" + sig_url="${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS.${TERRAFORM_GPG_KEY}.sig" + verify_signature TERRAFORM_GPG_KEY "$sha256sums_url" "$sig_url" "sentinel_checksums.txt" "sentinel_checksums.txt.sig" + fi # Verify the SHASUM matches the archive - shasum -a 256 --ignore-missing -c sentinel_checksums.txt + shasum -a 256 --ignore-missing -c sentinel_checksums.txt else echo "${SENTINEL_SHA256} *${SENTINEL_FILENAME}" >sentinel_checksums.txt fi diff --git a/test/terraform/install_in_ubuntu_noble.sh b/test/terraform/install_in_ubuntu_noble.sh new file mode 100644 index 000000000..a146e0417 --- /dev/null +++ b/test/terraform/install_in_ubuntu_noble.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e + +# Import test library +source dev-container-features-test-lib + +# Check to make sure the user is vscode +check "user is vscode" whoami | grep vscode + +# Check if terraform was installed correctly +check "terraform installed" terraform --version + +check "tflint" tflint --version + +# Report results +reportResults + diff --git a/test/terraform/install_in_ubuntu_noble_sentinel.sh b/test/terraform/install_in_ubuntu_noble_sentinel.sh new file mode 100644 index 000000000..00b832f71 --- /dev/null +++ b/test/terraform/install_in_ubuntu_noble_sentinel.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +# Import test library for `check` command +source dev-container-features-test-lib + +# Check to make sure the user is vscode +check "user is vscode" whoami | grep vscode + +# Check if terraform was installed correctly +check "terraform installed" terraform --version + +check "tflint" tflint --version + +# Sentinel specific tests +check "sentinel" sentinel --version + +# Report result +reportResults + diff --git a/test/terraform/scenarios.json b/test/terraform/scenarios.json index ea6b35b09..81945d042 100644 --- a/test/terraform/scenarios.json +++ b/test/terraform/scenarios.json @@ -1,4 +1,20 @@ { + "install_in_ubuntu_noble": { + "image": "mcr.microsoft.com/devcontainers/base:noble", + "features": { + "terraform": { + "version": "latest" + } + } + }, + "install_in_ubuntu_noble_sentinel": { + "image": "mcr.microsoft.com/devcontainers/base:noble", + "features": { + "terraform": { + "installSentinel": true + } + } + }, "install_sentinel": { "image": "mcr.microsoft.com/devcontainers/base:jammy", "features": { From 5fda44393bc0dbb026ddef02b42ef0630752bc7e Mon Sep 17 00:00:00 2001 From: Kaniska Date: Tue, 12 Aug 2025 18:46:28 +0530 Subject: [PATCH 02/93] [anaconda] - feature installation support for arm64/ aarch64. (#1342) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * anaconda feature installation support for arm64/ aarch64. * Adding support for RHEL based linux distributions. * Correction in the CONDA directory permission * Update src/anaconda/install.sh, removing whitespaces Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/anaconda/install.sh, removing whitespaces Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/anaconda/install.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/anaconda/install.sh, removing whitespaces as suggested by copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/anaconda/install.sh, removing whitespaces Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update test/anaconda/scenarios.json, removing whitespaces Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Correcting incorrect code review suggestion by Copilot * Corrections based on review comments. * Further corrections based on review comments. --------- Co-authored-by: Kaniska244 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Álvaro Rausell Guiard <33221237+AlvaroRausell@users.noreply.github.com> --- src/anaconda/NOTES.md | 3 + src/anaconda/README.md | 2 +- src/anaconda/devcontainer-feature.json | 2 +- src/anaconda/install.sh | 176 ++++++++++++++++-- test/anaconda/install_anaconda_almalinux8.sh | 31 +++ test/anaconda/install_anaconda_almalinux9.sh | 31 +++ test/anaconda/install_anaconda_bookworm.sh | 30 +++ test/anaconda/install_anaconda_bullseye.sh | 30 +++ test/anaconda/install_anaconda_fedora.sh | 31 +++ test/anaconda/install_anaconda_jammy.sh | 30 +++ test/anaconda/install_anaconda_noble.sh | 30 +++ .../install_anaconda_noble_without_user.sh | 30 +++ test/anaconda/install_anaconda_rockylinux8.sh | 31 +++ test/anaconda/install_anaconda_rockylinux9.sh | 32 ++++ test/anaconda/scenarios.json | 86 +++++++++ 15 files changed, 553 insertions(+), 22 deletions(-) create mode 100644 test/anaconda/install_anaconda_almalinux8.sh create mode 100644 test/anaconda/install_anaconda_almalinux9.sh create mode 100644 test/anaconda/install_anaconda_bookworm.sh create mode 100644 test/anaconda/install_anaconda_bullseye.sh create mode 100644 test/anaconda/install_anaconda_fedora.sh create mode 100644 test/anaconda/install_anaconda_jammy.sh create mode 100644 test/anaconda/install_anaconda_noble.sh create mode 100644 test/anaconda/install_anaconda_noble_without_user.sh create mode 100644 test/anaconda/install_anaconda_rockylinux8.sh create mode 100644 test/anaconda/install_anaconda_rockylinux9.sh create mode 100644 test/anaconda/scenarios.json diff --git a/src/anaconda/NOTES.md b/src/anaconda/NOTES.md index 394dd6f1d..4a372cade 100644 --- a/src/anaconda/NOTES.md +++ b/src/anaconda/NOTES.md @@ -17,4 +17,7 @@ conda install python=3.7 This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed. +Also RHEL based linux distributions such as almalinux, rockylinux, fedora are supported now. +Please do note that Alpine and cbl-mariner aren't supported due system level restrictions with the anaconda installer. + `bash` is required to execute the `install.sh` script. diff --git a/src/anaconda/README.md b/src/anaconda/README.md index 3346823b4..f093ce618 100644 --- a/src/anaconda/README.md +++ b/src/anaconda/README.md @@ -35,7 +35,7 @@ conda install python=3.7 ## OS Support This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed. - +Also RHEL based linux distributions such as almalinux, rockylinux, fedora are supported now. `bash` is required to execute the `install.sh` script. diff --git a/src/anaconda/devcontainer-feature.json b/src/anaconda/devcontainer-feature.json index e4779279b..ac76a9b99 100644 --- a/src/anaconda/devcontainer-feature.json +++ b/src/anaconda/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "anaconda", - "version": "1.0.13", + "version": "1.1.0", "name": "Anaconda", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/anaconda", "options": { diff --git a/src/anaconda/install.sh b/src/anaconda/install.sh index 7c7af5b00..6f57a3144 100755 --- a/src/anaconda/install.sh +++ b/src/anaconda/install.sh @@ -13,11 +13,63 @@ USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}" UPDATE_RC="${UPDATE_RC:-"true"}" CONDA_DIR="${CONDA_DIR:-"/usr/local/conda"}" -set -eux +set -euo pipefail export DEBIAN_FRONTEND=noninteractive +# Detect package manager and set install command +detect_package_manager() { + if command -v apt-get > /dev/null; then + PKG_MANAGER="apt-get" + PKG_UPDATE="apt-get update -y" + PKG_INSTALL="apt-get -y install --no-install-recommends" + PKG_CLEAN="apt-get -y clean" + PKG_LISTS="/var/lib/apt/lists/*" + PKG_QUERY="dpkg -s" + elif command -v apk > /dev/null; then + PKG_MANAGER="apk" + PKG_UPDATE="apk update" + PKG_INSTALL="apk add --no-cache" + PKG_CLEAN="rm -rf /var/cache/apk/*" + PKG_LISTS="/var/cache/apk/*" + PKG_QUERY="apk info -e" + elif command -v dnf > /dev/null; then + PKG_MANAGER="dnf" + PKG_UPDATE="dnf -y makecache" + PKG_INSTALL="dnf -y install" + PKG_CLEAN="dnf clean all" + PKG_LISTS="/var/cache/dnf/*" + PKG_QUERY="rpm -q" + elif command -v microdnf > /dev/null; then + PKG_MANAGER="microdnf" + PKG_UPDATE="microdnf update" + PKG_INSTALL="microdnf install -y" + PKG_CLEAN="microdnf clean all" + PKG_LISTS="/var/cache/yum/*" + PKG_QUERY="rpm -q" + elif command -v tdnf > /dev/null; then + PKG_MANAGER="tdnf" + PKG_UPDATE="tdnf makecache" + PKG_INSTALL="tdnf install -y" + PKG_CLEAN="tdnf clean all" + PKG_LISTS="/var/cache/tdnf/*" + PKG_QUERY="rpm -q" + elif command -v yum > /dev/null; then + PKG_MANAGER="yum" + PKG_UPDATE="yum -y makecache" + PKG_INSTALL="yum -y install" + PKG_CLEAN="yum clean all" + PKG_LISTS="/var/cache/yum/*" + PKG_QUERY="rpm -q" + else + echo "No supported package manager found (apt-get, apk, dnf, microdnf, tdnf, yum)." + exit 1 + fi +} + +detect_package_manager + # Clean up -rm -rf /var/lib/apt/lists/* +eval "$PKG_CLEAN" if [ "$(id -u)" -ne 0 ]; then echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' @@ -47,7 +99,12 @@ elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then fi architecture="$(uname -m)" -if [ "${architecture}" != "x86_64" ]; then +# Normalize arm64 to aarch64 for consistency +if [ "${architecture}" = "arm64" ]; then + architecture="aarch64" +fi + +if [ "${architecture}" != "x86_64" ] && [ "${architecture}" != "aarch64" ]; then echo "(!) Architecture $architecture unsupported" exit 1 fi @@ -66,12 +123,76 @@ updaterc() { # Checks if packages are installed and installs them if not check_packages() { - if ! dpkg -s "$@" > /dev/null 2>&1; then - if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then - echo "Running apt-get update..." - apt-get update -y + for pkg in "$@"; do + # Use PKG_QUERY variable to check if package is installed + if ! eval "$PKG_QUERY $pkg" > /dev/null 2>&1; then + # Package not installed, check if we need to update package lists + if [ "$PKG_MANAGER" = "apt-get" ]; then + # For apt-get, check if package lists are empty + if [ "$(find "$PKG_LISTS" | wc -l)" = "0" ]; then + echo "Running $PKG_UPDATE..." + eval "$PKG_UPDATE" + fi + else + # For other package managers, always update before installing + echo "Running $PKG_UPDATE..." + eval "$PKG_UPDATE" + fi + + # Install the package + echo "Installing package: $pkg" + eval "$PKG_INSTALL $pkg" + else + echo "Package $pkg is already installed" fi - apt-get -y install --no-install-recommends "$@" + done +} + +sudo_if() { + COMMAND="$*" + if [ "$(id -u)" -eq 0 ] && [ "$USERNAME" != "root" ]; then + if command -v runuser > /dev/null; then + runuser -l "$USERNAME" -c "$COMMAND" + elif command -v su > /dev/null; then + su - "$USERNAME" -c "$COMMAND" + elif command -v sudo > /dev/null; then + sudo -u "$USERNAME" -i bash -c "$COMMAND" + else + # Fallback: execute as root (not ideal but works in containers) + echo "Warning: No user switching command available, running as root" + eval "$COMMAND" + fi + else + eval "$COMMAND" + fi +} + +run_as_user() { + local user="$1" + shift + local cmd="$*" + + if command -v runuser > /dev/null; then + if [ "$PKG_MANAGER" = "apk" ]; then + runuser "$user" -c "$cmd" + else + runuser -l "$user" -c "$cmd" + fi + elif command -v su > /dev/null; then + if [ "$PKG_MANAGER" = "apk" ]; then + su "$user" -c "$cmd" + else + su --login -c "$cmd" "$user" + fi + elif command -v sudo > /dev/null; then + if [ "$PKG_MANAGER" = "apk" ]; then + sudo -u "$user" sh -c "$cmd" + else + sudo -u "$user" -i bash -c "$cmd" + fi + else + echo "Warning: No user switching command available, running as root" + eval "$cmd" fi } @@ -83,30 +204,46 @@ if ! conda --version &> /dev/null ; then usermod -a -G conda "${USERNAME}" # Install dependencies - check_packages wget ca-certificates + if [ "$PKG_MANAGER" = "apt-get" ]; then + check_packages wget ca-certificates libgtk-3-0 + elif [ "$PKG_MANAGER" = "apk" ]; then + check_packages wget ca-certificates gtk+3.0 + else + check_packages wget ca-certificates gtk3 + fi mkdir -p $CONDA_DIR + chown -R "${USERNAME}:conda" "${CONDA_DIR}" - chmod -R g+r+w "${CONDA_DIR}" - - find "${CONDA_DIR}" -type d -print0 | xargs -n 1 -0 chmod g+s + chmod -R g+r+w "${CONDA_DIR}" + echo "Installing Anaconda..." CONDA_VERSION=$VERSION if [ "${VERSION}" = "latest" ] || [ "${VERSION}" = "lts" ]; then - CONDA_VERSION="2021.11" + CONDA_VERSION="2024.10-1" fi - su --login -c "export http_proxy=${http_proxy:-} && export https_proxy=${https_proxy:-} \ - && wget -q https://repo.anaconda.com/archive/Anaconda3-${CONDA_VERSION}-Linux-x86_64.sh -O /tmp/anaconda-install.sh \ - && /bin/bash /tmp/anaconda-install.sh -u -b -p ${CONDA_DIR}" ${USERNAME} 2>&1 + if [ "${architecture}" = "x86_64" ]; then + run_as_user "${USERNAME}" "export http_proxy=${http_proxy:-} && export https_proxy=${https_proxy:-} \ + && wget -q https://repo.anaconda.com/archive/Anaconda3-${CONDA_VERSION}-Linux-x86_64.sh -O /tmp/anaconda-install.sh \ + && /bin/bash /tmp/anaconda-install.sh -u -b -p ${CONDA_DIR}" + elif [ "${architecture}" = "aarch64" ]; then + run_as_user "${USERNAME}" "export http_proxy=${http_proxy:-} && export https_proxy=${https_proxy:-} \ + && wget -q https://repo.anaconda.com/archive/Anaconda3-${CONDA_VERSION}-Linux-aarch64.sh -O /tmp/anaconda-install.sh \ + && /bin/bash /tmp/anaconda-install.sh -u -b -p ${CONDA_DIR}" + fi if [ "${VERSION}" = "latest" ] || [ "${VERSION}" = "lts" ]; then PATH=$PATH:${CONDA_DIR}/bin conda update -y conda fi - rm /tmp/anaconda-install.sh + chown -R "${USERNAME}:conda" "${CONDA_DIR}" + chmod -R g+r+w "${CONDA_DIR}" + + + rm /tmp/anaconda-install.sh updaterc "export CONDA_DIR=${CONDA_DIR}/bin" fi @@ -135,7 +272,6 @@ if [ -f "/etc/bash.bashrc" ]; then echo "${notice_script}" | tee -a /etc/bash.bashrc fi -# Clean up -rm -rf /var/lib/apt/lists/* - +# Final clean up +eval "$PKG_CLEAN" echo "Done!" diff --git a/test/anaconda/install_anaconda_almalinux8.sh b/test/anaconda/install_anaconda_almalinux8.sh new file mode 100644 index 000000000..416d32a2b --- /dev/null +++ b/test/anaconda/install_anaconda_almalinux8.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + + diff --git a/test/anaconda/install_anaconda_almalinux9.sh b/test/anaconda/install_anaconda_almalinux9.sh new file mode 100644 index 000000000..416d32a2b --- /dev/null +++ b/test/anaconda/install_anaconda_almalinux9.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + + diff --git a/test/anaconda/install_anaconda_bookworm.sh b/test/anaconda/install_anaconda_bookworm.sh new file mode 100644 index 000000000..4a17f3dc1 --- /dev/null +++ b/test/anaconda/install_anaconda_bookworm.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + diff --git a/test/anaconda/install_anaconda_bullseye.sh b/test/anaconda/install_anaconda_bullseye.sh new file mode 100644 index 000000000..4a17f3dc1 --- /dev/null +++ b/test/anaconda/install_anaconda_bullseye.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + diff --git a/test/anaconda/install_anaconda_fedora.sh b/test/anaconda/install_anaconda_fedora.sh new file mode 100644 index 000000000..416d32a2b --- /dev/null +++ b/test/anaconda/install_anaconda_fedora.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + + diff --git a/test/anaconda/install_anaconda_jammy.sh b/test/anaconda/install_anaconda_jammy.sh new file mode 100644 index 000000000..4a17f3dc1 --- /dev/null +++ b/test/anaconda/install_anaconda_jammy.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + diff --git a/test/anaconda/install_anaconda_noble.sh b/test/anaconda/install_anaconda_noble.sh new file mode 100644 index 000000000..4a17f3dc1 --- /dev/null +++ b/test/anaconda/install_anaconda_noble.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + diff --git a/test/anaconda/install_anaconda_noble_without_user.sh b/test/anaconda/install_anaconda_noble_without_user.sh new file mode 100644 index 000000000..4a17f3dc1 --- /dev/null +++ b/test/anaconda/install_anaconda_noble_without_user.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + diff --git a/test/anaconda/install_anaconda_rockylinux8.sh b/test/anaconda/install_anaconda_rockylinux8.sh new file mode 100644 index 000000000..416d32a2b --- /dev/null +++ b/test/anaconda/install_anaconda_rockylinux8.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + + diff --git a/test/anaconda/install_anaconda_rockylinux9.sh b/test/anaconda/install_anaconda_rockylinux9.sh new file mode 100644 index 000000000..d71085c4c --- /dev/null +++ b/test/anaconda/install_anaconda_rockylinux9.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "conda" conda --version +check "python" python --version +check "pylint" pylint --version +check "flake8" flake8 --version +check "autopep8" autopep8 --version +check "yapf" yapf --version +check "pydocstyle" pydocstyle --version +check "pycodestyle" pycodestyle --version +check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt + +check "certifi" pip show certifi | grep Version +check "cryptography" pip show cryptography | grep Version +check "setuptools" pip show setuptools | grep Version +check "tornado" pip show tornado | grep Version + +check "conda-update-conda" bash -c "conda update -y conda" +check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow" +check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch" + +# Report result +reportResults + + + diff --git a/test/anaconda/scenarios.json b/test/anaconda/scenarios.json new file mode 100644 index 000000000..65fba8458 --- /dev/null +++ b/test/anaconda/scenarios.json @@ -0,0 +1,86 @@ +{ + "install_anaconda_noble": { + "image": "mcr.microsoft.com/devcontainers/base:noble", + "user": "vscode", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_jammy": { + "image": "mcr.microsoft.com/devcontainers/base:jammy", + "user": "vscode", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_bookworm": { + "image": "mcr.microsoft.com/devcontainers/base:bookworm", + "user": "vscode", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_bullseye": { + "image": "mcr.microsoft.com/devcontainers/base:bullseye", + "user": "vscode", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_noble_without_user": { + "image": "mcr.microsoft.com/devcontainers/base:noble", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_almalinux8": { + "image": "almalinux:8", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_almalinux9": { + "image": "almalinux:9", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_rockylinux8": { + "image": "rockylinux:8", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_rockylinux9": { + "image": "rockylinux:9", + "features": { + "anaconda": { + "version": "latest" + } + } + }, + "install_anaconda_fedora": { + "image": "fedora", + "features": { + "anaconda": { + "version": "latest" + } + } + } +} From 04f00232d1d98b4e72b986fd679929ccfe2d8754 Mon Sep 17 00:00:00 2001 From: Olivier Lemasle Date: Tue, 12 Aug 2025 15:25:43 +0200 Subject: [PATCH 03/93] [rust] Update NOTES.md (#1426) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README.md was updated in #1376, but NOTES.md was left as is. The changes in README.md will be overriden when CI will update the documentation (e.g. with #1408). This PR also regenerates README.md, which fixes the documentation for option `components`. Co-authored-by: Álvaro Rausell Guiard <33221237+AlvaroRausell@users.noreply.github.com> --- src/rust/NOTES.md | 7 ++++++- src/rust/README.md | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/rust/NOTES.md b/src/rust/NOTES.md index 19fe92f31..1f01e6e52 100644 --- a/src/rust/NOTES.md +++ b/src/rust/NOTES.md @@ -2,6 +2,11 @@ ## OS Support -This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed. +This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, RockyLinux +and Mariner distributions with the `apt`, `yum`, `dnf`, `microdnf` and `tdnf` package manager installed. + + +**Note:** Alpine is not supported because the rustup-init binary requires glibc to run, but Alpine Linux does not include `glibc` +by default. Instead, it uses musl libc, which is not binary-compatible with glibc. `bash` is required to execute the `install.sh` script. diff --git a/src/rust/README.md b/src/rust/README.md index 963588c2a..ef0bc2311 100644 --- a/src/rust/README.md +++ b/src/rust/README.md @@ -18,7 +18,7 @@ Installs Rust, common Rust utilities, and their required dependencies | version | Select or enter a version of Rust to install. | string | latest | | profile | Select a rustup install profile. | string | minimal | | targets | Optional comma separated list of additional Rust targets to install. | string | - | -| components | Optional comma separeated list of rust components to be installed based on input. | string | rust-analyzer,rust-src,rustfmt,clippy | +| components | Optional, comma separated list of Rust components to be installed | string | rust-analyzer,rust-src,rustfmt,clippy | ## Customizations From b9c09c4dcb7906226fcbc88e3a0b194dde0c4cb2 Mon Sep 17 00:00:00 2001 From: Jam Balaya Date: Tue, 12 Aug 2025 22:27:41 +0900 Subject: [PATCH 04/93] chore(devcontainer): bump javascript-node image version (#1423) fix(devcontainer): bump javascript-node image version --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 096a3d095..db939da5b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,5 @@ { - "image": "mcr.microsoft.com/devcontainers/javascript-node:1-18", + "image": "mcr.microsoft.com/devcontainers/javascript-node:3-22", "features": { "ghcr.io/devcontainers/features/docker-in-docker:2": {} }, From 849a5e2a7fd2c8109531cec9e63bfde12472407a Mon Sep 17 00:00:00 2001 From: Danilo Hoffmann Date: Tue, 12 Aug 2025 16:53:56 +0200 Subject: [PATCH 05/93] [common-utils] use new ohmyzsh setting to disable auto update (#1424) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use new config to disable OhMyZsh auto update There's a new method: https://github.com/ohmyzsh/ohmyzsh/wiki/Settings#deprecated-settings * bump patch version * Remove `buster` from testing scenarios as it is EOL --------- Co-authored-by: Álvaro Rausell Guiard <33221237+AlvaroRausell@users.noreply.github.com> --- src/common-utils/devcontainer-feature.json | 2 +- src/common-utils/main.sh | 2 +- test/common-utils/buster.sh | 14 -------------- test/common-utils/scenarios.json | 7 ------- 4 files changed, 2 insertions(+), 23 deletions(-) delete mode 100755 test/common-utils/buster.sh diff --git a/src/common-utils/devcontainer-feature.json b/src/common-utils/devcontainer-feature.json index 82ddde046..14850232d 100644 --- a/src/common-utils/devcontainer-feature.json +++ b/src/common-utils/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "common-utils", - "version": "2.5.3", + "version": "2.5.4", "name": "Common Utilities", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/common-utils", "description": "Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-root user.", diff --git a/src/common-utils/main.sh b/src/common-utils/main.sh index abef18430..68abe58c8 100644 --- a/src/common-utils/main.sh +++ b/src/common-utils/main.sh @@ -558,7 +558,7 @@ if [ "${INSTALL_ZSH}" = "true" ]; then # Add devcontainer .zshrc template if [ "$INSTALL_OH_MY_ZSH_CONFIG" = "true" ]; then if ! [ -f "${template_path}" ] || ! grep -qF "$(head -n 1 "${template_path}")" "${user_rc_file}"; then - echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${user_rc_file} + echo -e "$(cat "${template_path}")\nzstyle ':omz:update' mode disabled" > ${user_rc_file} fi sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="devcontainers"/g' ${user_rc_file} fi diff --git a/test/common-utils/buster.sh b/test/common-utils/buster.sh deleted file mode 100755 index 9fd2f409f..000000000 --- a/test/common-utils/buster.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -set -e - -# Optional: Import test library -source dev-container-features-test-lib - -# Definition specific tests -. /etc/os-release -check "non-root user" test "$(whoami)" = "devcontainer" -check "distro" test "${VERSION_CODENAME}" = "buster" - -# Report result -reportResults \ No newline at end of file diff --git a/test/common-utils/scenarios.json b/test/common-utils/scenarios.json index 5a8ec87cd..ee138ca22 100644 --- a/test/common-utils/scenarios.json +++ b/test/common-utils/scenarios.json @@ -13,13 +13,6 @@ "common-utils": {} } }, - "buster": { - "image": "debian:buster", - "remoteUser": "devcontainer", - "features": { - "common-utils": {} - } - }, "bullseye": { "image": "debian:bullseye", "remoteUser": "devcontainer", From da45251310a057c03dbe08477fb43f91f574361f Mon Sep 17 00:00:00 2001 From: Sergey Katsubo Date: Thu, 28 Aug 2025 11:40:17 +0300 Subject: [PATCH 06/93] [docker] Add Debian Trixie to the docker-in-docker and docker-outside-of-docker distro lists (#1442) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Debian Trixie to the docker-* distro list * Grammar * Fix Microsoft signing keys for Debian Trixie in docker-* * Test docker installation on debian trixie * Handle possibly missing moby package in docker-outside-of-docker installation * Remove trixie test with `moby: true` --------- Co-authored-by: Álvaro Rausell Guiard <33221237+AlvaroRausell@users.noreply.github.com> --- src/docker-in-docker/devcontainer-feature.json | 2 +- src/docker-in-docker/install.sh | 16 ++++++++++------ .../devcontainer-feature.json | 2 +- src/docker-outside-of-docker/install.sh | 17 ++++++++++------- .../install_moby_on_debian_trixie.sh | 1 + .../install_on_debian_trixie.sh | 12 ++++++++++++ test/docker-in-docker/scenarios.json | 8 ++++++++ .../install_moby_on_debian_trixie.sh | 1 + .../install_on_debian_trixie.sh | 12 ++++++++++++ test/docker-outside-of-docker/scenarios.json | 8 ++++++++ 10 files changed, 64 insertions(+), 15 deletions(-) create mode 120000 test/docker-in-docker/install_moby_on_debian_trixie.sh create mode 100644 test/docker-in-docker/install_on_debian_trixie.sh create mode 120000 test/docker-outside-of-docker/install_moby_on_debian_trixie.sh create mode 100644 test/docker-outside-of-docker/install_on_debian_trixie.sh diff --git a/src/docker-in-docker/devcontainer-feature.json b/src/docker-in-docker/devcontainer-feature.json index e44f2d666..7194ba0e0 100644 --- a/src/docker-in-docker/devcontainer-feature.json +++ b/src/docker-in-docker/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "docker-in-docker", - "version": "2.12.2", + "version": "2.12.3", "name": "Docker (Docker-in-Docker)", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-in-docker", "description": "Create child containers *inside* a container, independent from the host's docker instance. Installs Docker extension in the container along with needed CLIs.", diff --git a/src/docker-in-docker/install.sh b/src/docker-in-docker/install.sh index b43a12918..bf60620f6 100755 --- a/src/docker-in-docker/install.sh +++ b/src/docker-in-docker/install.sh @@ -18,8 +18,9 @@ USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}" INSTALL_DOCKER_BUILDX="${INSTALLDOCKERBUILDX:-"true"}" INSTALL_DOCKER_COMPOSE_SWITCH="${INSTALLDOCKERCOMPOSESWITCH:-"true"}" MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" -DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal jammy noble" -DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal hirsute impish jammy noble" +MICROSOFT_GPG_KEYS_ROLLING_URI="https://packages.microsoft.com/keys/microsoft-rolling.asc" +DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="trixie bookworm buster bullseye bionic focal jammy noble" +DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="trixie bookworm buster bullseye bionic focal hirsute impish jammy noble" DISABLE_IP6_TABLES="${DISABLEIP6TABLES:-false}" # Default: Exit on any failure. @@ -198,14 +199,14 @@ architecture="$(dpkg --print-architecture)" if [ "${USE_MOBY}" = "true" ]; then if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution" - err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" + err "Supported distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" exit 1 fi echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'" else if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution" - err "Support distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" + err "Supported distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" exit 1 fi echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}'" @@ -233,7 +234,10 @@ if [ "${USE_MOBY}" = "true" ]; then cli_package_name="moby-cli" # Import key safely and import Microsoft apt repo - curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg + { + curl -sSL ${MICROSOFT_GPG_KEYS_URI} + curl -sSL ${MICROSOFT_GPG_KEYS_ROLLING_URI} + } | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list else # Name of licensed engine/cli @@ -305,7 +309,7 @@ else set -e if [ ${exit_code} -ne 0 ]; then - err "Packages for moby not available in OS ${ID} ${VERSION_CODENAME} (${architecture}). To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS version (eg: 'ubuntu-20.04')." + err "Packages for moby not available in OS ${ID} ${VERSION_CODENAME} (${architecture}). To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS version (eg: 'ubuntu-24.04')." exit 1 fi diff --git a/src/docker-outside-of-docker/devcontainer-feature.json b/src/docker-outside-of-docker/devcontainer-feature.json index 218df825f..bee1c8a57 100644 --- a/src/docker-outside-of-docker/devcontainer-feature.json +++ b/src/docker-outside-of-docker/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "docker-outside-of-docker", - "version": "1.6.3", + "version": "1.6.4", "name": "Docker (docker-outside-of-docker)", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-outside-of-docker", "description": "Re-use the host docker socket, adding the Docker CLI to a container. Feature invokes a script to enable using a forwarded Docker socket within a container to run Docker commands.", diff --git a/src/docker-outside-of-docker/install.sh b/src/docker-outside-of-docker/install.sh index 04e35db0f..d8da01979 100755 --- a/src/docker-outside-of-docker/install.sh +++ b/src/docker-outside-of-docker/install.sh @@ -18,10 +18,10 @@ TARGET_SOCKET="${TARGET_SOCKET:-"/var/run/docker.sock"}" USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}" INSTALL_DOCKER_BUILDX="${INSTALLDOCKERBUILDX:-"true"}" INSTALL_DOCKER_COMPOSE_SWITCH="${INSTALLDOCKERCOMPOSESWITCH:-"true"}" - MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" -DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal jammy noble plucky" -DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal hirsute impish jammy noble plucky" +MICROSOFT_GPG_KEYS_ROLLING_URI="https://packages.microsoft.com/keys/microsoft-rolling.asc" +DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="trixie bookworm buster bullseye bionic focal jammy noble plucky" +DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="trixie bookworm buster bullseye bionic focal hirsute impish jammy noble plucky" set -e @@ -205,14 +205,14 @@ architecture="$(dpkg --print-architecture)" if [ "${USE_MOBY}" = "true" ]; then if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution" - err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" + err "Supported distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" exit 1 fi echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'" else if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution" - err "Support distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" + err "Supported distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" exit 1 fi echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}'" @@ -224,7 +224,10 @@ if [ "${USE_MOBY}" = "true" ]; then cli_package_name="moby-cli" # Import key safely and import Microsoft apt repo - curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg + { + curl -sSL ${MICROSOFT_GPG_KEYS_URI} + curl -sSL ${MICROSOFT_GPG_KEYS_ROLLING_URI} + } | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list else # Name of proprietary engine package @@ -302,7 +305,7 @@ else if [ "${INSTALL_DOCKER_BUILDX}" = "true" ]; then buildx=(moby-buildx${buildx_version_suffix}) fi - apt-get -y install --no-install-recommends ${cli_package_name}${cli_version_suffix} "${buildx[@]}" + apt-get -y install --no-install-recommends ${cli_package_name}${cli_version_suffix} "${buildx[@]}" || { err "It seems packages for moby not available in OS ${ID} ${VERSION_CODENAME} (${architecture}). To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS version (eg: 'ubuntu-24.04')." ; exit 1 ; } apt-get -y install --no-install-recommends moby-compose || echo "(*) Package moby-compose (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping." else buildx=() diff --git a/test/docker-in-docker/install_moby_on_debian_trixie.sh b/test/docker-in-docker/install_moby_on_debian_trixie.sh new file mode 120000 index 000000000..6c5c2a157 --- /dev/null +++ b/test/docker-in-docker/install_moby_on_debian_trixie.sh @@ -0,0 +1 @@ +install_on_debian_trixie.sh \ No newline at end of file diff --git a/test/docker-in-docker/install_on_debian_trixie.sh b/test/docker-in-docker/install_on_debian_trixie.sh new file mode 100644 index 000000000..c6c679684 --- /dev/null +++ b/test/docker-in-docker/install_on_debian_trixie.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +# Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "docker installed" bash -c "type docker" + +# Report results +reportResults diff --git a/test/docker-in-docker/scenarios.json b/test/docker-in-docker/scenarios.json index 1587bda56..428909f8c 100644 --- a/test/docker-in-docker/scenarios.json +++ b/test/docker-in-docker/scenarios.json @@ -134,6 +134,14 @@ } } }, + "install_on_debian_trixie": { + "image": "debian:trixie", + "features": { + "docker-in-docker": { + "moby": false + } + } + }, "docker_specific_moby_buildx": { "image": "ubuntu:noble", "features": { diff --git a/test/docker-outside-of-docker/install_moby_on_debian_trixie.sh b/test/docker-outside-of-docker/install_moby_on_debian_trixie.sh new file mode 120000 index 000000000..6c5c2a157 --- /dev/null +++ b/test/docker-outside-of-docker/install_moby_on_debian_trixie.sh @@ -0,0 +1 @@ +install_on_debian_trixie.sh \ No newline at end of file diff --git a/test/docker-outside-of-docker/install_on_debian_trixie.sh b/test/docker-outside-of-docker/install_on_debian_trixie.sh new file mode 100644 index 000000000..c6c679684 --- /dev/null +++ b/test/docker-outside-of-docker/install_on_debian_trixie.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +# Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "docker installed" bash -c "type docker" + +# Report results +reportResults diff --git a/test/docker-outside-of-docker/scenarios.json b/test/docker-outside-of-docker/scenarios.json index 7125b4715..2163e7076 100644 --- a/test/docker-outside-of-docker/scenarios.json +++ b/test/docker-outside-of-docker/scenarios.json @@ -172,5 +172,13 @@ } }, "containerUser": "vscode" + }, + "install_on_debian_trixie": { + "image": "debian:trixie", + "features": { + "docker-outside-of-docker": { + "moby": false + } + } } } From c05bd451518d73c9658eb9a41db18aaa968b73f3 Mon Sep 17 00:00:00 2001 From: Kaniska Date: Mon, 1 Sep 2025 15:52:50 +0530 Subject: [PATCH 07/93] [ruby] - Fixing ruby feature installation issue in debian trixie(13) (#1453) * [ruby] - Making ruby feature work in debian trixie(13) * Restart test --- src/ruby/devcontainer-feature.json | 2 +- src/ruby/install.sh | 18 ++++++++++- test/ruby/install_additional_ruby_trixie.sh | 17 ++++++++++ test/ruby/install_ruby_trixie_base.sh | 15 +++++++++ test/ruby/install_ruby_trixie_base/Dockerfile | 18 +++++++++++ test/ruby/scenarios.json | 32 ++++++++++++++++++- 6 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 test/ruby/install_additional_ruby_trixie.sh create mode 100644 test/ruby/install_ruby_trixie_base.sh create mode 100644 test/ruby/install_ruby_trixie_base/Dockerfile diff --git a/src/ruby/devcontainer-feature.json b/src/ruby/devcontainer-feature.json index 82ae50a10..661c46bf0 100644 --- a/src/ruby/devcontainer-feature.json +++ b/src/ruby/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "ruby", - "version": "1.3.1", + "version": "1.3.2", "name": "Ruby (via rvm)", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/ruby", "description": "Installs Ruby, rvm, rbenv, common Ruby utilities, and needed dependencies.", diff --git a/src/ruby/install.sh b/src/ruby/install.sh index befeee4af..39cb5be03 100755 --- a/src/ruby/install.sh +++ b/src/ruby/install.sh @@ -240,13 +240,29 @@ if [ "${architecture}" != "amd64" ] && [ "${architecture}" != "x86_64" ] && [ "$ fi # Install dependencies -check_packages curl ca-certificates software-properties-common build-essential gnupg2 libreadline-dev \ +# Removed software-properties-common package from here as it has been removed for debian trixie(13) +check_packages curl ca-certificates build-essential gnupg2 libreadline-dev \ procps dirmngr gawk autoconf automake bison libffi-dev libgdbm-dev libncurses5-dev \ libsqlite3-dev libtool libyaml-dev pkg-config sqlite3 zlib1g-dev libgmp-dev libssl-dev if ! type git > /dev/null 2>&1; then check_packages git fi +# Conditionally install software-properties-common (skip on Debian Trixie) +if type apt-get >/dev/null 2>&1; then + if [ -f /etc/os-release ]; then + . /etc/os-release + if [ "${ID}" = "debian" ] && [ "${VERSION_CODENAME}" = "trixie" ]; then + echo "Skipping software-properties-common on Debian Trixie." + else + check_packages software-properties-common + fi + else + # Fallback for apt-based systems without /etc/os-release + check_packages software-properties-common + fi +fi + # Function to fetch the version released prior to the latest version get_previous_version() { local url=$1 diff --git a/test/ruby/install_additional_ruby_trixie.sh b/test/ruby/install_additional_ruby_trixie.sh new file mode 100644 index 000000000..76f7c9028 --- /dev/null +++ b/test/ruby/install_additional_ruby_trixie.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +check "ruby version 3.4.2 installed as default" ruby -v | grep 3.4.2 +check "ruby version 3.2.8 installed" rvm list | grep 3.2.8 +check "ruby version 3.3.2 installed" rvm list | grep 3.3.2 + +check "rbenv" bash -c 'eval "$(rbenv init -)" && rbenv --version' +check "rake" bash -c "gem list | grep rake" + +# Report result +reportResults + diff --git a/test/ruby/install_ruby_trixie_base.sh b/test/ruby/install_ruby_trixie_base.sh new file mode 100644 index 000000000..f90c76cc4 --- /dev/null +++ b/test/ruby/install_ruby_trixie_base.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "ruby version" ruby --version +check "rvm" rvm --version +check "gem version" gem --version + +# Report result +reportResults + diff --git a/test/ruby/install_ruby_trixie_base/Dockerfile b/test/ruby/install_ruby_trixie_base/Dockerfile new file mode 100644 index 000000000..e80891596 --- /dev/null +++ b/test/ruby/install_ruby_trixie_base/Dockerfile @@ -0,0 +1,18 @@ +# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.4, 3.3, 3.2, 3-bookworm, 3.4-bookworm, 3.3-bookworm, 3.2-bookworm, 3-bullseye, 3.4-bullseye, 3.3-bullseye, 3.2-bullseye, 3-buster, 3.2-buster +ARG VARIANT=3-trixie +FROM ruby:${VARIANT} + +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + # Remove imagemagick due to https://security-tracker.debian.org/tracker/CVE-2019-10131 + && apt-get purge -y imagemagick imagemagick-6-common + +# [Optional] Uncomment this section to install additional OS packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + +# [Optional] Uncomment this line to install additional gems. +# RUN gem install + +# [Optional] Uncomment this line to install global node packages. +# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 + diff --git a/test/ruby/scenarios.json b/test/ruby/scenarios.json index 7a13f7004..7aa7c5f8e 100644 --- a/test/ruby/scenarios.json +++ b/test/ruby/scenarios.json @@ -1,4 +1,34 @@ -{ +{ + "install_ruby_trixie_base": { + "build": { + "dockerfile": "Dockerfile" + }, + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": "true", + "username": "vscode", + "userUid": "1000", + "userGid": "1000", + "upgradePackages": "true" + }, + "ruby": "none", + "ghcr.io/devcontainers/features/node:1": "none", + "ghcr.io/devcontainers/features/git:1": { + "version": "latest", + "ppa": "false" + } + }, + "remoteUser": "vscode" + }, + "install_additional_ruby_trixie": { + "image": "debian:trixie", + "features": { + "ruby": { + "version": "3.4.2", + "additionalVersions": "3.2,3.3.2" + } + } + }, "install_additional_ruby": { "image": "ubuntu:noble", "features": { From 6a8863be0afc3a133dd1966d1b92b8eb34307950 Mon Sep 17 00:00:00 2001 From: Lingyu Zhou Date: Tue, 16 Sep 2025 11:24:20 -0400 Subject: [PATCH 08/93] [sshd] Add GatewayPorts option (#1464) add gatewayports option to sshd --- src/sshd/README.md | 1 + src/sshd/devcontainer-feature.json | 12 +++++++++++- src/sshd/install.sh | 2 ++ test/sshd/scenarios.json | 18 ++++++++++++++++++ test/sshd/sshd_with_default_gateway_ports.sh | 12 ++++++++++++ ...ith_pinned_gateway_ports_clientspecified.sh | 12 ++++++++++++ 6 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/sshd/scenarios.json create mode 100644 test/sshd/sshd_with_default_gateway_ports.sh create mode 100644 test/sshd/sshd_with_pinned_gateway_ports_clientspecified.sh diff --git a/src/sshd/README.md b/src/sshd/README.md index 7314e16af..f4215b391 100644 --- a/src/sshd/README.md +++ b/src/sshd/README.md @@ -15,6 +15,7 @@ Adds a SSH server into a container so that you can use an external terminal, sft | Options Id | Description | Type | Default Value | |-----|-----|-----|-----| +| gatewayPorts | Enable other hosts in the same network to connect to the forwarded ports | string | no | version | Currently unused. | string | latest | ## Usage diff --git a/src/sshd/devcontainer-feature.json b/src/sshd/devcontainer-feature.json index e400b0601..46c4ef302 100644 --- a/src/sshd/devcontainer-feature.json +++ b/src/sshd/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "sshd", - "version": "1.0.10", + "version": "1.1.0", "name": "SSH server", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/sshd", "description": "Adds a SSH server into a container so that you can use an external terminal, sftp, or SSHFS to interact with it.", @@ -12,6 +12,16 @@ ], "default": "latest", "description": "Currently unused." + }, + "gatewayPorts": { + "type": "string", + "enum": [ + "no", + "yes", + "clientspecified" + ], + "default": "no", + "description": "Enable other hosts in the same network to connect to the forwarded ports" } }, "entrypoint": "/usr/local/share/ssh-init.sh", diff --git a/src/sshd/install.sh b/src/sshd/install.sh index 146040896..9b9ddedf2 100755 --- a/src/sshd/install.sh +++ b/src/sshd/install.sh @@ -13,6 +13,7 @@ SSHD_PORT="${SSHD_PORT:-"2222"}" USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}" START_SSHD="${START_SSHD:-"false"}" NEW_PASSWORD="${NEW_PASSWORD:-"skip"}" +GATEWAY_PORTS="${GATEWAYPORTS:-"no"}" set -e @@ -89,6 +90,7 @@ mkdir -p /var/run/sshd sed -i 's/session\s*required\s*pam_loginuid\.so/session optional pam_loginuid.so/g' /etc/pam.d/sshd sed -i 's/#*PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config sed -i -E "s/#*\s*Port\s+.+/Port ${SSHD_PORT}/g" /etc/ssh/sshd_config +sed -i "s/#GatewayPorts no/GatewayPorts ${GATEWAY_PORTS}/g" /etc/ssh/sshd_config # Need to UsePAM so /etc/environment is processed sed -i -E "s/#?\s*UsePAM\s+.+/UsePAM yes/g" /etc/ssh/sshd_config diff --git a/test/sshd/scenarios.json b/test/sshd/scenarios.json new file mode 100644 index 000000000..1513f64f9 --- /dev/null +++ b/test/sshd/scenarios.json @@ -0,0 +1,18 @@ +{ + "sshd_with_default_gateway_ports": { + "image": "ubuntu:noble", + "features": { + "sshd": { + "gatewayPorts": "no" + } + } + }, + "sshd_with_pinned_gateway_ports_clientspecified": { + "image": "ubuntu:noble", + "features": { + "sshd": { + "gatewayPorts": "clientspecified" + } + } + } +} diff --git a/test/sshd/sshd_with_default_gateway_ports.sh b/test/sshd/sshd_with_default_gateway_ports.sh new file mode 100644 index 000000000..543074ad4 --- /dev/null +++ b/test/sshd/sshd_with_default_gateway_ports.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "correct default GatewayPorts" grep "GatewayPorts no" /etc/ssh/sshd_config + +# Report result +reportResults \ No newline at end of file diff --git a/test/sshd/sshd_with_pinned_gateway_ports_clientspecified.sh b/test/sshd/sshd_with_pinned_gateway_ports_clientspecified.sh new file mode 100644 index 000000000..58b7cb730 --- /dev/null +++ b/test/sshd/sshd_with_pinned_gateway_ports_clientspecified.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "correct default GatewayPorts" grep "GatewayPorts clientspecified" /etc/ssh/sshd_config + +# Report result +reportResults \ No newline at end of file From 787dd39806c4d5afdee8a66c4af4a6a9c08c1989 Mon Sep 17 00:00:00 2001 From: Kaniska Date: Tue, 16 Sep 2025 21:11:29 +0530 Subject: [PATCH 09/93] [terraform] - Fix terraform installation in debian trixie(13) (#1475) * [terraform] - Fix terraform installation in debian trixie(13) * Version bump --- src/terraform/devcontainer-feature.json | 2 +- src/terraform/install.sh | 22 +++++++++---------- test/terraform/install_in_ubuntu_trixie.sh | 19 ++++++++++++++++ .../install_in_ubuntu_trixie_sentinel.sh | 22 +++++++++++++++++++ test/terraform/scenarios.json | 16 ++++++++++++++ 5 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 test/terraform/install_in_ubuntu_trixie.sh create mode 100644 test/terraform/install_in_ubuntu_trixie_sentinel.sh diff --git a/src/terraform/devcontainer-feature.json b/src/terraform/devcontainer-feature.json index ceee4979e..a72f18993 100644 --- a/src/terraform/devcontainer-feature.json +++ b/src/terraform/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "terraform", - "version": "1.4.1", + "version": "1.4.2", "name": "Terraform, tflint, and TFGrunt", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/terraform", "description": "Installs the Terraform CLI and optionally TFLint and Terragrunt. Auto-detects latest version and installs needed dependencies.", diff --git a/src/terraform/install.sh b/src/terraform/install.sh index b1d64c27b..999815a38 100755 --- a/src/terraform/install.sh +++ b/src/terraform/install.sh @@ -19,6 +19,8 @@ INSTALL_SENTINEL=${INSTALLSENTINEL:-false} INSTALL_TFSEC=${INSTALLTFSEC:-false} INSTALL_TERRAFORM_DOCS=${INSTALLTERRAFORMDOCS:-false} CUSTOM_DOWNLOAD_SERVER="${CUSTOMDOWNLOADSERVER:-""}" +# This is because ubuntu noble and debian trixie don't support the old format of GPG keys and validation +NEW_GPG_CODENAMES="trixie noble" TERRAFORM_SHA256="${TERRAFORM_SHA256:-"automatic"}" TFLINT_SHA256="${TFLINT_SHA256:-"automatic"}" @@ -50,13 +52,11 @@ if [ "$(id -u)" -ne 0 ]; then exit 1 fi -# Detect Ubuntu Noble and use new repo setup, else use legacy GPG logic -IS_NOBLE=0 -if grep -qi 'ubuntu' /etc/os-release; then - . /etc/os-release - if [[ "$VERSION_CODENAME" == "noble" ]]; then - IS_NOBLE=1 - fi +# Detect Ubuntu Noble or Debian Trixie and use new repo setup, else use legacy GPG logic +IS_GPG_NEW=0 +. /etc/os-release +if [[ "${NEW_GPG_CODENAMES}" == *"${VERSION_CODENAME}"* ]]; then + IS_GPG_NEW=1 fi # Get the list of GPG key servers that are reachable @@ -112,7 +112,7 @@ receive_gpg_keys() { chmod 700 ${GNUPGHOME} # Special handling for HashiCorp GPG key on Ubuntu Noble - if [ "$IS_NOBLE" -eq 1 ] && [ "$keys" = "$TERRAFORM_GPG_KEY" ]; then + if [ "$IS_GPG_NEW" -eq 1 ] && [ "$keys" = "$TERRAFORM_GPG_KEY" ]; then echo "(*) Ubuntu Noble detected, using Keybase for HashiCorp GPG key import...." curl -fsSL https://keybase.io/hashicorp/pgp_keys.asc | gpg --import if ! gpg --list-keys "${TERRAFORM_GPG_KEY}" > /dev/null 2>&1; then @@ -400,7 +400,7 @@ verify_signature() { receive_gpg_keys "$gpg_key" verify_result=$? - if [ $verify_result -ne 0 ] && [ "$IS_NOBLE" -eq 1 ]; then + if [ $verify_result -ne 0 ] && [ "$IS_GPG_NEW" -eq 1 ]; then echo "Skipping the gpg key validation for ubuntu noble as unable to import the key." return 1 fi @@ -429,7 +429,7 @@ fi if [ "${TERRAFORM_SHA256}" != "dev-mode" ]; then if [ "${TERRAFORM_SHA256}" = "automatic" ]; then # For Ubuntu Noble, try GPG verification but continue if it fails - if [ "$IS_NOBLE" -eq 1 ]; then + if [ "$IS_GPG_NEW" -eq 1 ]; then echo "(*) Ubuntu Noble detected - attempting GPG verification with fallback..." set +e sha256sums_url="${HASHICORP_RELEASES_URL}/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS" @@ -543,7 +543,7 @@ if [ "${INSTALL_SENTINEL}" = "true" ]; then if [ "${SENTINEL_SHA256}" != "dev-mode" ]; then if [ "${SENTINEL_SHA256}" = "automatic" ]; then # For Ubuntu Noble, try GPG verification but continue if it fails - if [ "$IS_NOBLE" -eq 1 ]; then + if [ "$IS_GPG_NEW" -eq 1 ]; then echo "(*) Ubuntu Noble detected - attempting Sentinel GPG verification with fallback..." set +e sha256sums_url="${sentinel_releases_url}/${SENTINEL_VERSION}/sentinel_${SENTINEL_VERSION}_SHA256SUMS" diff --git a/test/terraform/install_in_ubuntu_trixie.sh b/test/terraform/install_in_ubuntu_trixie.sh new file mode 100644 index 000000000..9b03a3a60 --- /dev/null +++ b/test/terraform/install_in_ubuntu_trixie.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +# Import test library +source dev-container-features-test-lib + +# Check to make sure the user is vscode +check "user is vscode" whoami | grep vscode + +# Check if terraform was installed correctly +check "terraform installed" terraform --version + +check "tflint" tflint --version + +# Report results +reportResults + + diff --git a/test/terraform/install_in_ubuntu_trixie_sentinel.sh b/test/terraform/install_in_ubuntu_trixie_sentinel.sh new file mode 100644 index 000000000..467106785 --- /dev/null +++ b/test/terraform/install_in_ubuntu_trixie_sentinel.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +# Import test library for `check` command +source dev-container-features-test-lib + +# Check to make sure the user is vscode +check "user is vscode" whoami | grep vscode + +# Check if terraform was installed correctly +check "terraform installed" terraform --version + +check "tflint" tflint --version + +# Sentinel specific tests +check "sentinel" sentinel --version + +# Report result +reportResults + + diff --git a/test/terraform/scenarios.json b/test/terraform/scenarios.json index 81945d042..09bb0f598 100644 --- a/test/terraform/scenarios.json +++ b/test/terraform/scenarios.json @@ -1,4 +1,20 @@ { + "install_in_ubuntu_trixie": { + "image": "mcr.microsoft.com/devcontainers/base:trixie", + "features": { + "terraform": { + "version": "latest" + } + } + }, + "install_in_ubuntu_trixie_sentinel": { + "image": "mcr.microsoft.com/devcontainers/base:trixie", + "features": { + "terraform": { + "installSentinel": true + } + } + }, "install_in_ubuntu_noble": { "image": "mcr.microsoft.com/devcontainers/base:noble", "features": { From 0a82ddbc5e22a7648b81e1470ac0833b8c4834ef Mon Sep 17 00:00:00 2001 From: Kaniska Date: Tue, 16 Sep 2025 21:13:39 +0530 Subject: [PATCH 10/93] [azure-cli] - Fix azure-cli installation in debian trixie(13) (#1476) --- src/azure-cli/devcontainer-feature.json | 2 +- src/azure-cli/install.sh | 2 +- test/azure-cli/install_bicep_trixie.sh | 19 ++++++++++++ test/azure-cli/install_extensions_trixie.sh | 9 ++++++ .../install_with_python_3_13_trixie.sh | 22 ++++++++++++++ test/azure-cli/scenarios.json | 30 +++++++++++++++++++ 6 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 test/azure-cli/install_bicep_trixie.sh create mode 100644 test/azure-cli/install_extensions_trixie.sh create mode 100644 test/azure-cli/install_with_python_3_13_trixie.sh diff --git a/src/azure-cli/devcontainer-feature.json b/src/azure-cli/devcontainer-feature.json index 3b731a6b3..3bc905f47 100644 --- a/src/azure-cli/devcontainer-feature.json +++ b/src/azure-cli/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "azure-cli", - "version": "1.2.7", + "version": "1.2.8", "name": "Azure CLI", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/azure-cli", "description": "Installs the Azure CLI along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg.", diff --git a/src/azure-cli/install.sh b/src/azure-cli/install.sh index 93e10ff52..171c24510 100755 --- a/src/azure-cli/install.sh +++ b/src/azure-cli/install.sh @@ -19,7 +19,7 @@ AZ_BICEPVERSION=${BICEPVERSION:-latest} INSTALL_USING_PYTHON=${INSTALLUSINGPYTHON:-false} MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" AZCLI_ARCHIVE_ARCHITECTURES="amd64 arm64" -AZCLI_ARCHIVE_VERSION_CODENAMES="stretch bookworm buster bullseye bionic focal jammy noble" +AZCLI_ARCHIVE_VERSION_CODENAMES="stretch bookworm buster bullseye bionic focal jammy noble trixie" if [ "$(id -u)" -ne 0 ]; then echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' diff --git a/test/azure-cli/install_bicep_trixie.sh b/test/azure-cli/install_bicep_trixie.sh new file mode 100644 index 000000000..28ff7e509 --- /dev/null +++ b/test/azure-cli/install_bicep_trixie.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +# Import test library for `check` command +source dev-container-features-test-lib + +# Check to make sure the user is vscode +check "user is vscode" whoami | grep vscode + +check "version" az --version + +# Bicep-specific tests +check "bicep" bicep --version +check "az bicep" az bicep version + +# Report result +reportResults + diff --git a/test/azure-cli/install_extensions_trixie.sh b/test/azure-cli/install_extensions_trixie.sh new file mode 100644 index 000000000..fa55c2f5d --- /dev/null +++ b/test/azure-cli/install_extensions_trixie.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +# Import test library for `check` command +source dev-container-features-test-lib + +./install_extensions.sh + diff --git a/test/azure-cli/install_with_python_3_13_trixie.sh b/test/azure-cli/install_with_python_3_13_trixie.sh new file mode 100644 index 000000000..aac4f3c2d --- /dev/null +++ b/test/azure-cli/install_with_python_3_13_trixie.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +# Import test library for `check` command +source dev-container-features-test-lib + + +echo -e "\n🔄 Testing 'O.S'" +if cat /etc/os-release | grep -q 'PRETTY_NAME="Debian GNU/Linux 13 (trixie)"'; then + echo -e "\n✅ Passed 'O.S is Linux 13 (trixie)'!\n" +else + echo -e "\n❌ Failed 'O.S is other than Linux 13 (trixie)'!\n" +fi + +# Check to make sure the user is vscode +check "user is vscode" whoami | grep vscode +check "version" az --version + +# Report result +reportResults + diff --git a/test/azure-cli/scenarios.json b/test/azure-cli/scenarios.json index 3ec910399..c3a205e68 100644 --- a/test/azure-cli/scenarios.json +++ b/test/azure-cli/scenarios.json @@ -1,4 +1,14 @@ { + "install_extensions_trixie": { + "image": "mcr.microsoft.com/devcontainers/base:trixie", + "user": "vscode", + "features": { + "azure-cli": { + "version": "latest", + "extensions": "aks-preview,amg,containerapp" + } + } + }, "install_extensions": { "image": "mcr.microsoft.com/devcontainers/base:jammy", "user": "vscode", @@ -28,6 +38,16 @@ "installBicep": true } } + }, + "install_bicep_trixie": { + "image": "mcr.microsoft.com/devcontainers/base:trixie", + "user": "vscode", + "features": { + "azure-cli": { + "version": "latest", + "installBicep": true + } + } }, "install_with_python": { "image": "mcr.microsoft.com/devcontainers/base:jammy", @@ -39,6 +59,16 @@ } } }, + "install_with_python_3_13_trixie": { + "image": "mcr.microsoft.com/devcontainers/python:2-3.13-trixie", + "user": "vscode", + "features": { + "azure-cli": { + "version": "latest", + "installUsingPython": true + } + } + }, "install_with_python_3_12_bookworm": { "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bookworm", "user": "vscode", From 572770d2c3a40ef13821bff8ec7238e709ce5bae Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 16 Sep 2025 17:45:37 +0200 Subject: [PATCH 11/93] dotnet: add support for prerelease versions (#1470) * dotnet: add support for prerelease versions * Add 'additionalVersions' tests * Improve handling of empty 'channel' and 'quality' values * Fix invalid version spec in aspnetCoreRuntimeVersions --- src/dotnet/NOTES.md | 16 ++- src/dotnet/devcontainer-feature.json | 13 ++- src/dotnet/install.sh | 20 +++- src/dotnet/scripts/dotnet-helpers.sh | 94 +++++++++++++--- src/dotnet/scripts/vendor/dotnet-install.sh | 105 +++--------------- test/dotnet/install_dotnet_daily.sh | 22 ++++ ...nstall_dotnet_multiple_versions_preview.sh | 47 -------- test/dotnet/install_dotnet_preview.sh | 22 ++++ test/dotnet/scenarios.json | 28 +++-- 9 files changed, 194 insertions(+), 173 deletions(-) create mode 100644 test/dotnet/install_dotnet_daily.sh delete mode 100644 test/dotnet/install_dotnet_multiple_versions_preview.sh create mode 100644 test/dotnet/install_dotnet_preview.sh diff --git a/src/dotnet/NOTES.md b/src/dotnet/NOTES.md index 584c90cef..ff52835b0 100644 --- a/src/dotnet/NOTES.md +++ b/src/dotnet/NOTES.md @@ -10,9 +10,10 @@ Installing only the latest .NET SDK version (the default). Installing an additional SDK version. Multiple versions can be specified as comma-separated values. -``` json +``` jsonc "features": { "ghcr.io/devcontainers/features/dotnet:2": { + "version": "latest", // (this can be omitted) "additionalVersions": "lts" } } @@ -71,6 +72,19 @@ Installing .NET workloads. Multiple workloads can be specified as comma-separate } ``` +Installing prerelease builds. Supports `preview` and `daily` suffixes. + +``` json +"features": { + "ghcr.io/devcontainers/features/dotnet:2": { + "version": "10.0-preview", + "additionalVersions": "10.0.1xx-daily", + "dotnetRuntimeVersions": "10.0-daily", + "aspnetCoreRuntimeVersions": "10.0-daily" + } +} +``` + ## OS Support This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed. diff --git a/src/dotnet/devcontainer-feature.json b/src/dotnet/devcontainer-feature.json index 397f9a191..9389addaa 100644 --- a/src/dotnet/devcontainer-feature.json +++ b/src/dotnet/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "dotnet", - "version": "2.3.0", + "version": "2.4.0", "name": "Dotnet CLI", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/dotnet", "description": "This Feature installs the latest .NET SDK, which includes the .NET CLI and the shared runtime. Options are provided to choose a different version or additional versions.", @@ -11,28 +11,31 @@ "latest", "lts", "none", + "10.0", "10.0-preview", + "10.0-daily", + "9.0", "8.0", "7.0", "6.0" ], "default": "latest", - "description": "Select or enter a .NET SDK version. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version." + "description": "Select or enter a .NET SDK version. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases." }, "additionalVersions": { "type": "string", "default": "", - "description": "Enter additional .NET SDK versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version." + "description": "Enter additional .NET SDK versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases." }, "dotnetRuntimeVersions": { "type": "string", "default": "", - "description": "Enter additional .NET runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version." + "description": "Enter additional .NET runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases." }, "aspNetCoreRuntimeVersions": { "type": "string", "default": "", - "description": "Enter additional ASP.NET Core runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version." + "description": "Enter additional ASP.NET Core runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases." }, "workloads": { "type": "string", diff --git a/src/dotnet/install.sh b/src/dotnet/install.sh index 75f013d03..bd85fb91a 100644 --- a/src/dotnet/install.sh +++ b/src/dotnet/install.sh @@ -108,17 +108,27 @@ done check_packages wget ca-certificates icu-devtools for version in "${versions[@]}"; do - # Remove '-preview' from version if suffixed with the version label - clean_version="$(echo "$version" | sed 's/-preview$//')" - install_sdk "$clean_version" + read -r clean_version quality < <(parse_version_and_quality "$version") + if [ -n "$quality" ]; then + echo "Interpreting requested version '$version' as version '$clean_version' with quality '$quality'" + fi + install_sdk "$clean_version" "$quality" done for version in "${dotnetRuntimeVersions[@]}"; do - install_runtime "dotnet" "$version" + read -r clean_version quality < <(parse_version_and_quality "$version") + if [ -n "$quality" ]; then + echo "Interpreting requested runtime version '$version' as version '$clean_version' with quality '$quality'" + fi + install_runtime "dotnet" "$clean_version" "$quality" done for version in "${aspNetCoreRuntimeVersions[@]}"; do - install_runtime "aspnetcore" "$version" + read -r clean_version quality < <(parse_version_and_quality "$version") + if [ -n "$quality" ]; then + echo "Interpreting requested ASP.NET Core runtime version '$version' as version '$clean_version' with quality '$quality'" + fi + install_runtime "aspnetcore" "$clean_version" "$quality" done workloads=() diff --git a/src/dotnet/scripts/dotnet-helpers.sh b/src/dotnet/scripts/dotnet-helpers.sh index 84a674917..2ef8796eb 100644 --- a/src/dotnet/scripts/dotnet-helpers.sh +++ b/src/dotnet/scripts/dotnet-helpers.sh @@ -45,9 +45,12 @@ fetch_latest_version() { } # Installs a version of the .NET SDK -# Usage: install_sdk +# Usage: install_sdk [] +# Example: install_sdk "9.0" +# Example: install_sdk "10.0" "preview" install_sdk() { - local inputVersion="$1" + local inputVersion="$1" # Could be 'latest', 'lts', 'X.Y', 'X.Y.Z', 'X.Y.4xx', or base channel when paired with quality + local quality="$2" # Optional quality: GA, preview, daily (empty implies GA) local version="" local channel="" if [[ "$inputVersion" == "latest" ]]; then @@ -73,19 +76,25 @@ install_sdk() { version="$inputVersion" fi - # Currently this script does not make it possible to qualify the version, 'GA' is always implied - echo "Executing $DOTNET_INSTALL_SCRIPT --version $version --channel $channel --install-dir $DOTNET_ROOT" - "$DOTNET_INSTALL_SCRIPT" \ - --version "$version" \ - --channel "$channel" \ - --install-dir "$DOTNET_ROOT" + local cmd=("$DOTNET_INSTALL_SCRIPT" "--version" "$version" "--install-dir" "$DOTNET_ROOT") + if [ -n "$channel" ]; then + cmd+=("--channel" "$channel") + fi + if [ -n "$quality" ]; then + cmd+=("--quality" "$quality") + fi + echo "Executing ${cmd[*]}" + "${cmd[@]}" } # Installs a version of the .NET Runtime -# Usage: install_runtime +# Usage: install_runtime [] +# Example: install_runtime "dotnet" "9.0" +# Example: install_runtime "aspnetcore" "10.0" "preview" install_runtime() { local runtime="$1" - local inputVersion="$2" + local inputVersion="$2" # Could be 'latest', 'lts', 'X.Y', 'X.Y.Z' + local quality="$3" # Optional quality: GA, preview, daily (empty implies GA) local version="" local channel="" if [[ "$inputVersion" == "latest" ]]; then @@ -105,14 +114,16 @@ install_runtime() { # Assume version is an exact version string like '6.0.21' or '8.0.0-preview.7.23375.6' version="$inputVersion" fi - - echo "Executing $DOTNET_INSTALL_SCRIPT --runtime $runtime --version $version --channel $channel --install-dir $DOTNET_ROOT --no-path" - "$DOTNET_INSTALL_SCRIPT" \ - --runtime "$runtime" \ - --version "$version" \ - --channel "$channel" \ - --install-dir "$DOTNET_ROOT" \ - --no-path + + local cmd=("$DOTNET_INSTALL_SCRIPT" "--runtime" "$runtime" "--version" "$version" "--install-dir" "$DOTNET_ROOT" "--no-path") + if [ -n "$channel" ]; then + cmd+=("--channel" "$channel") + fi + if [ -n "$quality" ]; then + cmd+=("--quality" "$quality") + fi + echo "Executing ${cmd[*]}" + "${cmd[@]}" } # Installs one or more .NET workloads @@ -127,3 +138,50 @@ install_workloads() { # Clean up rm -r /tmp/dotnet-workload-temp-dir } + +# Input: version spec possibly containing -preview or -daily +# Supports channels in the forms: +# A.B (e.g. 10.0) +# A.B.Cxx (feature band e.g. 6.0.4xx) +# A.B-preview (adds quality) +# A.B-daily +# A.B.Cxx-preview +# A.B.Cxx-daily +# Output (stdout): " " +# - For channel specs (A.B or A.B.Cxx) without suffix -> quality is GA +# - For channel specs with -preview/-daily suffix -> quality is preview/daily +# - For exact version specs (contain a third numeric segment or prerelease labels beyond channel patterns, e.g. 8.0.100-rc.2.23502.2) -> quality is empty +# Examples: +# parse_version_and_quality "10.0-preview" => "10.0 preview" +# parse_version_and_quality "10.0-daily" => "10.0 daily" +# parse_version_and_quality "10.0" => "10.0 GA" +# parse_version_and_quality "6.0.4xx" => "6.0.4xx GA" +# parse_version_and_quality "6.0.4xx-preview" => "6.0.4xx preview" +# parse_version_and_quality "6.0.4xx-daily" => "6.0.4xx daily" +parse_version_and_quality() { + local input="$1" + local quality="" + local clean_version="$input" + # Match feature band with quality + if [[ "$input" =~ ^([0-9]+\.[0-9]+\.[0-9]xx)-(preview|daily)$ ]]; then + clean_version="${BASH_REMATCH[1]}" + quality="${BASH_REMATCH[2]}" + # Match simple channel with quality + elif [[ "$input" =~ ^([0-9]+\.[0-9]+)-(preview|daily)$ ]]; then + clean_version="${BASH_REMATCH[1]}" + quality="${BASH_REMATCH[2]}" + # Match plain feature band channel (defaults to GA) + elif [[ "$input" =~ ^[0-9]+\.[0-9]+\.[0-9]xx$ ]]; then + clean_version="$input" + quality="GA" + # Match simple channel (defaults to GA) + elif [[ "$input" =~ ^[0-9]+\.[0-9]+$ ]]; then + clean_version="$input" + quality="GA" + else + # Exact version (leave quality empty) + clean_version="$input" + quality="" + fi + echo "$clean_version" "$quality" +} \ No newline at end of file diff --git a/src/dotnet/scripts/vendor/dotnet-install.sh b/src/dotnet/scripts/vendor/dotnet-install.sh index 122ee68ed..034d2dfb1 100755 --- a/src/dotnet/scripts/vendor/dotnet-install.sh +++ b/src/dotnet/scripts/vendor/dotnet-install.sh @@ -477,7 +477,7 @@ get_normalized_quality() { local quality="$(to_lowercase "$1")" if [ ! -z "$quality" ]; then case "$quality" in - daily | signed | validated | preview) + daily | preview) echo "$quality" return 0 ;; @@ -486,7 +486,7 @@ get_normalized_quality() { return 0 ;; *) - say_err "'$quality' is not a supported value for --quality option. Supported values are: daily, signed, validated, preview, ga. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues." + say_err "'$quality' is not a supported value for --quality option. Supported values are: daily, preview, ga. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues." return 1 ;; esac @@ -1198,13 +1198,19 @@ downloadcurl() { local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs " local curl_exit_code=0; if [ -z "$out_path" ]; then - curl $curl_options "$remote_path_with_credential" 2>&1 + curl_output=$(curl $curl_options "$remote_path_with_credential" 2>&1) curl_exit_code=$? + echo "$curl_output" else - curl $curl_options -o "$out_path" "$remote_path_with_credential" 2>&1 + curl_output=$(curl $curl_options -o "$out_path" "$remote_path_with_credential" 2>&1) curl_exit_code=$? fi - + + # Regression in curl causes curl with --retry to return a 0 exit code even when it fails to download a file - https://github.com/curl/curl/issues/17554 + if [ $curl_exit_code -eq 0 ] && echo "$curl_output" | grep -q "^curl: ([0-9]*) "; then + curl_exit_code=$(echo "$curl_output" | sed 's/curl: (\([0-9]*\)).*/\1/') + fi + if [ $curl_exit_code -gt 0 ]; then download_error_msg="Unable to download $remote_path." # Check for curl timeout codes @@ -1272,61 +1278,6 @@ downloadwget() { return 0 } -extract_stem() { - local url="$1" - # extract the protocol - proto="$(echo $1 | grep :// | sed -e's,^\(.*://\).*,\1,g')" - # remove the protocol - url="${1/$proto/}" - # extract the path (if any) - since we know all of our feeds have a first path segment, we can skip the first one. otherwise we'd use -f2- to get the full path - full_path="$(echo $url | grep / | cut -d/ -f2-)" - path="$(echo $full_path | cut -d/ -f2-)" - echo $path -} - -check_url_exists() { - eval $invocation - local url="$1" - - local code="" - if machine_has "curl" - then - code=$(curl --head -o /dev/null -w "%{http_code}" -s --fail "$url"); - elif machine_has "wget" - then - # get the http response, grab the status code - server_response=$(wget -qO- --method=HEAD --server-response "$url" 2>&1) - code=$(echo "$server_response" | grep "HTTP/" | awk '{print $2}') - fi - if [ $code = "200" ]; then - return 0 - else - return 1 - fi -} - -sanitize_redirect_url() { - eval $invocation - - local url_stem - url_stem=$(extract_stem "$1") - say_verbose "Checking configured feeds for the asset at ${yellow:-}$url_stem${normal:-}" - - for feed in "${feeds[@]}" - do - local trial_url="$feed/$url_stem" - say_verbose "Checking ${yellow:-}$trial_url${normal:-}" - if check_url_exists "$trial_url"; then - say_verbose "Found a match at ${yellow:-}$trial_url${normal:-}" - echo "$trial_url" - return 0 - else - say_verbose "No match at ${yellow:-}$trial_url${normal:-}" - fi - done - return 1 -} - get_download_link_from_aka_ms() { eval $invocation @@ -1379,11 +1330,6 @@ get_download_link_from_aka_ms() { return 1 fi - sanitized_redirect_url=$(sanitize_redirect_url "$aka_ms_download_link") - if [[ -n "$sanitized_redirect_url" ]]; then - aka_ms_download_link="$sanitized_redirect_url" - fi - say_verbose "The redirect location retrieved: '$aka_ms_download_link'." return 0 else @@ -1396,24 +1342,15 @@ get_feeds_to_use() { feeds=( "https://builds.dotnet.microsoft.com/dotnet" - "https://dotnetcli.azureedge.net/dotnet" "https://ci.dot.net/public" - "https://dotnetbuilds.azureedge.net/public" ) if [[ -n "$azure_feed" ]]; then feeds=("$azure_feed") fi - if [[ "$no_cdn" == "true" ]]; then - feeds=( - "https://dotnetcli.blob.core.windows.net/dotnet" - "https://dotnetbuilds.blob.core.windows.net/public" - ) - - if [[ -n "$uncached_feed" ]]; then - feeds=("$uncached_feed") - fi + if [[ -n "$uncached_feed" ]]; then + feeds=("$uncached_feed") fi } @@ -1545,7 +1482,7 @@ generate_regular_links() { link_types+=("legacy") else legacy_download_link="" - say_verbose "Cound not construct a legacy_download_link; omitting..." + say_verbose "Could not construct a legacy_download_link; omitting..." fi # Check if the SDK version is already installed. @@ -1648,7 +1585,7 @@ install_dotnet() { say "The resource at $link_type link '$download_link' is not available." ;; *) - say "Failed to download $link_type link '$download_link': $download_error_msg" + say "Failed to download $link_type link '$download_link': $http_code $download_error_msg" ;; esac rm -f "$zip_path" 2>&1 && say_verbose "Temporary archive file $zip_path was removed" @@ -1709,7 +1646,6 @@ install_dir="" architecture="" dry_run=false no_path=false -no_cdn=false azure_feed="" uncached_feed="" feed_credential="" @@ -1782,10 +1718,6 @@ do verbose=true non_dynamic_parameters+=" $name" ;; - --no-cdn|-[Nn]o[Cc]dn) - no_cdn=true - non_dynamic_parameters+=" $name" - ;; --azure-feed|-[Aa]zure[Ff]eed) shift azure_feed="$1" @@ -1862,7 +1794,7 @@ do echo " examples: 2.0.0-preview2-006120; 1.1.0" echo " -q,--quality Download the latest build of specified quality in the channel." echo " -Quality" - echo " The possible values are: daily, signed, validated, preview, GA." + echo " The possible values are: daily, preview, GA." echo " Works only in combination with channel. Not applicable for STS and LTS channels and will be ignored if those channels are used." echo " For SDK use channel in A.B.Cxx format. Using quality for SDK together with channel in A.B format is not supported." echo " Supported since 5.0 release." @@ -1890,13 +1822,10 @@ do echo " --verbose,-Verbose Display diagnostics information." echo " --azure-feed,-AzureFeed For internal use only." echo " Allows using a different storage to download SDK archives from." - echo " This parameter is only used if --no-cdn is false." echo " --uncached-feed,-UncachedFeed For internal use only." echo " Allows using a different storage to download SDK archives from." - echo " This parameter is only used if --no-cdn is true." echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable." echo " -SkipNonVersionedFiles" - echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly." echo " --jsonfile Determines the SDK version from a user specified global.json file." echo " Note: global.json must have a value for 'SDK:Version'" echo " --keep-zip,-KeepZip If set, downloaded file is kept." @@ -1956,4 +1885,4 @@ fi say "Note that the script does not resolve dependencies during installation." say "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section." -say "Installation finished successfully." \ No newline at end of file +say "Installation finished successfully." diff --git a/test/dotnet/install_dotnet_daily.sh b/test/dotnet/install_dotnet_daily.sh new file mode 100644 index 000000000..52f4f8d1b --- /dev/null +++ b/test/dotnet/install_dotnet_daily.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +source dev-container-features-test-lib +source dotnet_env.sh +source dotnet_helpers.sh + +# Verify 10.0 SDK (any prerelease containing '10.0') is installed +check ".NET SDK 10.0 installed" \ +is_dotnet_sdk_version_installed "10.0" + +check ".NET Runtime 10.0 installed" \ +is_dotnet_runtime_version_installed "10.0" + +check "ASP.NET Core Runtime 10.0 installed" \ +is_aspnetcore_runtime_version_installed "10.0" + +check "Build and run .NET 10.0 project" \ +dotnet run --project projects/net10.0 + +reportResults diff --git a/test/dotnet/install_dotnet_multiple_versions_preview.sh b/test/dotnet/install_dotnet_multiple_versions_preview.sh deleted file mode 100644 index 76bfd1ae3..000000000 --- a/test/dotnet/install_dotnet_multiple_versions_preview.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -set -e - -# Optional: Import test library bundled with the devcontainer CLI -# See https://github.com/devcontainers/cli/blob/HEAD/docs/features/test.md#dev-container-features-test-lib -# Provides the 'check' and 'reportResults' commands. -source dev-container-features-test-lib - -# Feature-specific tests -# The 'check' command comes from the dev-container-features-test-lib. Syntax is... -# check