diff --git a/devBenches/devcontainer.test/README.md b/devBenches/devcontainer.test/README.md index e9cc383..de1e998 100644 --- a/devBenches/devcontainer.test/README.md +++ b/devBenches/devcontainer.test/README.md @@ -18,7 +18,8 @@ Layer 1a adds developer tools on top of Layer 0: - PATH configuration for all dev tools The Layer 3 user image adds the effective-user Corepack cache exercised by the -unprivileged pnpm checks in this harness. +unprivileged pnpm checks in this harness, including shells that place +`/usr/bin` before `/usr/local/bin`. ## Quick Start diff --git a/devBenches/devcontainer.test/test.sh b/devBenches/devcontainer.test/test.sh index f04950c..ad38a2b 100755 --- a/devBenches/devcontainer.test/test.sh +++ b/devBenches/devcontainer.test/test.sh @@ -69,6 +69,8 @@ test_tool_output "Node.js" "node --version" test_tool_output "npm" "npm --version" test_tool_output "yarn" "yarn --version" test_tool_output "pnpm as unprivileged user" "pnpm --version" +test_tool "pnpm wrapper survives /usr/bin-first PATH" \ + "PATH=/usr/bin:/usr/local/bin:/bin; test \"\$(command -v pnpm)\" = /usr/bin/pnpm && test \"\$(readlink -f /usr/bin/pnpm)\" = /usr/local/libexec/workbenches-corepack-user-cache && pnpm --version" test_tool "Corepack cache is user-owned and writable" \ "runtime_home=\$(getent passwd \"\$(id -u)\" | cut -d: -f6); cache=\"\$runtime_home/.cache/corepack\"; test -d \"\$cache\" && test -w \"\$cache\" && test \"\$(stat -c '%u' \"\$cache\")\" = \"\$(id -u)\"" test_tool "/usr/local/bin in PATH" "echo \$PATH | grep -q '/usr/local/bin'" diff --git a/user-layer/Dockerfile b/user-layer/Dockerfile index a76e858..3d79c11 100644 --- a/user-layer/Dockerfile +++ b/user-layer/Dockerfile @@ -18,7 +18,7 @@ FROM ${BASE_IMAGE} # Container version labels LABEL layer="3" LABEL layer.name="user-layer" -LABEL layer.version="1.2.1" +LABEL layer.version="1.2.2" LABEL layer.description="User personalization layer" # Build arguments @@ -32,11 +32,28 @@ USER root # Corepack's shared base-layer cache is root-owned. Route Corepack and its # package-manager shims through a runtime wrapper that selects a writable cache -# from the effective user's passwd home, including for non-interactive calls. +# from the effective user's passwd home. Preserve the original Corepack entry +# points before intercepting both common PATH locations; mounted shell configs +# may put /usr/bin ahead of /usr/local/bin. COPY corepack-user-cache /usr/local/libexec/workbenches-corepack-user-cache -RUN chmod 0755 /usr/local/libexec/workbenches-corepack-user-cache && \ +RUN set -eux && \ + chmod 0755 /usr/local/libexec/workbenches-corepack-user-cache && \ + mkdir -p /usr/local/libexec/workbenches-corepack-original && \ for command in corepack pnpm pnpx yarn yarnpkg; do \ + if [ -e "/usr/bin/$command" ] || [ -L "/usr/bin/$command" ]; then \ + original_command="/usr/bin/$command"; \ + elif [ -e "/usr/local/bin/$command" ] || [ -L "/usr/local/bin/$command" ]; then \ + original_command="/usr/local/bin/$command"; \ + else \ + echo "Required Corepack command is unavailable: $command" >&2; \ + exit 1; \ + fi; \ + preserved_command="${original_command}.workbenches-original"; \ + mv "$original_command" "$preserved_command"; \ + test -x "$preserved_command"; \ + ln -sfn "$preserved_command" "/usr/local/libexec/workbenches-corepack-original/$command"; \ ln -sfn /usr/local/libexec/workbenches-corepack-user-cache "/usr/local/bin/$command"; \ + ln -sfn /usr/local/libexec/workbenches-corepack-user-cache "/usr/bin/$command"; \ done # ======================================== diff --git a/user-layer/corepack-user-cache b/user-layer/corepack-user-cache index 90b90e4..2a755d9 100644 --- a/user-layer/corepack-user-cache +++ b/user-layer/corepack-user-cache @@ -25,4 +25,11 @@ case "${COREPACK_HOME:-}" in esac mkdir -p "$COREPACK_HOME" -exec "/usr/bin/$command_name" "$@" + +original_command="/usr/local/libexec/workbenches-corepack-original/$command_name" +if [ ! -x "$original_command" ]; then + echo "Original Corepack command is unavailable: $original_command" >&2 + exit 1 +fi + +exec "$original_command" "$@"