feat: initial Claude Code DevContainer Feature implementation #14
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: "Test" | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main, develop] | |
| concurrency: | |
| group: "${{ github.workflow }}-${{ github.ref }}" | |
| cancel-in-progress: true | |
| permissions: {} | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: ShellCheck | |
| uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0 | |
| with: | |
| severity: warning | |
| - name: Validate JSON | |
| run: | | |
| FAIL=0 | |
| while IFS= read -r -d '' f; do | |
| if ! python3 -m json.tool "$f" > /dev/null 2>&1; then | |
| echo "ERROR: Invalid JSON: $f" | |
| FAIL=1 | |
| fi | |
| done < <(find . -name '*.json' -not -path './.git/*' -print0) | |
| exit "$FAIL" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 | |
| - name: Validate YAML | |
| run: | | |
| uvx [email protected] -d relaxed .github/workflows/ | |
| - name: Prettier check | |
| run: | | |
| npx [email protected] --check "**/*.{json,yml,yaml,md}" --ignore-path .gitignore | |
| - name: Markdownlint | |
| run: | | |
| npx [email protected] "**/*.md" --ignore node_modules | |
| - name: shfmt format check | |
| run: | | |
| curl -fsSL https://github.com/mvdan/sh/releases/download/v3.13.0/shfmt_v3.13.0_linux_amd64 \ | |
| -o /usr/local/bin/shfmt && chmod +x /usr/local/bin/shfmt | |
| shfmt -ln bash -d -i 4 -ci src/ test/ | |
| - name: Check .sh files are executable | |
| run: | | |
| FAIL=0 | |
| while IFS= read -r -d '' f; do | |
| if [[ ! -x "$f" ]]; then | |
| echo "ERROR: $f is not executable" | |
| FAIL=1 | |
| fi | |
| done < <(find . -name '*.sh' -not -path './.git/*' -print0) | |
| exit "$FAIL" | |
| # Run all per-scenario tests (options-specific assertions) | |
| test-scenarios: | |
| needs: lint | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 # 10 scenarios building containers takes time | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Install devcontainer CLI | |
| run: npm install -g @devcontainers/[email protected] | |
| - name: Run all scenarios | |
| run: | | |
| devcontainer features test --project-folder . 2>&1 | tee /tmp/scenario-test-output.log | |
| # Workaround: devcontainers/[email protected] exits 0 even when feature install fails. | |
| # Grep for known failure strings and fail explicitly. Revisit on CLI upgrade. | |
| if grep -qE "Exit code [1-9][0-9]*|failed to install|Failed to launch|Failed:| FAIL:" /tmp/scenario-test-output.log; then | |
| echo "ERROR: Test output contains failures." | |
| exit 1 | |
| fi | |
| - name: Upload logs on failure | |
| if: failure() | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: logs-scenarios | |
| path: /tmp/scenario-test-output.log | |
| retention-days: 7 | |
| # Run core assertions across all supported base images | |
| test-image-matrix: | |
| needs: lint | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 10 | |
| matrix: | |
| image: | |
| # Raw OS images | |
| - "ubuntu:22.04" | |
| - "ubuntu:24.04" | |
| - "debian:bullseye" | |
| - "debian:bookworm" | |
| - "alpine:3.19" | |
| - "alpine:3.20" | |
| - "alpine:3.21" | |
| - "archlinux:latest" | |
| - "fedora:39" | |
| - "fedora:40" | |
| - "rockylinux:9" | |
| - "almalinux:9" | |
| - "amazonlinux:2023" | |
| # DevContainer base images | |
| - "mcr.microsoft.com/devcontainers/base:debian" | |
| - "mcr.microsoft.com/devcontainers/base:ubuntu" | |
| - "mcr.microsoft.com/devcontainers/base:alpine" | |
| - "mcr.microsoft.com/devcontainers/universal:2" | |
| # Language-specific images | |
| - "mcr.microsoft.com/devcontainers/python" | |
| - "mcr.microsoft.com/devcontainers/javascript-node" | |
| - "mcr.microsoft.com/devcontainers/typescript-node" | |
| - "mcr.microsoft.com/devcontainers/rust" | |
| - "mcr.microsoft.com/devcontainers/go" | |
| - "mcr.microsoft.com/devcontainers/cpp" | |
| - "mcr.microsoft.com/devcontainers/dotnet" | |
| - "mcr.microsoft.com/devcontainers/java" | |
| - "mcr.microsoft.com/devcontainers/ruby" | |
| - "mcr.microsoft.com/devcontainers/php" | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Install devcontainer CLI | |
| run: npm install -g @devcontainers/[email protected] | |
| - name: Test on ${{ matrix.image }} | |
| run: | | |
| devcontainer features test \ | |
| --features claude-code \ | |
| --skip-scenarios \ | |
| --base-image "${{ matrix.image }}" \ | |
| --project-folder . 2>&1 | tee /tmp/test-output.log | |
| # Workaround: devcontainers/[email protected] exits 0 even when feature install fails. | |
| # Grep for known failure strings and fail explicitly. Revisit on CLI upgrade. | |
| if grep -qE "Exit code [1-9][0-9]*|failed to install|Failed to launch|Failed:| FAIL:" /tmp/test-output.log; then | |
| echo "ERROR: Test output contains failures." | |
| exit 1 | |
| fi | |
| - name: Upload logs on failure | |
| if: failure() | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: logs-amd64-${{ strategy.job-index }} | |
| path: /tmp/test-output.log | |
| retention-days: 7 | |
| # arm64 tests via QEMU emulation on standard ubuntu-latest runners | |
| test-arm64: | |
| needs: lint | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 # QEMU emulation is significantly slower than native | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 2 | |
| matrix: | |
| image: | |
| - "ubuntu:24.04" | |
| - "alpine:3.21" | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up QEMU for arm64 emulation | |
| uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Install devcontainer CLI | |
| run: npm install -g @devcontainers/[email protected] | |
| - name: Test on ${{ matrix.image }} (arm64) | |
| env: | |
| DOCKER_DEFAULT_PLATFORM: linux/arm64 | |
| run: | | |
| devcontainer features test \ | |
| --features claude-code \ | |
| --skip-scenarios \ | |
| --base-image "${{ matrix.image }}" \ | |
| --project-folder . 2>&1 | tee /tmp/test-output.log | |
| # Workaround: devcontainers/[email protected] exits 0 even when feature install fails. | |
| # Grep for known failure strings and fail explicitly. Revisit on CLI upgrade. | |
| if grep -qE "Exit code [1-9][0-9]*|failed to install|Failed to launch|Failed:| FAIL:" /tmp/test-output.log; then | |
| echo "ERROR: Test output contains failures." | |
| exit 1 | |
| fi | |
| - name: Upload logs on failure | |
| if: failure() | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: logs-arm64-${{ strategy.job-index }} | |
| path: /tmp/test-output.log | |
| retention-days: 7 |