Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
90fc2c5
Initial plan
Copilot Mar 31, 2026
6ebf0fb
docs: add Results section with verified node/python versions and paths
Copilot Mar 31, 2026
957e141
Remove node/npm feature and references, keep only python
Copilot Mar 31, 2026
03f5e49
chore: remove python feature, add curl tests to all lifecycle hooks
Copilot Mar 31, 2026
c059979
test: run curl lifecycle tests on debian-13 and ubuntu-24.04, documen…
Copilot Mar 31, 2026
dcebedd
fix: add chmod 755 /etc/ssl/certs workaround in on-create.sh; documen…
Copilot Mar 31, 2026
9e9b4c0
feat: restore python:1 feature; fix SSL via chmod 755 at container st…
Copilot Mar 31, 2026
6db8c58
feat: add node feature; remove redundant chmod; root+non-root version…
Copilot Mar 31, 2026
f2190ed
fix: add Dockerfile with non-root SSL workaround; switch docker-compo…
Copilot Mar 31, 2026
99cd9c4
fix: add curlrc, /etc/environment and profile.d for comprehensive non…
Copilot Mar 31, 2026
04ed654
fix: add git system sslCAInfo config and GIT_SSL_CAINFO to fix NVM gi…
Copilot Mar 31, 2026
6499567
fix: use sudo \$(which node) instead of sudo bash -lc for root node v…
Copilot Mar 31, 2026
6997079
refactor: use echo blocks for Dockerfile env vars; fix pip install --…
Copilot Mar 31, 2026
cfccba4
switch from devcontainer features to local Dockerfile; drop SSL env o…
Copilot Mar 31, 2026
514e599
Replace devcontainer features with local Dockerfile using pyenv/nvm; …
Copilot Mar 31, 2026
df58287
update README: current approach, outstanding build blocker, handoff i…
Copilot Mar 31, 2026
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
49 changes: 49 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
FROM mcr.microsoft.com/devcontainers/base:trixie

# Version pins — change these ARGs and rebuild to switch versions.
ARG PYTHON_VERSION=3.13
ARG NODE_VERSION=lts

ENV PYENV_ROOT=/usr/local/pyenv \
NVM_DIR=/usr/local/nvm

# The padawan-fw runc shim bind-mounts a mode-0700 tmpdir over /etc/ssl/certs in every
# container it starts. Each RUN step opens with chmod 755 /etc/ssl/certs so that both
# root and the non-root vscode user can reach the cert bundle for TLS.

