fix: Protect Docker image from auto-cleanup and add auto-build #10
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 Suite | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main ] | |
| env: | |
| NODE_VERSION: '20' | |
| POLARS_MAX_THREADS: '4' | |
| DUCKDB_MEMORY_LIMIT: '2GB' | |
| jobs: | |
| # ============================================================ | |
| # UNIT TESTS | |
| # Fast feedback on code changes without Docker | |
| # ============================================================ | |
| unit-tests: | |
| runs-on: ubuntu-latest | |
| name: Unit Tests | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js ${{ env.NODE_VERSION }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build TypeScript | |
| run: npm run build | |
| - name: Run unit tests | |
| run: npm run test:unit | |
| - name: Check TypeScript compilation | |
| run: npx tsc --noEmit | |
| # ============================================================ | |
| # CORE E2E TESTS | |
| # Docker-based integration tests for core functionality | |
| # ============================================================ | |
| e2e-tests-core: | |
| runs-on: ubuntu-latest | |
| name: E2E Tests - Core | |
| needs: unit-tests | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js ${{ env.NODE_VERSION }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build TypeScript | |
| run: npm run build | |
| - name: Build Docker image | |
| run: npm run docker:build | |
| - name: Run core E2E tests | |
| run: NODE_OPTIONS='--experimental-vm-modules' npx jest tests/e2e/MCPServer.test.ts tests/e2e/DockerSandbox.test.ts --testTimeout=120000 | |
| timeout-minutes: 15 | |
| - name: Cleanup Docker containers | |
| if: always() | |
| run: | | |
| docker ps -a --filter "label=mcp-session" -q | xargs -r docker rm -f || true | |
| docker system prune -f | |
| # ============================================================ | |
| # ANALYTICS E2E TESTS | |
| # Tests for analytics functionality (Polars, DuckDB, Pandas) | |
| # ============================================================ | |
| e2e-tests-analytics: | |
| runs-on: ubuntu-latest | |
| name: E2E Tests - Analytics | |
| needs: unit-tests | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js ${{ env.NODE_VERSION }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build TypeScript | |
| run: npm run build | |
| - name: Build Docker image with analytics libraries | |
| run: npm run docker:build | |
| - name: Run analytics E2E tests | |
| run: NODE_OPTIONS='--experimental-vm-modules' npx jest tests/e2e/Analytics.test.ts --testTimeout=180000 | |
| timeout-minutes: 20 | |
| env: | |
| POLARS_MAX_THREADS: ${{ env.POLARS_MAX_THREADS }} | |
| DUCKDB_MEMORY_LIMIT: ${{ env.DUCKDB_MEMORY_LIMIT }} | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: analytics-test-results | |
| path: | | |
| test-results/ | |
| coverage/ | |
| - name: Cleanup Docker containers | |
| if: always() | |
| run: | | |
| docker ps -a --filter "label=mcp-session" -q | xargs -r docker rm -f || true | |
| docker system prune -f | |
| # ============================================================ | |
| # SECURITY TESTS | |
| # Isolation, resource limits, and security scenarios | |
| # ============================================================ | |
| security-tests: | |
| runs-on: ubuntu-latest | |
| name: Security Tests | |
| needs: e2e-tests-core | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js ${{ env.NODE_VERSION }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build TypeScript | |
| run: npm run build | |
| - name: Build Docker image | |
| run: npm run docker:build | |
| - name: Run security tests | |
| run: | | |
| NODE_OPTIONS='--experimental-vm-modules' npx jest tests/e2e --testNamePattern="Security|Isolation|Network|User|Memory" --testTimeout=120000 | |
| timeout-minutes: 10 | |
| - name: Test path traversal prevention | |
| run: | | |
| echo "Testing path traversal protection..." | |
| # This would run specific security test cases | |
| - name: Test resource limits | |
| run: | | |
| echo "Testing resource limit enforcement..." | |
| # Verify memory and CPU limits | |
| - name: Cleanup | |
| if: always() | |
| run: | | |
| docker ps -a --filter "label=mcp-session" -q | xargs -r docker rm -f || true | |
| # ============================================================ | |
| # PERFORMANCE TESTS | |
| # Benchmarks and performance regression detection | |
| # ============================================================ | |
| performance-tests: | |
| runs-on: ubuntu-latest | |
| name: Performance Tests | |
| needs: [e2e-tests-core, e2e-tests-analytics] | |
| if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js ${{ env.NODE_VERSION }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build TypeScript | |
| run: npm run build | |
| - name: Build Docker image | |
| run: npm run docker:build | |
| - name: Run performance benchmarks | |
| run: | | |
| NODE_OPTIONS='--experimental-vm-modules' npx jest tests/e2e/Analytics.test.ts --testNamePattern="Performance" --testTimeout=300000 | |
| timeout-minutes: 10 | |
| - name: Upload performance metrics | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: performance-metrics | |
| path: | | |
| performance-results/ | |
| - name: Cleanup | |
| if: always() | |
| run: | | |
| docker ps -a --filter "label=mcp-session" -q | xargs -r docker rm -f || true | |
| # ============================================================ | |
| # COVERAGE REPORT | |
| # Combined coverage from all test suites | |
| # ============================================================ | |
| coverage: | |
| runs-on: ubuntu-latest | |
| name: Coverage Report | |
| needs: [unit-tests, e2e-tests-core, e2e-tests-analytics] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js ${{ env.NODE_VERSION }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build TypeScript | |
| run: npm run build | |
| - name: Build Docker image | |
| run: npm run docker:build | |
| - name: Run all tests with coverage | |
| run: npm test -- --coverage | |
| timeout-minutes: 20 | |
| - name: Generate coverage report | |
| run: | | |
| echo "## Coverage Summary" > coverage-summary.md | |
| cat coverage/lcov-report/index.html | grep -o '>[0-9]\+%' | head -4 >> coverage-summary.md | |
| - name: Upload coverage report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: | | |
| coverage/ | |
| coverage-summary.md | |
| - name: Check coverage thresholds | |
| run: | | |
| # Extract coverage percentages and check against thresholds | |
| STATEMENTS=$(cat coverage/coverage-summary.json | grep -o '"statements":{"total":[0-9]*,"covered":[0-9]*,"skipped":[0-9]*,"pct":[0-9.]*' | grep -o '"pct":[0-9.]*' | cut -d':' -f2) | |
| BRANCHES=$(cat coverage/coverage-summary.json | grep -o '"branches":{"total":[0-9]*,"covered":[0-9]*,"skipped":[0-9]*,"pct":[0-9.]*' | grep -o '"pct":[0-9.]*' | cut -d':' -f2) | |
| FUNCTIONS=$(cat coverage/coverage-summary.json | grep -o '"functions":{"total":[0-9]*,"covered":[0-9]*,"skipped":[0-9]*,"pct":[0-9.]*' | grep -o '"pct":[0-9.]*' | cut -d':' -f2) | |
| LINES=$(cat coverage/coverage-summary.json | grep -o '"lines":{"total":[0-9]*,"covered":[0-9]*,"skipped":[0-9]*,"pct":[0-9.]*' | grep -o '"pct":[0-9.]*' | cut -d':' -f2) | |
| echo "Statements: ${STATEMENTS}%" | |
| echo "Branches: ${BRANCHES}%" | |
| echo "Functions: ${FUNCTIONS}%" | |
| echo "Lines: ${LINES}%" | |
| # Fail if below thresholds (70%) | |
| if (( $(echo "$STATEMENTS < 70" | bc -l) )); then echo "Statements coverage below 70%"; exit 1; fi | |
| if (( $(echo "$BRANCHES < 70" | bc -l) )); then echo "Branches coverage below 70%"; exit 1; fi | |
| if (( $(echo "$FUNCTIONS < 70" | bc -l) )); then echo "Functions coverage below 70%"; exit 1; fi | |
| if (( $(echo "$LINES < 70" | bc -l) )); then echo "Lines coverage below 70%"; exit 1; fi | |
| - name: Cleanup | |
| if: always() | |
| run: | | |
| docker ps -a --filter "label=mcp-session" -q | xargs -r docker rm -f || true | |
| # ============================================================ | |
| # DOCUMENTATION CHECK | |
| # Verify ADRs and specifications are up to date | |
| # ============================================================ | |
| documentation-check: | |
| runs-on: ubuntu-latest | |
| name: Documentation Check | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Check ADR files exist | |
| run: | | |
| test -f docs/ADR-001-analytics-architecture.md || (echo "ADR-001 missing"; exit 1) | |
| test -f docs/ADR-002-context-management.md || (echo "ADR-002 missing"; exit 1) | |
| test -f docs/ADR-003-caching-optimization.md || (echo "ADR-003 missing"; exit 1) | |
| test -f docs/MCP-SPECIFICATION.md || (echo "MCP-SPECIFICATION missing"; exit 1) | |
| echo "All documentation files present" | |
| - name: Verify README is up to date | |
| run: | | |
| grep -q "Analytics" README.md || echo "Note: README may need analytics section update" | |
| - name: Check test documentation | |
| run: | | |
| test -f tests/ANALYTICS_TEST_CASES.md || (echo "Analytics test cases missing"; exit 1) | |
| echo "Test documentation complete" |