Skip to content

ci: gate PRs on scripts/quality.sh - #8

Merged
pluginslab merged 1 commit into
mainfrom
ci/quality-gate
Sep 21, 2026
Merged

pluginslab merged 1 commit into
mainfrom
ci/quality-gate

Conversation

@pluginslab

Copy link
Copy Markdown
Owner

Replaces #5, which GitHub auto-closed when its base branch (fix/hook-portability, now merged) was deleted. Same commit, retargeted at main. Content and reasoning unchanged.

Why

The kit ships a pre-commit hook, a quality script, and a test suite for its own hooks — and none of it ran on a pull request. scripts/quality.sh even claims CI as a caller in its header comment:

# - CI (GitHub Actions, etc.)

There was no GitHub Actions. A gate that only fires on the machine of whoever happens to be committing is a convention, not a gate — and the difference between those two things is this repo's entire pitch.

This is not hypothetical: on its very first run this workflow found that all three planning hooks had never worked on Linux (fixed in #6, now on main).

What

One workflow, on push: main and every pull_request. It calls ./scripts/quality.sh rather than re-listing the checks, so there is a single 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, the version the plugin template's header declares. Gate on the version you claim to support, not on whatever the runner ships.
  • No composer.lock is committed, so the install resolves fresh. Deliberate: it catches an upstream release breaking the scaffold before a user hits it after npm create wp-ai-plugin. The tradeoff is non-hermetic builds.
  • Read-only permissions; concurrency cancels superseded runs.

What this deliberately cannot do

Boot WordPress. playground-verifier (#3) is the runtime gate and needs an agent harness plus the wp-playground MCP server, neither of which exists in a runner. The workflow says so in a comment, because the failure mode is someone seeing green and assuming the plugin runs. v1.0.2 shipped a scaffold that fataled on activation through checks exactly this green.

Verification

Simulated the runner locally rather than pushing and hoping: git archive HEAD into a clean tree with no vendor/, then composer install, then ./scripts/quality.sh. Green. The identical commit also passed as #5 before its base branch was deleted.

🤖 Generated with Claude Code

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) <noreply@anthropic.com>
@pluginslab
pluginslab merged commit 9b9000a into main Sep 21, 2026
1 check passed
@pluginslab
pluginslab deleted the ci/quality-gate branch September 21, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant