Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/node/README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# node

Install [Node.js](https://nodejs.org) from [Nodesource's DEB repository](https://deb.nodesource.com).
Install [Node.js](https://nodejs.org) from prebuilt binaries.

## Usage

```json
"features": {
"ghcr.io/CargoSense/devcontainer-features/node:3": {}
"ghcr.io/CargoSense/devcontainer-features/node:4": {}
}
```

## Options

| Option ID | Description | Type | Default Value |
|:----------|:--------------------------------|:-------|:--------------|
| `version` | The Node.js version to install. | string | `automatic` |
| `version` | The Node.js version to install. | string | `latest` |

## OS Support

This Feature should work on recent versions of Debian/Ubuntu and Linux distributions using the [apt](https://wiki.debian.org/AptCLI) management tool.
This Feature should work on recent versions of Debian/Ubuntu and Linux distributions using the [apt](https://wiki.debian.org/AptCLI) management tool and on architectures for which Node.js provides prebuilt binaries.
15 changes: 11 additions & 4 deletions src/node/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
{
"name": "Node.js",
"id": "node",
"version": "3.0.0",
"description": "Install Node.js from Nodesource's DEB repository.",
"version": "4.0.0",
"description": "Install Node.js from prebuilt binaries.",
"documentationURL": "https://github.com/CargoSense/devcontainer-features/tree/main/src/node",
"licenseURL": "https://github.com/CargoSense/devcontainer-features/blob/main/LICENSE",
"options": {
"version": {
"type": "string",
"default": "automatic",
"default": "latest",
"description": "The Node.js version to install."
}
},
"containerEnv": {
"NPM_CONFIG_CACHE": "/usr/local/npm"
"NPM_CONFIG_CACHE": "/usr/local/npm",
"NODE_HOME": "/usr/local/share/node",
"PATH": "/usr/local/share/node/bin:${PATH}"
},
"dependsOn": {
"ghcr.io/CargoSense/devcontainer-features/apt-packages:1": {
"packages": "libatomic1"
}
},
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
Expand Down
102 changes: 61 additions & 41 deletions src/node/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,31 @@

set -e

NODE_VERSION="${VERSION:-"automatic"}"
NODE_MAJOR_VERSION="24"

pkg="nodejs"

if [[ "${NODE_VERSION}" != "automatic" ]]; then
NODE_MAJOR_VERSION="$(echo "${NODE_VERSION}" | cut -d. -f1)"
pkg="${pkg}=${NODE_VERSION}-1nodesource1"
NODE_VERSION="${VERSION:-"latest"}"

USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"

# Determine the appropriate non-root user.
if [[ "${USERNAME}" = "automatic" ]]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "$(getent passwd 1000 | cut -d: -f1)")

for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do
if id -u "${CURRENT_USER}" >/dev/null 2>&1; then
USERNAME="${CURRENT_USER}"
break
fi
done

if [[ "${USERNAME}" = "" ]]; then
USERNAME="root"
fi
elif ! id -u "${USERNAME}" >/dev/null 2>&1; then
USERNAME="root"
fi

curl_installed=""
gpg_installed=""
xz_installed=""

if ! type curl >/dev/null 2>&1; then
apt update --yes
Expand All @@ -22,49 +35,56 @@ if ! type curl >/dev/null 2>&1; then
curl_installed="true"
fi

if ! type gpg >/dev/null 2>&1; then
if ! type xz >/dev/null 2>&1; then
apt update --yes
apt install --yes gnupg
apt install --yes xz-utils

gpg_installed="true"
xz_installed="true"
fi

apt_sources_snippet="$(cat << EOF
Types: deb
URIs: https://deb.nodesource.com/node_${NODE_MAJOR_VERSION}.x
Suites: nodistro
Components: main
Signed-By: /etc/apt/keyrings/nodesource.gpg
EOF
)"

install -dm 755 /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
echo "${apt_sources_snippet}" | tee /etc/apt/sources.list.d/nodesource.sources
# Normalize architecture
arch="$(dpkg --print-architecture)"
if [[ "${arch}" = "amd64" ]] || [[ "${arch}" = "x86_64" ]] || [[ "${arch}" = "i386" ]]; then
arch="x64"
fi

if [[ -n "${curl_installed}" ]]; then
apt purge curl --autoremove --yes
rm -rf /var/lib/apt/lists/*
# Normalize Node.js version string
if [[ "${NODE_VERSION}" != "latest" ]] && [[ "${NODE_VERSION}" != "v"* ]]; then
NODE_VERSION="v${NODE_VERSION}"
fi

if [[ -n "${gpg_installed}" ]]; then
apt purge gnupg --autoremove --yes
rm -rf /var/lib/apt/lists/*
# Configure "node" group
if ! grep -e "^node:" /etc/group >/dev/null 2>&1; then
groupadd --system node
fi
usermod --append --groups node "${USERNAME}"

# Install Node.js
umask 0002
mkdir -p "${NODE_HOME:?}"
curl -fsSL "https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-${arch}.tar.xz" | tar xf - -C "${NODE_HOME}" -J --strip-components 1

apt update --yes
apt install --yes "${pkg}"
rm -rf /var/lib/apt/lists/*
chown -R "${USERNAME}:node" "${NODE_HOME}"
chmod g+rws "${NODE_HOME}"

node_rc_snippet="$(cat << EOF
export NODE_VERSION="$(node -v | cut -c2-)"
EOF
)"
# Configure shell
rc_snippet="export NODE_VERSION=\"$(node -v | cut -c2-)\""

if [[ "$(cat /etc/bash.bashrc)" != *"${node_rc_snippet}"* ]]; then
echo "${node_rc_snippet}" >> /etc/bash.bashrc
if [[ -f /etc/bash.bashrc ]] && ! grep -q "${rc_snippet}" /etc/bash.bashrc; then
echo "${rc_snippet}" >>/etc/bash.bashrc
fi

if [[ -f "/etc/zsh/zshrc" ]] && [[ "$(cat /etc/zsh/zshrc)" != *"${node_rc_snippet}"* ]]; then
echo "${node_rc_snippet}" >> /etc/zsh/zshrc
if [[ -f /etc/zsh/zshrc ]] && ! grep -q "${rc_snippet}" /etc/zsh/zshrc; then
echo "${rc_snippet}" >>/etc/zsh/zshrc
fi

# Cleanup
if [[ -n "${curl_installed}" ]]; then
apt purge curl --autoremove --yes
rm -rf /var/lib/apt/lists/*
fi

if [[ -n "${xz_installed}" ]]; then
apt purge xz-utils --autoremove --yes
rm -rf /var/lib/apt/lists/*
fi
4 changes: 2 additions & 2 deletions test/node/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ set -e
source dev-container-features-test-lib

# Feature-specific tests
check "version" bash -c "node --version | grep -E 'v24\..+'"
check "which node" bash -c "which node | grep /usr/bin/node"
check "version" bash -c "node --version | grep -E 'v25\..+'"
check "which node" bash -c "which node | grep /usr/local/share/node/bin/node"

# Report result
reportResults
Loading