From 10a3afe81acf8c49afa1dc1bed135bed945ec08a Mon Sep 17 00:00:00 2001 From: shokkunrf <19404989+shokkunrf@users.noreply.github.com> Date: Sat, 23 May 2026 17:21:27 +0000 Subject: [PATCH 1/4] Add shokkunrf base and python-feature scenarios to feature tests --- features/test/bun/scenarios.json | 7 +++++++ features/test/bun/shokkunrf-base.sh | 1 + features/test/claude-code/scenarios.json | 7 +++++++ features/test/claude-code/shokkunrf-base.sh | 1 + .../devcontainer-base-debian-with-python.sh | 1 + features/test/gcloud/scenarios.json | 15 +++++++++++++++ features/test/gcloud/shokkunrf-base.sh | 1 + features/test/node-packages/scenarios.json | 9 +++++++++ features/test/node-packages/shokkunrf-base.sh | 1 + features/test/wd/scenarios.json | 7 +++++++ features/test/wd/shokkunrf-base.sh | 1 + 11 files changed, 51 insertions(+) create mode 120000 features/test/bun/shokkunrf-base.sh create mode 120000 features/test/claude-code/shokkunrf-base.sh create mode 120000 features/test/gcloud/devcontainer-base-debian-with-python.sh create mode 120000 features/test/gcloud/shokkunrf-base.sh create mode 120000 features/test/node-packages/shokkunrf-base.sh create mode 120000 features/test/wd/shokkunrf-base.sh diff --git a/features/test/bun/scenarios.json b/features/test/bun/scenarios.json index b10a777..986d8b8 100644 --- a/features/test/bun/scenarios.json +++ b/features/test/bun/scenarios.json @@ -25,5 +25,12 @@ "bun": {} }, "remoteUser": "vscode" + }, + "shokkunrf-base": { + "image": "ghcr.io/shokkunrf/devcontainer-images/base:latest", + "features": { + "bun": {} + }, + "remoteUser": "developer" } } diff --git a/features/test/bun/shokkunrf-base.sh b/features/test/bun/shokkunrf-base.sh new file mode 120000 index 0000000..61a58b0 --- /dev/null +++ b/features/test/bun/shokkunrf-base.sh @@ -0,0 +1 @@ +test.sh \ No newline at end of file diff --git a/features/test/claude-code/scenarios.json b/features/test/claude-code/scenarios.json index 3b75066..0f49e4d 100644 --- a/features/test/claude-code/scenarios.json +++ b/features/test/claude-code/scenarios.json @@ -25,5 +25,12 @@ "claude-code": {} }, "remoteUser": "vscode" + }, + "shokkunrf-base": { + "image": "ghcr.io/shokkunrf/devcontainer-images/base:latest", + "features": { + "claude-code": {} + }, + "remoteUser": "developer" } } diff --git a/features/test/claude-code/shokkunrf-base.sh b/features/test/claude-code/shokkunrf-base.sh new file mode 120000 index 0000000..61a58b0 --- /dev/null +++ b/features/test/claude-code/shokkunrf-base.sh @@ -0,0 +1 @@ +test.sh \ No newline at end of file diff --git a/features/test/gcloud/devcontainer-base-debian-with-python.sh b/features/test/gcloud/devcontainer-base-debian-with-python.sh new file mode 120000 index 0000000..61a58b0 --- /dev/null +++ b/features/test/gcloud/devcontainer-base-debian-with-python.sh @@ -0,0 +1 @@ +test.sh \ No newline at end of file diff --git a/features/test/gcloud/scenarios.json b/features/test/gcloud/scenarios.json index a53c886..47ef836 100644 --- a/features/test/gcloud/scenarios.json +++ b/features/test/gcloud/scenarios.json @@ -13,6 +13,14 @@ }, "remoteUser": "vscode" }, + "devcontainer-base-debian-with-python": { + "image": "mcr.microsoft.com/devcontainers/base:debian", + "features": { + "ghcr.io/devcontainers/features/python:1": {}, + "gcloud": {} + }, + "remoteUser": "vscode" + }, "devcontainer-base-ubuntu-root": { "image": "mcr.microsoft.com/devcontainers/base:ubuntu", "features": { @@ -25,5 +33,12 @@ "gcloud": {} }, "remoteUser": "vscode" + }, + "shokkunrf-base": { + "image": "ghcr.io/shokkunrf/devcontainer-images/base:latest", + "features": { + "gcloud": {} + }, + "remoteUser": "developer" } } diff --git a/features/test/gcloud/shokkunrf-base.sh b/features/test/gcloud/shokkunrf-base.sh new file mode 120000 index 0000000..61a58b0 --- /dev/null +++ b/features/test/gcloud/shokkunrf-base.sh @@ -0,0 +1 @@ +test.sh \ No newline at end of file diff --git a/features/test/node-packages/scenarios.json b/features/test/node-packages/scenarios.json index 933c858..49def7f 100644 --- a/features/test/node-packages/scenarios.json +++ b/features/test/node-packages/scenarios.json @@ -63,5 +63,14 @@ } }, "remoteUser": "node" + }, + "shokkunrf-base": { + "image": "ghcr.io/shokkunrf/devcontainer-images/base:latest", + "features": { + "node-packages": { + "packages": "@devcontainers/cli,prettier,@google/gemini-cli" + } + }, + "remoteUser": "developer" } } diff --git a/features/test/node-packages/shokkunrf-base.sh b/features/test/node-packages/shokkunrf-base.sh new file mode 120000 index 0000000..61a58b0 --- /dev/null +++ b/features/test/node-packages/shokkunrf-base.sh @@ -0,0 +1 @@ +test.sh \ No newline at end of file diff --git a/features/test/wd/scenarios.json b/features/test/wd/scenarios.json index 2e4be4c..cdd8d5c 100644 --- a/features/test/wd/scenarios.json +++ b/features/test/wd/scenarios.json @@ -21,5 +21,12 @@ "wd": {} }, "remoteUser": "vscode" + }, + "shokkunrf-base": { + "image": "ghcr.io/shokkunrf/devcontainer-images/base:latest", + "features": { + "wd": {} + }, + "remoteUser": "developer" } } diff --git a/features/test/wd/shokkunrf-base.sh b/features/test/wd/shokkunrf-base.sh new file mode 120000 index 0000000..61a58b0 --- /dev/null +++ b/features/test/wd/shokkunrf-base.sh @@ -0,0 +1 @@ +test.sh \ No newline at end of file From deb60934907f45445afb135b2442cc2c66701fdf Mon Sep 17 00:00:00 2001 From: shokkunrf <19404989+shokkunrf@users.noreply.github.com> Date: Sat, 23 May 2026 17:21:34 +0000 Subject: [PATCH 2/4] Run feature CI tests on both amd64 and arm64 --- .github/workflows/ci-test-features.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-test-features.yml b/.github/workflows/ci-test-features.yml index a2958d1..cdc85c5 100644 --- a/.github/workflows/ci-test-features.yml +++ b/.github/workflows/ci-test-features.yml @@ -37,11 +37,17 @@ jobs: test: needs: detect - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: feature: ${{ fromJson(needs.detect.outputs.features) }} + arch: [amd64, arm64] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm steps: - name: Checkout uses: actions/checkout@v6 From c02f6641ece0f4109686d4b0fa49f6d659b7ecf6 Mon Sep 17 00:00:00 2001 From: shokkunrf <19404989+shokkunrf@users.noreply.github.com> Date: Sat, 23 May 2026 17:21:43 +0000 Subject: [PATCH 3/4] Detect changed features from features/test/ changes too --- .github/workflows/ci-test-features.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-test-features.yml b/.github/workflows/ci-test-features.yml index cdc85c5..1fddd55 100644 --- a/.github/workflows/ci-test-features.yml +++ b/.github/workflows/ci-test-features.yml @@ -29,9 +29,9 @@ jobs: features=$(ls -d features/src/*/ | xargs -n1 basename | jq -R -s -c 'split("\n")[:-1]') elif [ "${{ github.event_name }}" = "pull_request" ]; then base="${{ github.event.pull_request.base.sha }}" - features=$(git diff --name-only "$base" HEAD -- features/src/ | cut -d/ -f3 | sort -u | jq -R -s -c 'split("\n")[:-1]') + features=$(git diff --name-only "$base" HEAD -- features/src/ features/test/ | cut -d/ -f3 | sort -u | jq -R -s -c 'split("\n")[:-1]') else - features=$(git diff --name-only "${{ github.event.before }}" HEAD -- features/src/ | cut -d/ -f3 | sort -u | jq -R -s -c 'split("\n")[:-1]') + features=$(git diff --name-only "${{ github.event.before }}" HEAD -- features/src/ features/test/ | cut -d/ -f3 | sort -u | jq -R -s -c 'split("\n")[:-1]') fi echo "features=$features" >> $GITHUB_OUTPUT From 6d5c880f1c84e8dd3c4279f67103ec7103704f1e Mon Sep 17 00:00:00 2001 From: shokkunrf <19404989+shokkunrf@users.noreply.github.com> Date: Sat, 23 May 2026 17:22:01 +0000 Subject: [PATCH 4/4] Use system python3 for gcloud install on all architectures --- features/src/gcloud/README.md | 4 ++-- features/src/gcloud/devcontainer-feature.json | 2 +- features/src/gcloud/install.sh | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/features/src/gcloud/README.md b/features/src/gcloud/README.md index 17b3e37..084dd62 100644 --- a/features/src/gcloud/README.md +++ b/features/src/gcloud/README.md @@ -13,8 +13,8 @@ Installs [Google Cloud CLI](https://cloud.google.com/sdk/gcloud) via the officia ## Requirements - `curl` and `tar` must be available in the container -- Linux (x86_64 or aarch64) -- aarch64: Python 3.9-3.14 must be installed (x86_64 bundles Python) +- Linux x86_64 or aarch64 (glibc-based; Alpine/musl is not supported) +- A Python 3 with the `sqlite3` stdlib module. If missing, the feature installs `python3` via `apt-get` (tested on Debian and Ubuntu). If a `python` feature is also added, its Python is reused. ## Using host credentials diff --git a/features/src/gcloud/devcontainer-feature.json b/features/src/gcloud/devcontainer-feature.json index ded28e3..ba19dbd 100644 --- a/features/src/gcloud/devcontainer-feature.json +++ b/features/src/gcloud/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "gcloud", - "version": "1.0.0", + "version": "1.0.1", "name": "Google Cloud CLI", "documentationURL": "https://github.com/shokkunrf/devcontainer/tree/develop/features/src/gcloud/README.md", "description": "Installs Google Cloud CLI via the official tarball", diff --git a/features/src/gcloud/install.sh b/features/src/gcloud/install.sh index ee8fc7c..9e2a04c 100755 --- a/features/src/gcloud/install.sh +++ b/features/src/gcloud/install.sh @@ -1,6 +1,7 @@ #!/bin/sh # References: # - https://cloud.google.com/sdk/docs/install-sdk +# - https://github.com/GoogleCloudPlatform/cloud-sdk-docker set -eu @@ -17,10 +18,29 @@ case "$ARCH" in ;; esac +# gcloud needs a system python3 with the sqlite3 stdlib module +# (arm tarball ships no bundled Python; some minimal images ship python3 without libsqlite3). +if ! command -v python3 >/dev/null 2>&1 || ! python3 -c 'import sqlite3' >/dev/null 2>&1; then + if ! command -v apt-get >/dev/null 2>&1; then + echo "ERROR: python3 with sqlite3 is required but apt-get is not available" + exit 1 + fi + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y --no-install-recommends python3 libsqlite3-0 + rm -rf /var/lib/apt/lists/* +fi + INSTALL_DIR="/usr/local" TARBALL="google-cloud-cli-linux-${ARCH_SUFFIX}.tar.gz" curl -fsSL "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/${TARBALL}" | tar -xz -C "$INSTALL_DIR" +# Drop the x86_64-only bundled Python so every arch uses the system one. +rm -rf "${INSTALL_DIR}/google-cloud-sdk/platform/bundledpythonunix" + +CLOUDSDK_PYTHON="$(command -v python3)" +export CLOUDSDK_PYTHON + "${INSTALL_DIR}/google-cloud-sdk/install.sh" --quiet --path-update false --command-completion false ln -s "${INSTALL_DIR}/google-cloud-sdk/bin/gcloud" /usr/local/bin/gcloud