# Build dependencies needed by pyenv to compile Python from source.
RUN chmod 755 /etc/ssl/certs \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
libsqlite3-dev libncursesw5-dev xz-utils tk-dev libxml2-dev \
libxmlsec1-dev libffi-dev liblzma-dev \
&& rm -rf /var/lib/apt/lists/*

# Install pyenv to /usr/local/pyenv and compile the pinned Python version.
# Direct git clone avoids the pyenv-installer script's Launchpad/GitHub API calls
# and makes the install reproducible.
RUN chmod 755 /etc/ssl/certs \
&& git clone https://github.com/pyenv/pyenv.git ${PYENV_ROOT} \
&& ${PYENV_ROOT}/bin/pyenv install ${PYTHON_VERSION} \
&& ${PYENV_ROOT}/bin/pyenv global ${PYTHON_VERSION} \
&& chown -R root:root ${PYENV_ROOT} \
&& chmod -R a+rX ${PYENV_ROOT} \
&& ln -sf "$(${PYENV_ROOT}/bin/pyenv which python3)" /usr/local/bin/python3 \
&& ln -sf "$(${PYENV_ROOT}/bin/pyenv which pip3)" /usr/local/bin/pip3 \
&& ln -sf "$(${PYENV_ROOT}/bin/pyenv which pip3)" /usr/local/bin/pip

# Install nvm to /usr/local/nvm and install the pinned Node version.
RUN chmod 755 /etc/ssl/certs \
&& mkdir -p "${NVM_DIR}" \
&& curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh \
| NVM_DIR="${NVM_DIR}" bash \
&& . "${NVM_DIR}/nvm.sh" \
&& nvm install "${NODE_VERSION}" \
&& nvm alias default "${NODE_VERSION}" \
&& NODE_BIN="$(nvm which default)" \
&& chown -R root:root "${NVM_DIR}" \
&& chmod -R a+rX "${NVM_DIR}" \
&& ln -sf "${NODE_BIN}" /usr/local/bin/node \
&& ln -sf "$(dirname "${NODE_BIN}")/npm" /usr/local/bin/npm \
&& ln -sf "$(dirname "${NODE_BIN}")/npx" /usr/local/bin/npx
12 changes: 3 additions & 9 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,8 @@
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/repro",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "22"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.13"
}
},
"onCreateCommand": "./.devcontainer/on-create.sh",
"updateContentCommand": "./.devcontainer/update-content.sh"
"updateContentCommand": "./.devcontainer/update-content.sh",
"postCreateCommand": "./.devcontainer/post-create.sh",
"postStartCommand": "./.devcontainer/post-start.sh"
}
10 changes: 3 additions & 7 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
services:
app:
image: mcr.microsoft.com/devcontainers/base:debian-13
build:
context: ..
dockerfile: .devcontainer/Dockerfile
command: sleep infinity
volumes:
- ..:/workspaces/repro
- npm-cache:/home/vscode/.cache/npm
- pip-cache:/home/vscode/.cache/pip

volumes:
npm-cache:
pip-cache:
52 changes: 26 additions & 26 deletions .devcontainer/on-create.sh
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
#!/usr/bin/env bash
set -euxo pipefail

mkdir -p "$HOME/.cache/npm" "$HOME/.cache/pip"
sudo chown "$(id -u):$(id -g)" "$HOME/.cache" "$HOME/.cache/npm" "$HOME/.cache/pip" || true
# The padawan-fw runc shim bind-mounts a mode-0700 tmpdir over /etc/ssl/certs when this
# container was started. Repair the permissions so non-root users can traverse the
# directory and use TLS normally for the lifetime of this container.
sudo chmod 755 /etc/ssl/certs

echo "=== user ==="
echo "=== [onCreateCommand] user ==="
whoami
id

echo "=== env ==="
env | sort
echo "=== filtered env ==="
env | grep -E 'SSL|REQUESTS|CURL|NODE|NPM|PIP|PYTHON' || true
echo "=== [onCreateCommand] python version (root) ==="
sudo python3 --version

echo "=== ssl bundle ==="
ls -l /etc/ssl/certs || true
ls -l /etc/ssl/certs/ca-certificates.crt || true
echo "=== [onCreateCommand] python version (vscode) ==="
python3 --version

echo "=== [onCreateCommand] node version (root) ==="
sudo "$(which node)" --version

echo "=== python ssl defaults ==="
python3 - <<'PY'
import ssl
print(ssl.get_default_verify_paths())
PY
echo "=== [onCreateCommand] node version (vscode) ==="
node --version

echo "=== [onCreateCommand] ssl bundle ==="
ls -l /etc/ssl/certs/ca-certificates.crt || true

echo "=== root curl ==="
echo "=== [onCreateCommand] root curl ==="
sudo bash -lc '
set -euxo pipefail
whoami
id
env | grep -E "SSL|REQUESTS|CURL|NODE|NPM|PIP|PYTHON" || true
curl -Ivs https://github.com >/tmp/root-curl.txt 2>&1 || {
cat /tmp/root-curl.txt
echo "root curl user: $(whoami)"
curl -Ivs https://github.com >/tmp/oncreate-root-curl.txt 2>&1 || {
cat /tmp/oncreate-root-curl.txt
exit 1
}
cat /tmp/root-curl.txt
cat /tmp/oncreate-root-curl.txt
'

echo "=== user curl ==="
curl -Ivs https://github.com >/tmp/user-curl.txt 2>&1 || {
cat /tmp/user-curl.txt
echo "=== [onCreateCommand] user curl ==="
curl -Ivs https://github.com >/tmp/oncreate-user-curl.txt 2>&1 || {
cat /tmp/oncreate-user-curl.txt
exit 1
}
cat /tmp/user-curl.txt
cat /tmp/oncreate-user-curl.txt
52 changes: 52 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -euxo pipefail

# The padawan-fw runc shim bind-mounts a mode-0700 tmpdir over /etc/ssl/certs when this
# container was started. Repair the permissions so non-root users can traverse the
# directory and use TLS normally for the lifetime of this container.
sudo chmod 755 /etc/ssl/certs

echo "=== [postCreateCommand] user ==="
whoami
id

echo "=== [postCreateCommand] python version (root) ==="
sudo python3 --version

echo "=== [postCreateCommand] python version (vscode) ==="
python3 --version

echo "=== [postCreateCommand] node version (root) ==="
sudo "$(which node)" --version

echo "=== [postCreateCommand] node version (vscode) ==="
node --version

echo "=== [postCreateCommand] ssl bundle ==="
ls -l /etc/ssl/certs/ca-certificates.crt || true

echo "=== [postCreateCommand] root curl ==="
sudo bash -lc '
set -euxo pipefail
echo "root curl user: $(whoami)"
curl -Ivs https://github.com >/tmp/postcreate-root-curl.txt 2>&1 || {
cat /tmp/postcreate-root-curl.txt
exit 1
}
cat /tmp/postcreate-root-curl.txt
'

echo "=== [postCreateCommand] user curl ==="
curl -Ivs https://github.com >/tmp/postcreate-user-curl.txt 2>&1 || {
cat /tmp/postcreate-user-curl.txt
exit 1
}
cat /tmp/postcreate-user-curl.txt

echo "=== [postCreateCommand] pip install (non-root) ==="
pip install --user cowsay

echo "=== [postCreateCommand] npm install (non-root) ==="
mkdir -p /tmp/npm-test
cd /tmp/npm-test
npm install cowsay
44 changes: 44 additions & 0 deletions .devcontainer/post-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euxo pipefail

# The padawan-fw runc shim bind-mounts a mode-0700 tmpdir over /etc/ssl/certs each time
# this container starts. Repair the permissions so non-root users can traverse the
# directory and use TLS normally for the lifetime of this container session.
sudo chmod 755 /etc/ssl/certs

echo "=== [postStartCommand] user ==="
whoami
id

echo "=== [postStartCommand] python version (root) ==="
sudo python3 --version

echo "=== [postStartCommand] python version (vscode) ==="
python3 --version

echo "=== [postStartCommand] node version (root) ==="
sudo "$(which node)" --version

echo "=== [postStartCommand] node version (vscode) ==="
node --version

echo "=== [postStartCommand] ssl bundle ==="
ls -l /etc/ssl/certs/ca-certificates.crt || true

echo "=== [postStartCommand] root curl ==="
sudo bash -lc '
set -euxo pipefail
echo "root curl user: $(whoami)"
curl -Ivs https://github.com >/tmp/poststart-root-curl.txt 2>&1 || {
cat /tmp/poststart-root-curl.txt
exit 1
}
cat /tmp/poststart-root-curl.txt
'

echo "=== [postStartCommand] user curl ==="
curl -Ivs https://github.com >/tmp/poststart-user-curl.txt 2>&1 || {
cat /tmp/poststart-user-curl.txt
exit 1
}
cat /tmp/poststart-user-curl.txt
49 changes: 33 additions & 16 deletions .devcontainer/update-content.sh
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
#!/usr/bin/env bash
set -euxo pipefail

echo "=== updateContent user ==="
# The padawan-fw runc shim bind-mounts a mode-0700 tmpdir over /etc/ssl/certs when this
# container was started. Repair the permissions so non-root users can traverse the
# directory and use TLS normally for the lifetime of this container.
sudo chmod 755 /etc/ssl/certs

echo "=== [updateContentCommand] user ==="
whoami
id

echo "=== filtered env ==="
env | grep -E 'SSL|REQUESTS|CURL|NODE|NPM|PIP|PYTHON' || true
echo "=== [updateContentCommand] python version (root) ==="
sudo python3 --version

echo "=== tool versions ==="
node --version
npm --version
echo "=== [updateContentCommand] python version (vscode) ==="
python3 --version
python3 -m pip --version

echo "=== npm https test ==="
npm view lodash version
echo "=== [updateContentCommand] node version (root) ==="
sudo "$(which node)" --version

echo "=== [updateContentCommand] node version (vscode) ==="
node --version

echo "=== [updateContentCommand] ssl bundle ==="
ls -l /etc/ssl/certs/ca-certificates.crt || true

echo "=== pip https test ==="
python3 -m pip install --user requests
echo "=== [updateContentCommand] root curl ==="
sudo bash -lc '
set -euxo pipefail
echo "root curl user: $(whoami)"
curl -Ivs https://github.com >/tmp/updatecontent-root-curl.txt 2>&1 || {
cat /tmp/updatecontent-root-curl.txt
exit 1
}
cat /tmp/updatecontent-root-curl.txt
'

echo "=== python ssl defaults ==="
python3 - <<'PY'
import ssl
print(ssl.get_default_verify_paths())
PY
echo "=== [updateContentCommand] user curl ==="
curl -Ivs https://github.com >/tmp/updatecontent-user-curl.txt 2>&1 || {
cat /tmp/updatecontent-user-curl.txt
exit 1
}
cat /tmp/updatecontent-user-curl.txt
Loading