Skip to content
Closed
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
8 changes: 8 additions & 0 deletions .claude/commands/lint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Run linters in current project
Use:

```
make lint
```

Double check all warning and errors, fix errors and warnings, don't ignore warnings as they require fixing same as errors.
8 changes: 8 additions & 0 deletions .claude/commands/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Run unit tests
Use

````
make test
```
Ensure they pass. Double check any error.
````
49 changes: 49 additions & 0 deletions .devcontainer/Dockerfile.devcontainer
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
FROM mcr.microsoft.com/devcontainers/base:debian

# Build arguments
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000

# Install essential development tools for VSCode extension development
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
wget \
curl \
make \
git \
build-essential \
bash-completion \
gnupg \
dirmngr \
unzip \
&& rm -rf /var/lib/apt/lists/*

# Create workspace directory if it doesn't exist
RUN mkdir -p /workspace

# Ensure proper permissions for the vscode user
# The base image already creates the vscode user with UID 1000
RUN if [ "$(getent passwd $USER_UID)" != "" ]; then \
if [ "$USERNAME" != "$(getent passwd $USER_UID | cut -d: -f1)" ]; then \
usermod -l $USERNAME $(getent passwd $USER_UID | cut -d: -f1); \
groupmod -n $USERNAME $(getent group $USER_GID | cut -d: -f1); \
fi; \
fi \
&& chown -R $USERNAME:$USERNAME /workspace

WORKDIR /workspace

# SSH setup for development
RUN mkdir -p /home/$USERNAME/.ssh \
&& touch /home/$USERNAME/.ssh/known_hosts \
&& chown -R $USERNAME:$USERNAME /home/$USERNAME/.ssh \
&& chmod 700 /home/$USERNAME/.ssh \
&& chmod 600 /home/$USERNAME/.ssh/known_hosts

# Switch to non-root user
USER $USERNAME

# Environment variables for development
ENV NODE_ENV=development \
SHELL=/bin/bash
50 changes: 50 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "Claude Runner VSCode Extension",
"build": {
"dockerfile": "./Dockerfile.devcontainer",
"context": "..",
"args": {
"USERNAME": "vscode",
"USER_UID": "1000",
"USER_GID": "1000"
}
},
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "23",
"installTools": true
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12",
"installTools": true
}
},
"customizations": {
"vscode": {
"settings": {
"typescript.preferences.includePackageJsonAutoImports": "auto",
"npm.packageManager": "npm",
"eslint.validate": ["typescript", "typescriptreact"],
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
},
"extensions": [
"ms-vscode.vscode-typescript-next",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"ms-vscode.extension-test-runner",
"ms-vscode.vscode-json",
"bradlc.vscode-tailwindcss",
"formulahendry.auto-rename-tag",
"christian-kohler.path-intellisense"
]
}
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace/,type=bind,consistency=cached",
"workspaceFolder": "/workspace/",
"remoteUser": "vscode",
"postCreateCommand": ".devcontainer/postinstall.sh"
}
26 changes: 26 additions & 0 deletions .devcontainer/postinstall.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

npm install
npm run setup

# Setup Claude configuration directory
mkdir -p /workspace/.claude
ln -sf /workspace/.claude /home/vscode/.claude 2>/dev/null || true

# Install Claude Code CLI globally for testing
npm install -g @anthropic-ai/claude-code

# Add useful aliases for development
echo 'alias ll="ls -alF"' >> ~/.bashrc
echo 'alias cl="claude --dangerously-skip-permissions"' >> ~/.bashrc
echo 'export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1' >> ~/.bashrc

# Setup SonarQube Scanner (optional for code quality)
if [ -f .sonar ]; then
export SONAR_SCANNER_VERSION=7.0.2.4839
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux-x64
curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux-x64.zip
unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
echo 'export PATH=$HOME/.sonar/sonar-scanner-'$SONAR_SCANNER_VERSION'-linux-x64/bin:$PATH' >> ~/.bashrc
fi
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@typescript-eslint/consistent-type-definitions": ["error", "interface"],
"@typescript-eslint/prefer-readonly": "warn"
},
"ignorePatterns": ["out", "dist", "**/*.d.ts"],
"ignorePatterns": ["out", "dist", "**/*.d.ts", "docs/**"],
"env": {
"node": true,
"es6": true
Expand Down
90 changes: 90 additions & 0 deletions .github/workflows/docker-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Docker E2E Tests

on:
workflow_dispatch:
schedule:
- cron: '0 2 * * 0' # Weekly on Sunday at 2 AM
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
docker-e2e-tests:
name: "Docker E2E Tests"
runs-on: ubuntu-latest

strategy:
matrix:
test-phase:
- name: "without-claude-cli"
install-claude: false
description: "Test extension when Claude CLI not installed"
- name: "with-claude-cli"
install-claude: true
description: "Test extension when Claude CLI is installed"

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build test Docker image
run: |
docker build -f docker/Dockerfile.test -t claude-runner-test:${{ matrix.test-phase.name }} .

- name: Run tests in Docker container
run: |
docker run --rm \
-e TEST_PHASE="${{ matrix.test-phase.name }}" \
-e INSTALL_CLAUDE="${{ matrix.test-phase.install-claude }}" \
--name claude-test-${{ matrix.test-phase.name }} \
claude-runner-test:${{ matrix.test-phase.name }}

- name: Extract test artifacts
if: always()
run: |
mkdir -p test-results/${{ matrix.test-phase.name }}
docker create --name extract claude-runner-test:${{ matrix.test-phase.name }}
docker cp extract:/workspace/dist/ test-results/${{ matrix.test-phase.name }}/
docker rm extract

- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: docker-test-${{ matrix.test-phase.name }}
path: test-results/
retention-days: 7

docker-test-summary:
name: "Docker Test Summary"
runs-on: ubuntu-latest
needs: docker-e2e-tests
if: always()

steps:
- name: Generate Docker Test Report
run: |
echo "Docker E2E Test Results" >> $GITHUB_STEP_SUMMARY
echo "=======================" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Test Phases:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Without Claude CLI:" >> $GITHUB_STEP_SUMMARY
echo "- Tests extension detection of missing Claude CLI" >> $GITHUB_STEP_SUMMARY
echo "- Verifies graceful handling of missing dependencies" >> $GITHUB_STEP_SUMMARY
echo "- Runs core unit and main window tests" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "With Claude CLI:" >> $GITHUB_STEP_SUMMARY
echo "- Installs Claude CLI via npm" >> $GITHUB_STEP_SUMMARY
echo "- Tests full integration capabilities" >> $GITHUB_STEP_SUMMARY
echo "- Runs comprehensive E2E test suite" >> $GITHUB_STEP_SUMMARY
echo "- Validates CLI detection and functionality" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Environment:" >> $GITHUB_STEP_SUMMARY
echo "- Docker containers for isolation" >> $GITHUB_STEP_SUMMARY
echo "- Xvfb for headless VS Code testing" >> $GITHUB_STEP_SUMMARY
echo "- VSIX package building and installation" >> $GITHUB_STEP_SUMMARY
119 changes: 119 additions & 0 deletions .github/workflows/test-pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: Claude Runner Extension Tests

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:

jobs:
test-without-claude:
name: "Test Extension without Claude CLI"
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install system dependencies
run: make setup-ci

- name: Setup project
run: make setup

- name: Build and validate extension
run: |
make lint
make build-vsix

- name: Run tests without Claude CLI
run: |
make setup-test-env
make test-ci-without-claude
timeout-minutes: 15

- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: claude-runner.vsix
path: dist/*.vsix
retention-days: 1

test-with-claude:
name: "Test Extension with Claude CLI"
runs-on: ubuntu-latest
needs: test-without-claude

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install system dependencies
run: make setup-ci

- name: Setup project
run: make setup

- name: Download VSIX artifact
uses: actions/download-artifact@v4
with:
name: claude-runner.vsix
path: dist/

- name: Build extension for testing
run: make build

- name: Install and configure Claude CLI
run: |
make install-claude-cli
make setup-claude-config

- name: Run tests with Claude CLI
run: |
make setup-test-env
make test-ci-with-claude
timeout-minutes: 20

test-report:
name: "Generate Test Report"
runs-on: ubuntu-latest
needs: [test-without-claude, test-with-claude]
if: always()

steps:
- name: Generate Test Summary
run: |
echo "Claude Runner Extension Test Results" >> $GITHUB_STEP_SUMMARY
echo "=====================================" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ needs.test-without-claude.result }}" == "success" ]; then
echo "Extension tests without Claude CLI - PASSED" >> $GITHUB_STEP_SUMMARY
else
echo "Extension tests without Claude CLI - FAILED" >> $GITHUB_STEP_SUMMARY
fi

if [ "${{ needs.test-with-claude.result }}" == "success" ]; then
echo "Extension tests with Claude CLI - PASSED" >> $GITHUB_STEP_SUMMARY
else
echo "Extension tests with Claude CLI - FAILED" >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
echo "Test Coverage:" >> $GITHUB_STEP_SUMMARY
echo "- Unit Tests" >> $GITHUB_STEP_SUMMARY
echo "- Main Window Loading Tests" >> $GITHUB_STEP_SUMMARY
echo "- Claude CLI Detection Tests" >> $GITHUB_STEP_SUMMARY
echo "- Claude CLI Integration Tests" >> $GITHUB_STEP_SUMMARY
echo "- End-to-End Workflow Tests" >> $GITHUB_STEP_SUMMARY
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ extension.js.map
webview.js.map
webview.css.map
.claude/pipeline-logs/*
!tests/fixtures/logs/**

# SonarQube configuration (contains sensitive data)
.scannerwork/
.sonar
.sonar
!.vscode/settings.json

# CSS Analysis Reports
css-analysis-report.json
2 changes: 1 addition & 1 deletion .sonar.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SonarQube Configuration
# Copy this file to .sonar and replace with your actual values
SONAR_HOST_URL=https://sonarqube.114.be.tn
SONAR_LOGIN=your-sonar-token-here
SONAR_TOKEN=your-sonar-token-here
Loading