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
3 changes: 2 additions & 1 deletion devBenches/devcontainer.test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions devBenches/devcontainer.test/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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'"
Expand Down
23 changes: 20 additions & 3 deletions user-layer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

# ========================================
Expand Down
9 changes: 8 additions & 1 deletion user-layer/corepack-user-cache
Original file line number Diff line number Diff line change
Expand Up @@ -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" "$@"