Update instruction files #18
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 | |
| # - PHPStan static analysis | |
| # - 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 }} | |
| - name: Check coverage threshold | |
| run: | | |
| COVERAGE=$(grep -oP 'Lines:\s+\K[\d.]+' <<< "$(./vendor/bin/phpunit --coverage-text 2>/dev/null)") | |
| echo "PHP coverage: $COVERAGE%" | |
| if (( $(echo "$COVERAGE < ${{ env.MIN_COVERAGE }}" | bc -l) )); then | |
| echo "::warning::PHP coverage ($COVERAGE%) is below minimum threshold (${{ env.MIN_COVERAGE }}%)" | |
| fi | |
| static-analysis: | |
| name: Static Analysis | |
| 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' | |
| tools: composer | |
| - name: Install dependencies | |
| run: composer install --prefer-dist --no-progress | |
| - name: Run PHPStan | |
| run: | | |
| if [ -f "phpstan.neon" ]; then | |
| ./vendor/bin/phpstan analyse --error-format=github | |
| else | |
| echo "PHPStan configuration not found, skipping" | |
| fi | |
| continue-on-error: true | |
| - name: Run PHPMD | |
| run: | | |
| if command -v phpmd &> /dev/null; then | |
| phpmd . github phpmd.xml --exclude vendor,node_modules,build | |
| fi | |
| continue-on-error: true | |
| 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 build/blocks/*/*.js build/blocks/*/*.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 failed or not configured" | |
| fi | |
| continue-on-error: true | |
| quality-gate: | |
| name: Quality Gate | |
| runs-on: ubuntu-latest | |
| needs: [js-coverage, php-coverage, static-analysis, bundle-analysis] | |
| if: always() | |
| steps: | |
| - name: Check quality gate status | |
| run: | | |
| JS_COVERAGE="${{ needs.js-coverage.result }}" | |
| PHP_COVERAGE="${{ needs.php-coverage.result }}" | |
| STATIC="${{ needs.static-analysis.result }}" | |
| BUNDLE="${{ needs.bundle-analysis.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 "| Static Analysis | $STATIC |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Bundle Analysis | $BUNDLE |" >> $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 |