chore: move reports directory to .github/reports and consolidate inst… #8
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
| # Code Quality and Coverage Workflow | |
| # Runs code quality checks, generates coverage reports, and enforces quality gates | |
| # | |
| # Features: | |
| # - Code coverage with Codecov integration | |
| # - ESLint/Stylelint quality reports | |
| # - Bundle size analysis | |
| # - Quality gate enforcement | |
| name: Code Quality | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| env: | |
| MIN_COVERAGE: 70 | |
| MAX_BUNDLE_SIZE: 50000 | |
| jobs: | |
| js-coverage: | |
| name: JavaScript Coverage | |
| runs-on: ubuntu-latest | |
| 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: Run tests with coverage | |
| run: npm run test:unit -- --coverage | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: ./coverage/coverage-final.json | |
| flags: javascript | |
| name: js-coverage | |
| fail_ci_if_error: false | |
| verbose: true | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Check coverage threshold | |
| run: | | |
| COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct') | |
| echo "JavaScript coverage: $COVERAGE%" | |
| if (( $(echo "$COVERAGE < ${{ env.MIN_COVERAGE }}" | bc -l) )); then | |
| echo "::error::JavaScript coverage ($COVERAGE%) is below minimum threshold (${{ env.MIN_COVERAGE }}%)" | |
| exit 1 | |
| fi | |
| echo "✅ JavaScript coverage meets threshold" | |
| php-coverage: | |
| name: PHP Coverage | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup PHP | |
| uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: '8.1' | |
| extensions: mysql, zip, xdebug | |
| tools: composer | |
| coverage: xdebug | |
| - name: Install dependencies | |
| run: composer install --prefer-dist --no-progress | |
| - name: Run PHPUnit with coverage | |
| run: | | |
| ./vendor/bin/phpunit --coverage-clover coverage.xml --coverage-text | |
| env: | |
| XDEBUG_MODE: coverage | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: ./coverage.xml | |
| flags: php | |
| name: php-coverage | |
| fail_ci_if_error: false | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| bundle-analysis: | |
| name: Bundle Analysis | |
| runs-on: ubuntu-latest | |
| 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 for production | |
| run: npm run build | |
| - name: Analyze bundle size | |
| run: | | |
| echo "## Bundle Size Analysis" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Calculate total size | |
| TOTAL_SIZE=0 | |
| echo "| File | Size (bytes) | Size (KB) |" >> $GITHUB_STEP_SUMMARY | |
| echo "|------|-------------|-----------|" >> $GITHUB_STEP_SUMMARY | |
| for file in build/*.js build/*.css; do | |
| if [ -f "$file" ]; then | |
| SIZE=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file") | |
| SIZE_KB=$(echo "scale=2; $SIZE / 1024" | bc) | |
| FILENAME=$(basename "$file") | |
| echo "| $FILENAME | $SIZE | ${SIZE_KB}KB |" >> $GITHUB_STEP_SUMMARY | |
| TOTAL_SIZE=$((TOTAL_SIZE + SIZE)) | |
| fi | |
| done | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| TOTAL_KB=$(echo "scale=2; $TOTAL_SIZE / 1024" | bc) | |
| echo "**Total: ${TOTAL_KB}KB**" >> $GITHUB_STEP_SUMMARY | |
| echo "Total bundle size: ${TOTAL_SIZE} bytes (${TOTAL_KB}KB)" | |
| if [ "$TOTAL_SIZE" -gt "${{ env.MAX_BUNDLE_SIZE }}" ]; then | |
| echo "::warning::Bundle size (${TOTAL_SIZE}) exceeds recommended maximum (${{ env.MAX_BUNDLE_SIZE }})" | |
| fi | |
| - name: Run size-limit check | |
| run: | | |
| if npm run size 2>/dev/null; then | |
| echo "✅ Bundle size within limits" | |
| else | |
| echo "::warning::Bundle size check not configured" | |
| fi | |
| continue-on-error: true | |
| lint-report: | |
| name: Lint Report | |
| runs-on: ubuntu-latest | |
| 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: Generate ESLint report | |
| run: | | |
| npm run lint:js -- --format json --output-file eslint-report.json || true | |
| if [ -f "eslint-report.json" ]; then | |
| ERRORS=$(cat eslint-report.json | jq '[.[].errorCount] | add // 0') | |
| WARNINGS=$(cat eslint-report.json | jq '[.[].warningCount] | add // 0') | |
| echo "## ESLint Report" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Errors:** $ERRORS" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Warnings:** $WARNINGS" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Generate Stylelint report | |
| run: | | |
| npm run lint:css -- --formatter json --output-file stylelint-report.json || true | |
| if [ -f "stylelint-report.json" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "## Stylelint Report" >> $GITHUB_STEP_SUMMARY | |
| echo "CSS/SCSS linting complete. See logs for details." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| quality-gate: | |
| name: Quality Gate | |
| runs-on: ubuntu-latest | |
| needs: [js-coverage, php-coverage, bundle-analysis, lint-report] | |
| if: always() | |
| steps: | |
| - name: Check quality gate status | |
| run: | | |
| JS_COVERAGE="${{ needs.js-coverage.result }}" | |
| PHP_COVERAGE="${{ needs.php-coverage.result }}" | |
| BUNDLE="${{ needs.bundle-analysis.result }}" | |
| LINT="${{ needs.lint-report.result }}" | |
| echo "## Quality Gate Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| JavaScript Coverage | $JS_COVERAGE |" >> $GITHUB_STEP_SUMMARY | |
| echo "| PHP Coverage | $PHP_COVERAGE |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Bundle Analysis | $BUNDLE |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Lint Report | $LINT |" >> $GITHUB_STEP_SUMMARY | |
| # Fail if critical checks failed | |
| if [[ "$JS_COVERAGE" == "failure" ]] || [[ "$PHP_COVERAGE" == "failure" ]]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "❌ **Quality gate failed** - Coverage requirements not met" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ **Quality gate passed**" >> $GITHUB_STEP_SUMMARY |