diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 5896660..889c08e 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -87,6 +87,8 @@ jobs: baseImage: mcr.microsoft.com/devcontainers/base:debian - features: github-dev baseImage: mcr.microsoft.com/devcontainers/base:ubuntu + - features: mistral-dev + baseImage: ubuntu:latest outputs: status: ${{ steps.status.outputs.status }} @@ -104,6 +106,11 @@ jobs: # before the test runs (same pattern as dotfiles-sync below). run: mkdir -p ~/.claude + - name: Create mount sources for mistral-dev + if: matrix.features == 'mistral-dev' + # The bind mount source ~/.vibe must exist on the host or `docker run` aborts. + run: mkdir -p ~/.vibe + - name: Create mount sources for dotfiles-sync if: matrix.features == 'dotfiles-sync' # All bind sources declared in src/dotfiles-sync/devcontainer-feature.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index da8fab7..4201e7c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,6 +67,10 @@ jobs: - features: claude-dev baseImage: ubuntu:latest + # mistral-dev — IDE-config-only feature + - features: mistral-dev + baseImage: ubuntu:latest + # auto-header - requires jq (installed by helpers4-common) - features: auto-header baseImage: mcr.microsoft.com/devcontainers/base:ubuntu @@ -102,6 +106,11 @@ jobs: # before the test runs (same pattern as dotfiles-sync below). run: mkdir -p ~/.claude + - name: Create mount sources for mistral-dev + if: matrix.features == 'mistral-dev' + # The bind mount source ~/.vibe must exist on the host or `docker run` aborts. + run: mkdir -p ~/.vibe + - name: Create mount sources for dotfiles-sync if: matrix.features == 'dotfiles-sync' # All bind sources declared in src/dotfiles-sync/devcontainer-feature.json diff --git a/src/claude-dev/devcontainer-feature.json b/src/claude-dev/devcontainer-feature.json index 66342ef..fecffe5 100644 --- a/src/claude-dev/devcontainer-feature.json +++ b/src/claude-dev/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "claude-dev", - "version": "1.0.2", + "version": "1.0.3", "name": "Claude Code Development Environment", "description": "Installs the Claude Code IDE extension (anthropic.claude-code) for VS Code and Cursor. Mounts ~/.claude from the host via a directory symlink — credentials and config persist across all rebuilds.", "documentationURL": "https://github.com/helpers4/devcontainer/tree/main/src/claude-dev", @@ -19,6 +19,10 @@ "description": "Username in the container that should receive the Claude credentials symlink." } }, + // Creates ~/.claude on the host before Docker evaluates the bind mount. + // Without this, Docker refuses to start the container if the directory + // has never been created (e.g. fresh OS install, first Claude login). + "initializeCommand": "mkdir -p ~/.claude", "mounts": [ { // Neutral staging path — install.sh resolves the correct target home at build diff --git a/src/mistral-dev/devcontainer-feature.json b/src/mistral-dev/devcontainer-feature.json index 753a66c..bda2179 100644 --- a/src/mistral-dev/devcontainer-feature.json +++ b/src/mistral-dev/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "mistral-dev", - "version": "1.0.0", + "version": "1.0.1", "name": "Mistral Vibe Development Environment", "description": "Installs the Mistral Vibe IDE extension (mistralai.mistral-vibe-code) for VS Code and Cursor. Mounts ~/.vibe from the host via a directory symlink — credentials and config persist across all rebuilds.", "documentationURL": "https://github.com/helpers4/devcontainer/tree/main/src/mistral-dev", @@ -24,6 +24,10 @@ "description": "Also install the Mistral Vibe CLI (vibe command). Requires Python 3.12+ and pip in the container." } }, + // Creates ~/.vibe on the host before Docker evaluates the bind mount. + // Without this, Docker refuses to start the container if the directory + // has never been created (e.g. fresh OS install, first Mistral login). + "initializeCommand": "mkdir -p ~/.vibe", "mounts": [ { // Neutral staging path — install.sh resolves the correct target home at build diff --git a/test/mistral-dev/test.sh b/test/mistral-dev/test.sh new file mode 100755 index 0000000..1cbd23e --- /dev/null +++ b/test/mistral-dev/test.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -e + +SCRIPT="/usr/local/share/mistral-dev/setup-credentials.sh" + +if [ ! -f "${SCRIPT}" ]; then + echo "❌ FAIL: ${SCRIPT} is missing" + exit 1 +fi + +if [ ! -x "${SCRIPT}" ]; then + echo "❌ FAIL: ${SCRIPT} is not executable" + exit 1 +fi + +if ! grep -q '^TARGET_HOME=' "${SCRIPT}"; then + echo "❌ FAIL: TARGET_HOME not baked into ${SCRIPT}" + exit 1 +fi + +if ! grep -q 'STAGED="/mnt/h4vibe"' "${SCRIPT}"; then + echo "❌ FAIL: STAGED not baked into ${SCRIPT}" + exit 1 +fi + +if ! grep -q 'ln -sf' "${SCRIPT}"; then + echo "❌ FAIL: symlink creation not baked into ${SCRIPT}" + exit 1 +fi + +echo "✅ PASS: setup-credentials.sh installed, executable, and all required values baked in" +echo "🎉 Test passed."