Robustness pass: engine retry, JSON parsing, concurrency limits, stal… #55
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: CI | |
| on: | |
| push: | |
| branches: ["**"] | |
| tags-ignore: ["**"] # tags are handled by release.yml | |
| pull_request: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Lint — JS, CSS, PHP syntax, PHPCS, PHPStan | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5.0.1 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v5.0.0 | |
| with: | |
| node-version: "lts/*" | |
| cache: "npm" | |
| - name: Set up PHP | |
| uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: "8.2" | |
| tools: cs2pr | |
| coverage: none | |
| - name: Install JS dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Install PHP dependencies | |
| run: composer install --no-interaction --prefer-dist | |
| - name: Lint — JavaScript | |
| run: npm run lint:js | |
| - name: Lint — CSS/SCSS | |
| run: npm run lint:css | |
| - name: Lint — PHP syntax | |
| run: npm run lint:php:syntax | |
| - name: Lint — PHP CodeSniffer | |
| run: composer run phpcs -- -q -n --report=checkstyle | cs2pr | |
| - name: Analyze — PHPStan | |
| run: composer run phpstan -- --memory-limit=1G --error-format=github | |
| - name: Validate block HTML | |
| run: npm run test:php:validate | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Test — JS unit tests | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| test-js: | |
| name: JS Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5.0.1 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v5.0.0 | |
| with: | |
| node-version: "lts/*" | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Run Jest | |
| run: npm run test:js -- --coverage | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Test — PHP unit tests (no WP install required, uses stubs bootstrap) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| test-php-unit: | |
| name: PHP Unit (PHP ${{ matrix.php }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| php: ["8.2", "8.3"] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5.0.1 | |
| - name: Set up PHP ${{ matrix.php }} | |
| uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: ${{ matrix.php }} | |
| coverage: none | |
| - name: Install PHP dependencies | |
| run: composer install --no-interaction --prefer-dist | |
| - name: Run PHPUnit (unit suite) | |
| run: vendor/bin/phpunit --testsuite unit | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Test — PHP integration tests (requires WordPress test suite) | |
| # Matrix: PHP 8.0 / WP 6.4 and PHP 8.3 / WP latest | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| test-php-integration: | |
| name: PHP Integration (PHP ${{ matrix.php }} / WP ${{ matrix.wp }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - php: "8.2" | |
| wp: "6.4" | |
| - php: "8.2" | |
| wp: "6.7" | |
| - php: "8.3" | |
| wp: "latest" | |
| services: | |
| mysql: | |
| image: mysql:8.0 | |
| env: | |
| MYSQL_ROOT_PASSWORD: root | |
| MYSQL_DATABASE: wp_tests | |
| ports: | |
| - 3306:3306 | |
| options: >- | |
| --health-cmd="mysqladmin ping" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5.0.1 | |
| - name: Set up PHP ${{ matrix.php }} | |
| uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: ${{ matrix.php }} | |
| extensions: mysqli | |
| coverage: none | |
| - name: Install PHP dependencies | |
| run: composer install --no-interaction --prefer-dist | |
| - name: Install WordPress test suite | |
| run: bash bin/install-wp-tests.sh wp_tests root root 127.0.0.1 ${{ matrix.wp }} true | |
| - name: Run PHPUnit (integration suite) | |
| run: vendor/bin/phpunit -c phpunit-integration.xml.dist | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Build — only runs when lint + unit tests all pass | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [lint, test-js, test-php-unit] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5.0.1 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v5.0.0 | |
| with: | |
| node-version: "lts/*" | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Build | |
| run: npm run build | |
| - name: Verify build output | |
| run: | | |
| # Required files exist | |
| test -f build/index.js || { echo "MISSING: build/index.js"; exit 1; } | |
| test -f build/index.css || { echo "MISSING: build/index.css"; exit 1; } | |
| test -f build/block.json || { echo "MISSING: build/block.json"; exit 1; } | |
| test -f build/index.asset.php || { echo "MISSING: build/index.asset.php"; exit 1; } | |
| test -f build/render.php || { echo "MISSING: build/render.php"; exit 1; } | |
| # index.js must be at least 50 KB — catches empty or truncated builds | |
| ACTUAL=$(wc -c < build/index.js) | |
| [ "$ACTUAL" -gt 50000 ] || { echo "FAIL: build/index.js is only ${ACTUAL} bytes (min 50000)"; exit 1; } | |
| # No undefined icon prop — catches missing named exports reaching the bundle | |
| if grep -qP 'icon:\s*void 0' build/index.js; then | |
| echo "FAIL: 'icon: void 0' found in build/index.js — an undefined icon import reached the bundle" | |
| exit 1 | |
| fi | |
| echo "Build output verified." | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v6.0.0 | |
| with: | |
| name: build-${{ github.sha }} | |
| path: build/ | |
| retention-days: 7 | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Plugin Check — WordPress.org compatibility and best-practice checks | |
| # Runs after build so the compiled assets are present in the workspace. | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| plugin-check: | |
| name: Plugin Check | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5.0.1 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v5.0.0 | |
| with: | |
| node-version: "lts/*" | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Build plugin assets | |
| run: npm run build | |
| - name: WordPress Plugin Check | |
| uses: wordpress/plugin-check-action@9a0e904d688a8b72f99eba093641ec725404e1e8 # post-v1.1.5, uses nick-fields/retry@v4 (node24) | |
| with: | |
| build-dir: "./" | |
| # Exclude dev-only directories so the check only sees distributable files. | |
| exclude-directories: | | |
| tests | |
| vendor | |
| node_modules | |
| bin | |
| scripts | |
| docs | |
| # Check names to skip entirely: | |
| # plugin_review_phpcs — we run PHPCS separately with stricter standards. | |
| # i18n_usage — JS translations are handled by our own i18n pipeline. | |
| # plugin_updater — Update URI: header is intentional for GitHub | |
| # distribution; not applicable for wordpress.org. | |
| exclude-checks: | | |
| plugin_review_phpcs | |
| i18n_usage | |
| plugin_updater | |
| # Error/warning codes to suppress: | |
| # hidden_files / github_directory / unexpected_markdown_file — | |
| # dev-tree artefacts (.gitignore, .github/, HOOKS.md) that are | |
| # stripped by bin/release-zip.sh before distribution. | |
| # application_detected — composer/npm/webpack root files are dev-only, | |
| # excluded from the release zip. | |
| ignore-codes: | | |
| hidden_files | |
| github_directory | |
| unexpected_markdown_file | |
| application_detected |