From da45251310a057c03dbe08477fb43f91f574361f Mon Sep 17 00:00:00 2001 From: Sergey Katsubo Date: Thu, 28 Aug 2025 11:40:17 +0300 Subject: [PATCH 01/90] [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 02/90] [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 03/90] [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 04/90] [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 05/90] [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 06/90] 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