From bec1ed1092767494dae65e5a8106b799f42286c9 Mon Sep 17 00:00:00 2001 From: pluginslab <57633278+pluginslab@users.noreply.github.com> Date: Wed, 16 Sep 2026 22:16:13 +0100 Subject: [PATCH] ci: gate PRs on scripts/quality.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kit ships a pre-commit hook, a quality script, and a 56-case test suite for its own hooks — and none of it ran on a pull request. A gate that only fires on the machine of whoever happens to be committing is a convention, not a gate. CI calls scripts/quality.sh rather than re-listing the checks, so there is one definition of "quality" shared by the hook, a local run, and the runner. A check that exists only in CI is a check that surprises you on a PR. Pinned to PHP 8.2 because that is what the plugin template's header declares. Same reasoning playground-verifier applies when it boots at the declared minimum instead of at latest: gate on the version you claim to support, not on whatever the runner happens to ship. No composer.lock is committed, so the install resolves fresh. That is deliberate — it catches an upstream release breaking the scaffold before a user hits it on `composer install` after `npm create wp-ai-plugin`. Verified by simulating the run locally: `git archive HEAD` into a clean tree with no vendor/, then composer install + quality.sh. Green. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/quality.yml | 63 +++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/quality.yml diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..8f29d9a --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,63 @@ +name: Quality + +# The kit's own gate. `scripts/quality.sh` is the single source of truth for +# "what is quality" — the same script the pre-commit hook and a local run +# invoke — so CI deliberately calls it rather than re-listing the checks here. +# A check that exists only in CI is a check that surprises you on a PR. +# +# What this cannot do: boot WordPress. The `playground-verifier` sub-agent is +# the kit's runtime gate, and it needs an agent harness plus the wp-playground +# MCP server, neither of which exists in a GitHub runner. Static analysis is +# the floor here, not the ceiling — dispatch the verifier before merging +# anything that touches the plugin template. + +on: + push: + branches: [main] + pull_request: + +# Read-only. This workflow inspects the tree; it never writes to the repo. +permissions: + contents: read + +concurrency: + group: quality-${{ github.ref }} + cancel-in-progress: true + +jobs: + quality: + name: quality.sh + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + # 8.2 is the version the plugin template's header declares + # (`Requires PHP: 8.2`). Gate on the minimum you claim to support, not on + # whatever the runner ships — the same reasoning playground-verifier + # applies when it boots at the declared minimum rather than at latest. + - name: Set up PHP 8.2 + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + tools: composer:v2 + coverage: none + + - name: Cache Composer packages + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ runner.os }}-php8.2-${{ hashFiles('composer.json') }} + restore-keys: composer-${{ runner.os }}-php8.2- + + # No composer.lock is committed, so this resolves fresh. That is the + # point: it catches an upstream release breaking the scaffold before a + # user hits it on `composer install` after `npm create wp-ai-plugin`. + - name: Install Composer dependencies + run: composer install --prefer-dist --no-progress --no-interaction + + # phpcs + the kit's own bash test suite. Every other check inside + # quality.sh is gated on its tool being present, so this stays correct + # as the kit grows a JS build or a phpunit config. + - name: Run quality suite + run: ./scripts/quality.sh