From 40aeb53ad77842bc30c9a1adb9ad28a41b753153 Mon Sep 17 00:00:00 2001 From: Venkumahanti Subhankar Date: Tue, 28 Jul 2026 15:49:25 +0530 Subject: [PATCH 1/3] docs(node): document pre-bundled items and how to opt out (#1695) * docs(node): document pre-bundled items and how to opt out Added notes on excluding pre-bundled items and VS Code extensions. * Fix formatting in NOTES.md Corrected formatting and punctuation in the NOTES.md file. * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/node/NOTES.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/node/NOTES.md b/src/node/NOTES.md index 506fa1b4e..9f1c1d3bc 100644 --- a/src/node/NOTES.md +++ b/src/node/NOTES.md @@ -25,3 +25,27 @@ Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, and Rocky Linux distributi **Note**: RedHat 7 Family (RedHat, CentOS, etc.) must use Node versions less than 18 due to its system libraries and long-term support (LTS) policies. `bash` is required to execute the `install.sh` script. + +## Pre-bundled items + +> [!NOTE] +> Beyond the core install, this feature also sets up a few items by default for convenience — recommended VS Code extensions (such as a linter) and supporting tools. This is intentional behavior shared across features in this repository. + +## Excluding pre-bundled items + +Exclude a bundled **VS Code extension** by prefixing its ID with `-`, or (when supported by a feature option) disable a bundled **tool** by setting its version option to `none` (for example, `pnpmVersion`: `none`): + +```json +{ + "features": { + "ghcr.io/devcontainers/features/node:2": { + "pnpmVersion": "none" + } + }, + "customizations": { + "vscode": { + "extensions": [ "-dbaeumer.vscode-eslint" ] + } + } +} +``` From 529a88d08e10671b5e61c48ade6904a02b867779 Mon Sep 17 00:00:00 2001 From: Venkumahanti Subhankar Date: Tue, 28 Jul 2026 15:51:09 +0530 Subject: [PATCH 2/3] fix(nix): Resolve PATH mismatch for packages option in multi-user mode (#1691) * fix(nix): Resolve PATH mismatch for packages option in multi-user mode * fix(nix): align package installs with the active multi-user profile --- src/nix/install.sh | 6 ++---- src/nix/post-install-steps.sh | 14 +++++++++++--- test/nix/packages.sh | 1 + test/nix/scenarios.json | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/nix/install.sh b/src/nix/install.sh index 0030c2b18..ca19f658a 100755 --- a/src/nix/install.sh +++ b/src/nix/install.sh @@ -113,10 +113,8 @@ fi chmod +x,o+r ${FEATURE_DIR} ${FEATURE_DIR}/post-install-steps.sh if [ "${MULTIUSER}" = "true" ]; then /usr/local/share/nix-entrypoint.sh - su ${USERNAME} -c " - . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh - ${FEATURE_DIR}/post-install-steps.sh - " + . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh + NIX_FEATURE_INSTALL_PROFILE=/nix/var/nix/profiles/default ${FEATURE_DIR}/post-install-steps.sh else su ${USERNAME} -c " . \$HOME/.nix-profile/etc/profile.d/nix.sh diff --git a/src/nix/post-install-steps.sh b/src/nix/post-install-steps.sh index 68f93a391..94cfed8a3 100755 --- a/src/nix/post-install-steps.sh +++ b/src/nix/post-install-steps.sh @@ -2,6 +2,14 @@ set -e echo "(*) Executing post-installation steps..." +# In multi-user mode, install into the default profile that is on PATH. +NIX_ENV_PROFILE_ARGS=() +NIX_PROFILE_INSTALL_ARGS=() +if [ -n "${NIX_FEATURE_INSTALL_PROFILE}" ]; then + NIX_ENV_PROFILE_ARGS=(-p "${NIX_FEATURE_INSTALL_PROFILE}") + NIX_PROFILE_INSTALL_ARGS=(--profile "${NIX_FEATURE_INSTALL_PROFILE}") +fi + # if not starts with "nixpkgs." add it as prefix to package name add_nixpkgs_prefix() { local packages=$1 @@ -20,17 +28,17 @@ if [ ! -z "${PACKAGES}" ] && [ "${PACKAGES}" != "none" ]; then if [ "${USEATTRIBUTEPATH}" = "true" ]; then PACKAGES=$(add_nixpkgs_prefix "$PACKAGES") echo "Installing packages \"${PACKAGES}\" in profile..." - nix-env -iA ${PACKAGES} + nix-env "${NIX_ENV_PROFILE_ARGS[@]}" -iA ${PACKAGES} else echo "Installing packages \"${PACKAGES}\" in profile..." - nix-env --install ${PACKAGES} + nix-env "${NIX_ENV_PROFILE_ARGS[@]}" --install ${PACKAGES} fi fi # Install Nix flake in profile if specified if [ ! -z "${FLAKEURI}" ] && [ "${FLAKEURI}" != "none" ]; then echo "Installing flake ${FLAKEURI} in profile..." - nix profile install "${FLAKEURI}" + nix profile install "${NIX_PROFILE_INSTALL_ARGS[@]}" "${FLAKEURI}" fi nix-collect-garbage --delete-old diff --git a/test/nix/packages.sh b/test/nix/packages.sh index ad896e9e0..c59a6e6d9 100755 --- a/test/nix/packages.sh +++ b/test/nix/packages.sh @@ -29,6 +29,7 @@ check "nix-env" type nix-env check "vim_installed" type vim check "node_installed" type node check "yarn_installed" type yarn +check "vim_in_default_profile" bash -lc "nix-env -p /nix/var/nix/profiles/default -q | grep -q '^vim'" # Report result # If any of the checks above exited with a non-zero exit code, the test will fail. diff --git a/test/nix/scenarios.json b/test/nix/scenarios.json index 38eed0268..3fb839629 100644 --- a/test/nix/scenarios.json +++ b/test/nix/scenarios.json @@ -86,7 +86,7 @@ "remoteUser": "vscode", "features": { "nix": { - "packages": "nodePackages.nodejs,nixpkgs.vim,nixpkgs.yarn", + "packages": "nodejs,nixpkgs.vim,nixpkgs.yarn", "useAttributePath": true } } From 99a3f1c39fb6771640100bfcbbb4ef5de1e4aa1e Mon Sep 17 00:00:00 2001 From: Venkumahanti Subhankar Date: Tue, 28 Jul 2026 16:20:33 +0530 Subject: [PATCH 3/3] fix(java): Add retry logic for transient SDKMAN bootstrap failures (#1688) * Implement retry logic for SDK installation Added a retry mechanism for SDK installation and SDKMAN CLI installation. * Update Java version from 1.8.0 to 1.8.1 Mandatory minor bump for fixing the sdkman transient error * Update expected Java version in installation script Java version updated due to upstream update from sdkman. * Fix string quotes in install_latest_version.sh * Change curl option from -sSL to -fsSL in install.sh --- src/java/devcontainer-feature.json | 2 +- src/java/install.sh | 28 ++++++++++++++++++++++++++-- test/java/install_latest_version.sh | 4 ++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/java/devcontainer-feature.json b/src/java/devcontainer-feature.json index c82718a49..3a1170df7 100644 --- a/src/java/devcontainer-feature.json +++ b/src/java/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "java", - "version": "1.8.0", + "version": "1.8.1", "name": "Java (via SDKMAN!)", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/java", "description": "Installs Java, SDKMAN! (if not installed), and needed dependencies.", diff --git a/src/java/install.sh b/src/java/install.sh index 988460307..a142ab9e3 100644 --- a/src/java/install.sh +++ b/src/java/install.sh @@ -195,6 +195,29 @@ updaterc() { fi } +run_with_retries() { + local max_attempts="$1" + local wait_seconds="$2" + local operation="$3" + local attempt=1 + shift 3 + + until "$@"; do + if [ "${attempt}" -ge "${max_attempts}" ]; then + echo "(!) ${operation} failed after ${max_attempts} attempts." + return 1 + fi + + echo "(*) ${operation} failed on attempt ${attempt}. Retrying in ${wait_seconds}s..." + attempt=$((attempt + 1)) + sleep "${wait_seconds}" + done +} + +install_sdkman_cli() { + bash -o pipefail -c 'curl -fsSL "https://get.sdkman.io?rcupdate=false" | bash' +} + find_version_list() { prefix="$1" suffix="$2" @@ -284,7 +307,8 @@ sdk_install() { JAVA_VERSION=${requested_version} fi - su ${USERNAME} -c "umask 0002 && . ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk install ${install_type} ${requested_version} && sdk flush archives && sdk flush temp" + run_with_retries 5 10 "Installing ${install_type} ${requested_version} via SDKMAN" \ + su ${USERNAME} -c "umask 0002 && . ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk install ${install_type} ${requested_version} && sdk flush archives && sdk flush temp" } export DEBIAN_FRONTEND=noninteractive @@ -323,7 +347,7 @@ if [ ! -d "${SDKMAN_DIR}" ]; then if [ "${ADJUSTED_ID}" = "rhel" ] && [ "${MAJOR_VERSION_ID}" = "8" ]; then export SDKMAN_NATIVE_VERSION="false" fi - curl -sSL "https://get.sdkman.io?rcupdate=false" | bash + run_with_retries 5 10 "Installing SDKMAN" install_sdkman_cli # For RHEL 8 systems, also disable native CLI in config file and remove native binaries if [ "${ADJUSTED_ID}" = "rhel" ] && [ "${MAJOR_VERSION_ID}" = "8" ]; then # Disable native CLI in config to prevent future usage diff --git a/test/java/install_latest_version.sh b/test/java/install_latest_version.sh index 03175e767..2c8852970 100644 --- a/test/java/install_latest_version.sh +++ b/test/java/install_latest_version.sh @@ -8,8 +8,8 @@ source dev-container-features-test-lib echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java javac HelloWorld.java -check "hello world" /bin/bash -c "java HelloWorld | grep "Hello, World!"" -check "java version latest installed" grep "25" <(java --version) +check "hello world" /bin/bash -c 'java HelloWorld | grep "Hello, World!"' +check "java version latest installed" grep "26" <(java --version) # Report result reportResults