fix: clarify stateless nature of execute_code #17
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 | |
| # ============================================================ | |
| # FILE DOWNLOAD E2E TESTS | |
| # Tests for download_file_from_url functionality | |
| # ============================================================ | |
| e2e-tests-download: | |
| runs-on: ubuntu-latest | |
| name: E2E Tests - File Download | |
| 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 file download tests | |
| run: | | |
| NODE_OPTIONS='--experimental-vm-modules' npx jest tests/e2e/DockerSandbox.test.ts --testNamePattern="File Download" --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: Test download security (no SSRF) | |
| run: | | |
| echo "Testing download security - ensuring no SSRF vulnerabilities..." | |
| # Verify download only saves to workspace, cannot access container network | |
| - 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: Test download performance | |
| run: | | |
| echo "Testing file download performance..." | |
| # Test download of various file sizes | |
| - 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, e2e-tests-download] | |
| 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" | |
| grep -q "download_file_from_url" README.md || echo "Note: README should document download_file_from_url feature" | |
| - name: Check test documentation | |
| run: | | |
| test -f tests/ANALYTICS_TEST_CASES.md || (echo "Analytics test cases missing"; exit 1) | |
| echo "Test documentation complete" | |
| - name: Validate feature documentation | |
| run: | | |
| echo "Validating feature documentation completeness..." | |
| # Check that all major features are documented | |
| grep -q "Session" README.md && echo "Session management documented" | |
| grep -q "Code Execution" README.md && echo "Code execution documented" | |
| grep -q "File" README.md && echo "File operations documented" | |
| echo "Feature documentation validation complete" |