Skip to content

Commit b3aa446

Browse files
feat(node): add npm version selection and installation options
1 parent 0c2cd3f commit b3aa446

6 files changed

Lines changed: 123 additions & 6 deletions

File tree

src/node/devcontainer-feature.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@
2727
"default": "/usr/local/share/nvm",
2828
"description": "The path where NVM will be installed."
2929
},
30+
"npmVersion": {
31+
"type": "string",
32+
"proposals": [
33+
"10.9.0",
34+
"10.8.0",
35+
"10.7.0",
36+
"9.9.3",
37+
"8.19.4",
38+
"latest",
39+
"none"
40+
],
41+
"default": "10.9.0",
42+
"description": "Select or enter a specific NPM version to install globally. Use 'latest' for the latest version, 'none' to skip npm version update, or specify a version like '10.9.0'."
43+
},
3044
"pnpmVersion": {
3145
"type": "string",
3246
"proposals": [
@@ -78,4 +92,4 @@
7892
"installsAfter": [
7993
"ghcr.io/devcontainers/features/common-utils"
8094
]
81-
}
95+
}

src/node/install.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# Maintainer: The Dev Container spec maintainers
99

1010
export NODE_VERSION="${VERSION:-"lts"}"
11+
export NPM_VERSION="${NPMVERSION:-"lts"}"
1112
export PNPM_VERSION="${PNPMVERSION:-"latest"}"
1213
export NVM_VERSION="${NVMVERSION:-"latest"}"
1314
export NVM_DIR="${NVMINSTALLPATH:-"/usr/local/share/nvm"}"
@@ -381,6 +382,41 @@ if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then
381382
IFS=$OLDIFS
382383
fi
383384

385+
# Install or update npm to specific version
386+
if [ ! -z "${NPM_VERSION}" ] && [ "${NPM_VERSION}" = "none" ]; then
387+
echo "Ignoring NPM version update"
388+
else
389+
if bash -c ". '${NVM_DIR}/nvm.sh' && type npm >/dev/null 2>&1"; then
390+
(
391+
. "${NVM_DIR}/nvm.sh"
392+
[ ! -z "$http_proxy" ] && npm set proxy="$http_proxy"
393+
[ ! -z "$https_proxy" ] && npm set https-proxy="$https_proxy"
394+
[ ! -z "$no_proxy" ] && npm set noproxy="$no_proxy"
395+
echo "Installing npm version ${NPM_VERSION}..."
396+
397+
# Clear npm cache to avoid conflicts
398+
npm cache clean --force 2>/dev/null || true
399+
400+
# Try npm installation with retries
401+
for i in {1..3}; do
402+
if npm install -g npm@$NPM_VERSION --force; then
403+
echo "Successfully installed npm@${NPM_VERSION}"
404+
break
405+
else
406+
echo "Attempt $i failed, retrying..."
407+
sleep 2
408+
if [ $i -eq 3 ]; then
409+
echo "Failed to install npm@${NPM_VERSION} after 3 attempts. Trying latest npm as fallback..."
410+
npm install -g npm@latest --force || echo "Fallback to latest npm also failed. Keeping current npm version $(npm --version 2>/dev/null || echo 'unknown')."
411+
fi
412+
fi
413+
done
414+
)
415+
else
416+
echo "Skip installing/updating npm because npm is not available"
417+
fi
418+
fi
419+
384420
# Install pnpm
385421
if [ ! -z "${PNPM_VERSION}" ] && [ "${PNPM_VERSION}" = "none" ]; then
386422
echo "Ignoring installation of PNPM"

test/node/install_npm_latest.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# Verify npm is latest version (valid version format)
9+
check "npm_latest_version" bash -c "npm -v | grep -E '^[0-9]+\.[0-9]+\.[0-9]+'"
10+
11+
# Also verify pnpm works as configured
12+
check "pnpm_version" bash -c "pnpm -v | grep 8.8.0"
13+
14+
# Report result
15+
reportResults

test/node/install_npm_none.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# When npmVersion is "none", npm should not be updated from node's bundled version
9+
check "npm_not_updated" bash -c "npm --version"
10+
11+
# Report result
12+
reportResults
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# Verify npm is installed with specific version 10.8.0
9+
check "npm_specific_version" bash -c "npm -v | grep '^10.8.0'"
10+
11+
# Report result
12+
reportResults

test/node/scenarios.json

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@
66
"version": "lts"
77
}
88
}
9-
},
9+
},
1010
"install_node_debian_bookworm": {
1111
"image": "debian:12",
1212
"features": {
1313
"node": {
1414
"version": "lts"
1515
}
1616
}
17-
},
17+
},
1818
"nvm_test_fallback": {
1919
"image": "debian:11",
2020
"features": {
2121
"node": {
2222
"version": "lts"
2323
}
2424
}
25-
},
25+
},
2626
"install_additional_node": {
2727
"image": "debian:11",
2828
"features": {
@@ -98,7 +98,7 @@
9898
"features": {
9999
"node": {
100100
"version": "22",
101-
"pnpmVersion":"8.8.0"
101+
"pnpmVersion": "8.8.0"
102102
}
103103
}
104104
},
@@ -207,5 +207,33 @@
207207
"version": "lts"
208208
}
209209
}
210+
},
211+
"install_specific_npm_version": {
212+
"image": "debian:12",
213+
"features": {
214+
"node": {
215+
"version": "lts",
216+
"npmVersion": "10.8.0"
217+
}
218+
}
219+
},
220+
"install_npm_none": {
221+
"image": "mcr.microsoft.com/devcontainers/base",
222+
"features": {
223+
"node": {
224+
"version": "lts",
225+
"npmVersion": "none"
226+
}
227+
}
228+
},
229+
"install_npm_latest": {
230+
"image": "debian:12",
231+
"features": {
232+
"node": {
233+
"version": "22",
234+
"npmVersion": "latest",
235+
"pnpmVersion": "8.8.0"
236+
}
237+
}
210238
}
211-
}
239+
}

0 commit comments

Comments
 (0)