refactor: Decompose 6 mega-files into 13 focused modules, remove lega… #92
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: Quality Gates | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| jobs: | |
| quality-gates: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: TypeScript compilation | |
| run: | | |
| echo "::group::TypeScript Compilation" | |
| npm run build | |
| echo "::endgroup::" | |
| - name: Lint check | |
| run: | | |
| echo "::group::ESLint" | |
| npm run lint || echo "::warning::ESLint found issues" | |
| echo "::endgroup::" | |
| - name: Type safety validation | |
| run: | | |
| echo "::group::Type Safety" | |
| npx vitest run src/test/quality/type-safety.test.ts | |
| echo "::endgroup::" | |
| - name: Run tests with coverage | |
| run: | | |
| echo "::group::Test Suite" | |
| npm run test -- --coverage --run | |
| echo "::endgroup::" | |
| - name: Coverage enforcement | |
| run: | | |
| echo "::group::Coverage Check" | |
| # Vitest will fail if coverage thresholds not met | |
| if [ -f coverage/coverage-summary.json ]; then | |
| LINES=$(cat coverage/coverage-summary.json | jq '.total.lines.pct') | |
| STATEMENTS=$(cat coverage/coverage-summary.json | jq '.total.statements.pct') | |
| FUNCTIONS=$(cat coverage/coverage-summary.json | jq '.total.functions.pct') | |
| BRANCHES=$(cat coverage/coverage-summary.json | jq '.total.branches.pct') | |
| echo "Coverage Results:" | |
| echo " Lines: $LINES%" | |
| echo " Statements: $STATEMENTS%" | |
| echo " Functions: $FUNCTIONS%" | |
| echo " Branches: $BRANCHES%" | |
| # Quality gate: minimum 85% coverage | |
| if (( $(echo "$LINES < 85" | bc -l) )); then | |
| echo "::error::Line coverage $LINES% is below 85% threshold" | |
| exit 1 | |
| fi | |
| if (( $(echo "$STATEMENTS < 85" | bc -l) )); then | |
| echo "::error::Statement coverage $STATEMENTS% is below 85% threshold" | |
| exit 1 | |
| fi | |
| else | |
| echo "::warning::No coverage report found" | |
| fi | |
| echo "::endgroup::" | |
| - name: Security audit | |
| run: | | |
| echo "::group::Security Audit" | |
| npx tsx src/test/reports/security-audit.ts | |
| # Check for critical security issues | |
| if [ -f .claude/reports/security-audit.json ]; then | |
| CRITICAL=$(cat .claude/reports/security-audit.json | jq '.summary.violations.critical') | |
| HIGH=$(cat .claude/reports/security-audit.json | jq '.summary.violations.high') | |
| SCORE=$(cat .claude/reports/security-audit.json | jq '.summary.overallScore') | |
| echo "Security Score: $SCORE/100" | |
| echo "Critical Issues: $CRITICAL" | |
| echo "High Issues: $HIGH" | |
| # Quality gate: no critical issues, score >= 70 | |
| if [ "$CRITICAL" -gt 0 ]; then | |
| echo "::error::Found $CRITICAL critical security issues" | |
| exit 1 | |
| fi | |
| if [ "$HIGH" -gt 5 ]; then | |
| echo "::error::Found $HIGH high security issues (max 5 allowed)" | |
| exit 1 | |
| fi | |
| if (( $(echo "$SCORE < 70" | bc -l) )); then | |
| echo "::error::Security score $SCORE is below 70 threshold" | |
| exit 1 | |
| fi | |
| fi | |
| echo "::endgroup::" | |
| - name: Performance tests | |
| run: | | |
| echo "::group::Performance Tests" | |
| npx vitest run src/test/performance/performance.test.ts | |
| echo "::endgroup::" | |
| - name: Integration tests | |
| run: | | |
| echo "::group::Integration Tests" | |
| npx vitest run src/test/integration/ | |
| echo "::endgroup::" | |
| - name: Generate quality metrics | |
| run: | | |
| echo "::group::Quality Metrics" | |
| npx tsx src/test/reports/quality-dashboard.ts | |
| if [ -f .claude/reports/quality-metrics.json ]; then | |
| GRADE=$(cat .claude/reports/quality-metrics.json | jq -r '.overallGrade') | |
| SCORE=$(cat .claude/reports/quality-metrics.json | jq '.overallScore') | |
| echo "Overall Grade: $GRADE" | |
| echo "Overall Score: $SCORE/100" | |
| # Quality gate: minimum grade B (80+) | |
| if [ "$GRADE" == "C" ] || [ "$GRADE" == "D" ] || [ "$GRADE" == "F" ]; then | |
| echo "::warning::Quality grade $GRADE is below B threshold" | |
| fi | |
| fi | |
| echo "::endgroup::" | |
| - name: Upload coverage reports | |
| uses: codecov/codecov-action@v3 | |
| if: always() | |
| with: | |
| files: ./coverage/lcov.info | |
| flags: unittests | |
| name: codecov-nxtg-forge | |
| - name: Upload quality reports | |
| uses: actions/upload-artifact@v3 | |
| if: always() | |
| with: | |
| name: quality-reports | |
| path: | | |
| .claude/reports/ | |
| coverage/ | |
| - name: Comment PR with quality metrics | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| let comment = '## Quality Gates Report\n\n'; | |
| // Coverage | |
| if (fs.existsSync('coverage/coverage-summary.json')) { | |
| const coverage = JSON.parse(fs.readFileSync('coverage/coverage-summary.json', 'utf8')); | |
| comment += '### Test Coverage\n'; | |
| comment += `- Lines: ${coverage.total.lines.pct}%\n`; | |
| comment += `- Statements: ${coverage.total.statements.pct}%\n`; | |
| comment += `- Functions: ${coverage.total.functions.pct}%\n`; | |
| comment += `- Branches: ${coverage.total.branches.pct}%\n\n`; | |
| } | |
| // Security | |
| if (fs.existsSync('.claude/reports/security-audit.json')) { | |
| const security = JSON.parse(fs.readFileSync('.claude/reports/security-audit.json', 'utf8')); | |
| comment += '### Security Audit\n'; | |
| comment += `- Score: ${security.summary.overallScore}/100\n`; | |
| comment += `- Critical: ${security.summary.violations.critical}\n`; | |
| comment += `- High: ${security.summary.violations.high}\n`; | |
| comment += `- Medium: ${security.summary.violations.medium}\n\n`; | |
| } | |
| // Quality Metrics | |
| if (fs.existsSync('.claude/reports/quality-metrics.json')) { | |
| const quality = JSON.parse(fs.readFileSync('.claude/reports/quality-metrics.json', 'utf8')); | |
| comment += '### Overall Quality\n'; | |
| comment += `- Grade: ${quality.overallGrade}\n`; | |
| comment += `- Score: ${quality.overallScore}/100\n\n`; | |
| } | |
| // Status | |
| comment += '### Status\n'; | |
| comment += process.env.GITHUB_WORKFLOW_CONCLUSION === 'success' | |
| ? '✅ All quality gates passed!\n' | |
| : '❌ Some quality gates failed. Please review the logs.\n'; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: comment | |
| }); | |
| - name: Quality gate summary | |
| if: always() | |
| run: | | |
| echo "::notice::Quality Gates Complete" | |
| echo "See artifacts for detailed reports" |