Files
Profa c0ba2b4d86 fix: rename scripts to .cjs/.mjs for ESM compatibility
package.json has "type": "module" so .js files are treated as ESM.
Scripts using require() renamed to .cjs, scripts using import to .mjs.
Fixes Test Dashboard CI failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:58:50 +00:00

393 lines
11 KiB
YAML

name: Optimized CI
# Optimized CI workflow targeting < 2 minute execution
# Runs journey tests first (highest value), then contracts and critical infrastructure
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
permissions:
contents: read
actions: write
pull-requests: write
checks: write
jobs:
# Fast path: Journey + Contract tests (primary quality signal)
fast-tests:
name: Fast Tests (Journey + Contract)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run Journey Tests
id: journey-tests
run: npm run test:journeys || echo "journey_failed=true" >> $GITHUB_OUTPUT
env:
NODE_OPTIONS: '--max-old-space-size=1024'
continue-on-error: true
- name: Run Contract Tests
id: contract-tests
if: always()
run: |
if [ -d "tests/contracts" ] && [ "$(ls -A tests/contracts/*.test.ts 2>/dev/null)" ]; then
npm run test:contracts
else
echo "No contract tests found"
fi
env:
NODE_OPTIONS: '--max-old-space-size=512'
continue-on-error: true
- name: Run Code Intelligence Tests (MinCut/Graph Algorithms)
id: code-intelligence-tests
if: always()
run: npm run test:code-intelligence
env:
NODE_OPTIONS: '--max-old-space-size=768'
SKIP_INTEGRATION_TESTS: 'true'
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: fast-test-results
path: junit.xml
retention-days: 7
- name: Check test results
if: always()
run: |
FAILED=0
if [ "${{ steps.journey-tests.outcome }}" == "failure" ]; then
echo "Journey tests failed"
FAILED=1
fi
if [ "${{ steps.code-intelligence-tests.outcome }}" == "failure" ]; then
echo "Code Intelligence tests failed (MinCut/Graph algorithms)"
FAILED=1
fi
if [ "$FAILED" -eq 1 ]; then
exit 1
fi
echo "Fast tests passed (including Code Intelligence)"
# Infrastructure tests (can run in parallel)
infrastructure-tests:
name: Infrastructure Tests
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run Infrastructure Tests
run: |
if [ -d "tests/infrastructure" ] && [ "$(ls -A tests/infrastructure/*.test.ts 2>/dev/null)" ]; then
npm run test:infrastructure
else
echo "No infrastructure tests found"
fi
env:
NODE_OPTIONS: '--max-old-space-size=768'
continue-on-error: true
- name: Run Regression Tests
run: |
if [ -d "tests/regression" ] && [ "$(find tests/regression -name '*.test.ts' 2>/dev/null | head -1)" ]; then
npm run test:regression
else
echo "No regression tests found"
fi
env:
NODE_OPTIONS: '--max-old-space-size=512'
continue-on-error: true
# Postgres integration tests
integration-tests:
name: Postgres Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 10
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: aqe_test
POSTGRES_USER: aqe_test
POSTGRES_PASSWORD: aqe_test
ports:
- 15432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run Postgres integration tests
run: npm run test:integration:pg
env:
POSTGRES_URL: postgresql://aqe_test:aqe_test@localhost:15432/aqe_test
NODE_OPTIONS: '--max-old-space-size=1024'
# Performance gates
performance-gates:
name: Performance Gates
runs-on: ubuntu-latest
needs: fast-tests
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run Performance Gates
id: perf-gates
run: |
npm run performance:gate > perf-report.md 2>&1 || PERF_EXIT=$?
echo "PERF_EXIT_CODE=${PERF_EXIT:-0}" >> $GITHUB_OUTPUT
cat perf-report.md
continue-on-error: true
- name: Upload performance report
uses: actions/upload-artifact@v4
if: always()
with:
name: performance-report
path: perf-report.md
retention-days: 30
- name: Check performance gate results
if: always()
run: |
EXIT_CODE="${{ steps.perf-gates.outputs.PERF_EXIT_CODE }}"
if [ "$EXIT_CODE" -eq 0 ]; then
echo "All performance gates passed"
elif [ "$EXIT_CODE" -eq 2 ]; then
echo "Performance gates passed with warnings"
else
echo "Performance gates failed (exit code: $EXIT_CODE)"
# Don't fail the build on performance warnings, only on failures
if [ "$EXIT_CODE" -eq 1 ]; then
exit 1
fi
fi
# Coverage analysis (runs after fast tests)
coverage:
name: Coverage Analysis
runs-on: ubuntu-latest
needs: fast-tests
timeout-minutes: 10
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run tests with coverage (excluding browser E2E)
run: npm run test:coverage
env:
NODE_OPTIONS: '--max-old-space-size=1024'
CI: 'true'
continue-on-error: true
- name: Upload coverage report
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage/
retention-days: 7
- name: Check coverage thresholds
if: always()
run: |
if [ -f "coverage/coverage-summary.json" ]; then
COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct')
echo "Line coverage: ${COVERAGE}%"
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "Coverage below 80% threshold"
else
echo "Coverage meets threshold"
fi
fi
# Test dashboard (summary job)
dashboard:
name: Test Dashboard
runs-on: ubuntu-latest
needs: [fast-tests, infrastructure-tests]
if: always()
timeout-minutes: 2
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Generate Dashboard
run: |
node scripts/test-dashboard.cjs
- name: Generate Migration Metrics
run: |
echo "# CI Test Metrics" > ci-metrics.md
echo "" >> ci-metrics.md
echo "**Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> ci-metrics.md
echo "**Commit**: ${{ github.sha }}" >> ci-metrics.md
echo "" >> ci-metrics.md
total_files=$(find tests -name "*.test.ts" 2>/dev/null | wc -l || echo "0")
total_lines=$(find tests -name "*.test.ts" -exec wc -l {} + 2>/dev/null | tail -1 | awk '{print $1}' || echo "0")
large_files=$(find tests -name "*.test.ts" -exec wc -l {} \; 2>/dev/null | awk '$1 > 600' | wc -l || echo "0")
skipped=$(grep -r "describe.skip\|it.skip\|test.skip" tests --include="*.test.ts" 2>/dev/null | wc -l || echo "0")
echo "## Current State" >> ci-metrics.md
echo "- Total test files: $total_files (target: 50)" >> ci-metrics.md
echo "- Total lines: $total_lines (target: 40,000)" >> ci-metrics.md
echo "- Files > 600 lines: $large_files (target: 0)" >> ci-metrics.md
echo "- Skipped tests: $skipped (target: 0)" >> ci-metrics.md
echo "" >> ci-metrics.md
# Progress calculation
baseline_files=426
baseline_lines=208253
files_reduced=$((baseline_files - total_files))
lines_reduced=$((baseline_lines - total_lines))
echo "## Progress from Baseline" >> ci-metrics.md
echo "- Files reduced: $files_reduced (-$((files_reduced * 100 / baseline_files))%)" >> ci-metrics.md
echo "- Lines reduced: $lines_reduced (-$((lines_reduced * 100 / baseline_lines))%)" >> ci-metrics.md
cat ci-metrics.md
- name: Upload metrics
uses: actions/upload-artifact@v4
with:
name: ci-metrics
path: ci-metrics.md
retention-days: 30
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const metrics = fs.readFileSync('ci-metrics.md', 'utf8');
const body = `## Test Suite Metrics
${metrics}
---
*Generated by Optimized CI*`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(c =>
c.user?.type === 'Bot' && c.body?.includes('Test Suite Metrics')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body
});
}