Files
proffesor-for-testing__agen…/.github/workflows/mcp-tools-test.yml
Dragan Spiridonov 8eb060b6e2 ci(mcp): make the MCP integration regression tests actually run (C3)
The #528 and #535 integration tests (tests/integration/mcp, gated on
describe.skipIf(!BUILT)) never executed in CI — a false green:
- the mcp-integration-tests job ran `npm ci` but no `npm run build`, so the
  dist bundles were absent and both tests silently skipped;
- the step was `continue-on-error: true`, so even a real failure passed;
- neither test was in the release gate's test:integration:fast list.

Fixes:
- mcp-tools-test.yml: add `npm run build` before test:mcp:integration and drop
  continue-on-error so the job is a real gate (the exit-124 hang tolerance
  stays for the known vitest-hang flake).
- both tests: skip only for LOCAL unbuilt checkouts (`!BUILT && !process.env.CI`)
  — in CI a missing build now fails loudly instead of skipping. Verified:
  CI=1 with the bundle removed fails the suite instead of reporting green.
- package.json: add both tests to test:integration:fast so they also run on the
  release gate (npm-publish.yml), which builds first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:46:16 +00:00

271 lines
8.8 KiB
YAML

name: MCP Tools Testing
permissions:
contents: read
actions: write
issues: write
pull-requests: write
checks: write
on:
push:
branches: [main, testing-with-qe]
paths:
- 'src/mcp/**'
- 'tests/mcp/**'
- 'tests/integration/mcp/**'
- 'package.json'
- 'package-lock.json'
pull_request:
branches: [main]
paths:
- 'src/mcp/**'
- 'tests/mcp/**'
- 'tests/integration/mcp/**'
- 'package.json'
# On PRs: cancel stale runs when a new push arrives (old run is obsolete).
# On main: never cancel — every push must run to completion for accurate CI signal.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# Split MCP unit tests into parallel shards by subdirectory.
# Previously ran as one sequential job hitting the 30-min timeout.
# Now each shard runs in ~8-12 min instead of ~25 min total.
mcp-unit-handlers:
name: MCP Units — Handlers
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '24.13.0', cache: 'npm' }
- run: npm ci
- run: npm run build
- name: Run handler tests
run: bash scripts/ci-vitest-run.sh tests/unit/mcp/handlers/ --fileParallelism=false --reporter=verbose
env:
NODE_OPTIONS: '--max-old-space-size=1024'
- uses: actions/upload-artifact@v4
if: always()
with:
name: mcp-unit-handlers-results
path: junit.xml
retention-days: 14
mcp-unit-security:
name: MCP Units — Security
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '24.13.0', cache: 'npm' }
- run: npm ci
- run: npm run build
- name: Run security tests
run: timeout 480 npx vitest run tests/unit/mcp/security/ --fileParallelism=false --reporter=verbose
env:
NODE_OPTIONS: '--max-old-space-size=1024'
- uses: actions/upload-artifact@v4
if: always()
with:
name: mcp-unit-security-results
path: junit.xml
retention-days: 14
mcp-unit-tools-transport:
name: MCP Units — Tools + Transport + Metrics
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '24.13.0', cache: 'npm' }
- run: npm ci
- run: npm run build
- name: Run tools, transport, metrics tests
run: >-
timeout 480 npx vitest run
tests/unit/mcp/tools/
tests/unit/mcp/transport/
tests/unit/mcp/metrics/
--fileParallelism=false
--reporter=verbose
env:
NODE_OPTIONS: '--max-old-space-size=1024'
- uses: actions/upload-artifact@v4
if: always()
with:
name: mcp-unit-tools-transport-results
path: junit.xml
retention-days: 14
mcp-unit-root:
name: MCP Units — Root Files
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '24.13.0', cache: 'npm' }
- run: npm ci
- run: npm run build
- name: Run root-level MCP tests
run: >-
bash scripts/ci-vitest-run.sh
tests/unit/mcp/mcp-server.test.ts
tests/unit/mcp/mcp-performance-benchmark.test.ts
tests/unit/mcp/tool-registry-security.test.ts
tests/unit/mcp/tool-scoping.test.ts
tests/unit/mcp/wrapped-domain-handlers.test.ts
--fileParallelism=false
--reporter=verbose
env:
NODE_OPTIONS: '--max-old-space-size=1024'
- uses: actions/upload-artifact@v4
if: always()
with:
name: mcp-unit-root-results
path: junit.xml
retention-days: 14
mcp-integration-tests:
name: MCP Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '24.13.0', cache: 'npm' }
- run: npm ci
# C3: integration tests under tests/integration/mcp drive the BUILT
# bundles (dist/cli + dist/mcp). Without this build step they were
# silently skipping (describe.skipIf(!BUILT)) — a false green.
- run: npm run build
- name: Run MCP integration tests
run: |
timeout 480 npm run test:mcp:integration; EXIT=$?
if [ $EXIT -eq 124 ] && [ -f junit.xml ]; then
FAILURES=$(grep -c '<failure' junit.xml 2>/dev/null || echo "0")
if [ "$FAILURES" = "0" ]; then
echo "::warning::Vitest hung after tests passed (exit 124). Treating as success."
exit 0
fi
fi
exit $EXIT
env:
NODE_OPTIONS: '--max-old-space-size=1024'
# C3: was `continue-on-error: true`, which let real failures pass as
# green. Removed so this job is an actual gate. The exit-124 hang
# tolerance above still absorbs the known vitest-hang flake.
- name: Generate test report
uses: dorny/test-reporter@v1
if: always() && hashFiles('junit.xml') != ''
continue-on-error: true
with:
name: MCP Integration Test Results
path: 'junit.xml'
reporter: jest-junit
fail-on-error: false
fail-on-empty: false
- uses: actions/upload-artifact@v4
if: always()
with:
name: mcp-integration-test-results
path: |
test-results/
junit.xml
retention-days: 30
mcp-validation:
name: Validate All MCP Tools
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '24.13.0', cache: 'npm' }
- run: npm ci
- run: npm run build
- name: Validate MCP tools
run: timeout 480 npm run mcp:validate
continue-on-error: true
- uses: actions/upload-artifact@v4
if: always()
with:
name: mcp-validation-report
path: reports/mcp-validation-*.json
retention-days: 30
- name: Generate MCP report
run: timeout 480 npm run mcp:report
if: always()
- uses: actions/upload-artifact@v4
if: always()
with:
name: mcp-report
path: reports/mcp-report-*.md
retention-days: 30
mcp-summary:
name: MCP Test Summary
runs-on: ubuntu-latest
needs: [mcp-unit-handlers, mcp-unit-security, mcp-unit-tools-transport, mcp-unit-root, mcp-integration-tests, mcp-validation]
if: always()
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Create summary comment
uses: actions/github-script@v7
if: github.event_name == 'pull_request'
with:
script: |
const fs = require('fs');
const path = require('path');
let summary = '## MCP Tools Test Summary\n\n';
// Check validation report
try {
const validationFiles = fs.readdirSync('mcp-validation-report');
if (validationFiles.length > 0) {
const reportPath = path.join('mcp-validation-report', validationFiles[0]);
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
summary += `### Validation Results\n`;
summary += `- Total Tools: ${report.totalTools}\n`;
summary += `- Valid Tools: ${report.validTools}\n`;
summary += `- Invalid Tools: ${report.invalidTools}\n`;
summary += `- Coverage: ${report.coverage}%\n\n`;
}
} catch (err) {
summary += '### Validation Results\n- Validation report not found\n\n';
}
summary += '### Unit Test Results\n';
summary += '- Handlers: ${{ needs.mcp-unit-handlers.result }}\n';
summary += '- Security: ${{ needs.mcp-unit-security.result }}\n';
summary += '- Tools/Transport: ${{ needs.mcp-unit-tools-transport.result }}\n';
summary += '- Root: ${{ needs.mcp-unit-root.result }}\n\n';
summary += '### Other Results\n';
summary += '- Integration Tests: ${{ needs.mcp-integration-tests.result }}\n';
summary += '- Validation: ${{ needs.mcp-validation.result }}\n';
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});