diff --git a/deps_rocker/extensions/codex/codex_snippet.Dockerfile b/deps_rocker/extensions/codex/codex_snippet.Dockerfile new file mode 100644 index 00000000..ef4fff78 --- /dev/null +++ b/deps_rocker/extensions/codex/codex_snippet.Dockerfile @@ -0,0 +1,3 @@ +# Install OpenAI Codex CLI with BuildKit cache for npm global installs +RUN --mount=type=cache,target=/root/.npm,id=global-npm-cache \ + npm install -g @@openai/codex diff --git a/deps_rocker/extensions/codex/codex_user_snippet.Dockerfile b/deps_rocker/extensions/codex/codex_user_snippet.Dockerfile deleted file mode 100644 index 8a6233db..00000000 --- a/deps_rocker/extensions/codex/codex_user_snippet.Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -# Install OpenAI Codex CLI with BuildKit cache for npm global installs -RUN npm install -g @@openai/codex - -# Create symlink in /usr/local/bin for non-interactive shell access -RUN sudo ln -sf ~/.pixi/envs/nodejs/bin/codex /usr/local/bin/codex diff --git a/deps_rocker/extensions/codex/test.sh b/deps_rocker/extensions/codex/test.sh index 9976196a..f0164af8 100755 --- a/deps_rocker/extensions/codex/test.sh +++ b/deps_rocker/extensions/codex/test.sh @@ -1,4 +1,4 @@ -#!/bin/bash -l +#!/bin/bash set -e echo "Testing codex installation..." diff --git a/deps_rocker/extensions/gemini/gemini_snippet.Dockerfile b/deps_rocker/extensions/gemini/gemini_snippet.Dockerfile new file mode 100644 index 00000000..2a063271 --- /dev/null +++ b/deps_rocker/extensions/gemini/gemini_snippet.Dockerfile @@ -0,0 +1,3 @@ +# Install Google Gemini CLI tool via npm with BuildKit cache for global installs +RUN --mount=type=cache,target=/root/.npm,id=global-npm-cache \ + npm install -g @@google/gemini-cli diff --git a/deps_rocker/extensions/gemini/gemini_user_snippet.Dockerfile b/deps_rocker/extensions/gemini/gemini_user_snippet.Dockerfile deleted file mode 100644 index 5164ff71..00000000 --- a/deps_rocker/extensions/gemini/gemini_user_snippet.Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -# Install Google Gemini CLI tool via npm with BuildKit cache for global installs -RUN npm install -g @@google/gemini-cli - -# Create symlink in /usr/local/bin for non-interactive shell access -RUN sudo ln -sf ~/.pixi/envs/nodejs/bin/gemini /usr/local/bin/gemini diff --git a/deps_rocker/extensions/gemini/test.sh b/deps_rocker/extensions/gemini/test.sh index d368def3..687ee784 100755 --- a/deps_rocker/extensions/gemini/test.sh +++ b/deps_rocker/extensions/gemini/test.sh @@ -1,4 +1,4 @@ -#!/bin/bash -l +#!/bin/bash set -e echo "Testing gemini installation..." diff --git a/deps_rocker/extensions/npm/npm.py b/deps_rocker/extensions/npm/npm.py index 222835a8..736bca3c 100644 --- a/deps_rocker/extensions/npm/npm.py +++ b/deps_rocker/extensions/npm/npm.py @@ -2,7 +2,13 @@ class Npm(SimpleRockerExtension): - """Install npm via pixi using nodejs from conda-forge""" + """Install npm using nvm (Node Version Manager)""" name = "npm" - depends_on_extension = ("pixi",) + depends_on_extension = ("curl",) + builder_apt_packages = ["curl", "ca-certificates", "git"] + + empy_args = { + "NODE_VERSION": "24.9.0", + "NPM_VERSION": "11.6.1", + } diff --git a/deps_rocker/extensions/npm/npm_builder_snippet.Dockerfile b/deps_rocker/extensions/npm/npm_builder_snippet.Dockerfile new file mode 100644 index 00000000..6c5d94ce --- /dev/null +++ b/deps_rocker/extensions/npm/npm_builder_snippet.Dockerfile @@ -0,0 +1,32 @@ +# syntax=docker/dockerfile:1.4 +ARG NODE_VERSION=@NODE_VERSION@ + +@(f"FROM {base_image} AS {builder_stage}") + +ARG NODE_VERSION +ENV NVM_DIR=/usr/local/nvm + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt-cache \ + --mount=type=cache,target=/var/lib/apt/lists,sharing=locked,id=apt-lists \ + apt-get update && \ + apt-get install -y --no-install-recommends git && \ + rm -rf /var/lib/apt/lists/* + +# Clone nvm from git with caching +RUN --mount=type=cache,target=/tmp/nvm-git-cache,id=nvm-git-cache \ + bash -c "set -e && \ + if [ -d /tmp/nvm-git-cache/.git ]; then \ + cd /tmp/nvm-git-cache && git fetch --tags && git checkout v0.40.3; \ + else \ + git clone https://github.com/nvm-sh/nvm.git /tmp/nvm-git-cache && \ + cd /tmp/nvm-git-cache && git checkout v0.40.0; \ + fi && \ + # Use tar to copy nvm cache, excluding .git, test, and .github for smaller image and security + # Ensure /usr/local/nvm exists before extracting + mkdir -p /usr/local/nvm && tar --exclude='.git' --exclude='test' --exclude='.github' -cf - -C /tmp/nvm-git-cache . | tar -xf - -C /usr/local/nvm" + +# Install Node.js using nvm with cached downloads - use template substitution for version +RUN --mount=type=cache,target=/usr/local/nvm/.cache,id=nvm-node-cache \ + bash -c "set -e && \ + . \$NVM_DIR/nvm.sh && \ + nvm install @(NODE_VERSION)" diff --git a/deps_rocker/extensions/npm/npm_snippet.Dockerfile b/deps_rocker/extensions/npm/npm_snippet.Dockerfile new file mode 100644 index 00000000..ca8337f7 --- /dev/null +++ b/deps_rocker/extensions/npm/npm_snippet.Dockerfile @@ -0,0 +1,13 @@ + +ENV NODE_VERSION=24.9.0 +# Install nvm, node and npm +ENV NVM_DIR=/usr/local/nvm + +ENV NPM_CONFIG_UPDATE_NOTIFIER=false +ENV NPM_CONFIG_FUND=false + +# Copy pre-installed nvm directory from builder +@(f"COPY --from={builder_stage} $NVM_DIR $NVM_DIR") + +# Add node and npm to path +ENV PATH="$NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH" diff --git a/deps_rocker/extensions/npm/npm_user_snippet.Dockerfile b/deps_rocker/extensions/npm/npm_user_snippet.Dockerfile deleted file mode 100644 index 11a3cfe0..00000000 --- a/deps_rocker/extensions/npm/npm_user_snippet.Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -# Install Node.js and npm via pixi global install -RUN pixi global install nodejs - -# Add npm global bin directory to PATH for login shells -RUN echo 'export PATH="$HOME/.pixi/envs/nodejs/bin:$PATH"' >> ~/.profile - -# Create symlinks in /usr/local/bin for non-interactive shell access -RUN sudo ln -sf ~/.pixi/envs/nodejs/bin/node /usr/local/bin/node && \ - sudo ln -sf ~/.pixi/envs/nodejs/bin/npm /usr/local/bin/npm && \ - sudo ln -sf ~/.pixi/envs/nodejs/bin/npx /usr/local/bin/npx - -# Configure shell to use bash and source profile for subsequent RUN commands -SHELL ["/bin/bash", "-l", "-c"] - -# Disable npm update notifier and fund messages -ENV NPM_CONFIG_UPDATE_NOTIFIER=false -ENV NPM_CONFIG_FUND=false diff --git a/deps_rocker/extensions/npm/test.sh b/deps_rocker/extensions/npm/test.sh index d8d6ab4d..ee296468 100755 --- a/deps_rocker/extensions/npm/test.sh +++ b/deps_rocker/extensions/npm/test.sh @@ -1,4 +1,5 @@ -#!/bin/bash -l +#!/bin/bash + set -e echo "Testing npm installation..." diff --git a/specs/01/npm-pixi-install/plan.md b/specs/01/npm-pixi-install/plan.md deleted file mode 100644 index 5c54eb5c..00000000 --- a/specs/01/npm-pixi-install/plan.md +++ /dev/null @@ -1,29 +0,0 @@ -# Implementation Plan: NPM via Pixi - -## Changes Required - -### 1. Update npm.py -- Remove `depends_on_extension = ("curl",)` -- Add `depends_on_extension = ("pixi",)` instead -- Remove `builder_apt_packages` since pixi handles installation -- Update or remove `empy_args` - pixi will manage the nodejs version -- Keep the class simple since pixi does the heavy lifting - -### 2. Update npm_snippet.Dockerfile -- Remove NVM installation logic -- Remove ENV variables for NVM_DIR and NODE_VERSION -- Add pixi installation snippet using `pixi global install nodejs` -- Ensure npm and node binaries are in PATH via pixi -- Use BuildKit cache mount for pixi cache (inherited from pixi extension) - -### 3. Test Verification -- Verify test.sh still works and checks for npm and node commands -- Ensure version checks pass -- Test that npm can install packages - -## Benefits -- Simpler installation using pixi ecosystem -- Better caching via BuildKit mounts -- Consistent with other pixi-based extensions -- Eliminates need for separate NVM installation -- Easier to manage nodejs versions through pixi diff --git a/specs/01/npm-pixi-install/spec.md b/specs/01/npm-pixi-install/spec.md deleted file mode 100644 index 5bd6b616..00000000 --- a/specs/01/npm-pixi-install/spec.md +++ /dev/null @@ -1,23 +0,0 @@ -# NPM Extension: Install via Pixi - -Update the npm extension to install Node.js and npm using pixi with the nodejs package from conda-forge instead of using NVM (Node Version Manager). - -## Requirements -- Install Node.js and npm via pixi using the `nodejs` conda-forge package -- Remove dependency on curl and NVM -- Use BuildKit cache mounts for pixi cache (inherited from pixi extension) -- Maintain backward compatibility for users of the npm extension -- Existing tests should continue to work - -## Out of Scope -- Changing npm version pinning behavior (pixi manages the version) -- Modifying npm configuration beyond what's needed for pixi installation - -## Implementation -- Updated `npm.py` to depend on `pixi` instead of `curl` -- Removed `npm_builder_snippet.Dockerfile` (no longer needed) -- Created `npm_user_snippet.Dockerfile` to use `pixi global install nodejs` in user stage -- Kept NPM environment variables for disabling update notifier and fund messages - -## Fix -- Renamed `npm_snippet.Dockerfile` to `npm_user_snippet.Dockerfile` because pixi global install must run in the user stage after pixi is set up in the user environment