Skip to content

Add/build tools - #2

Closed
troychaplin wants to merge 12 commits into
mainfrom
add/build-tools
Closed

Add/build tools#2
troychaplin wants to merge 12 commits into
mainfrom
add/build-tools

Conversation

@troychaplin

Copy link
Copy Markdown
Member

What?

Adds a first pass at build tooling for the plugin: linting, static analysis, continuous integration, a pre-commit hook, and contributor documentation — plus the code fixes those tools surfaced.

Why?

The plugin had no automated quality checks. Coding standards, static analysis and CI were all missing, so nothing enforced consistency and nothing verified a branch before review. This establishes the basics so future work has a baseline to build on.

Standing the tooling up also surfaced a set of real defects in the existing code that no one had a way to catch. Those are fixed here rather than deferred, since several of them are one-line changes and leaving them would mean merging a red build.

How?

Tooling added

  • ESLint, Stylelint, PHP_CodeSniffer (WordPress Coding Standards) and PHPStan at level 8, all reachable through npm run lint and npm run format.
  • GitHub Actions CI: PHPCS and PHPStan across PHP 8.1–8.4, plus JS/CSS linting and a production build.
  • A husky pre-commit hook running lint-staged on staged files, followed by a project-wide PHPStan (it can't be scoped to staged files, as it needs whole-codebase context to resolve types).
  • .nvmrc pinning Node, .editorconfig for shared editor settings, and wp-env scripts (env:start, env:stop, env:clean).
  • CONTRIBUTING.md, a pull request template, and CHANGELOG.md.

Fixes surfaced by the tooling

  • The Media Library view-preference AJAX handler passed $_POST['value'] through wp_unslash() without sanitizing. Every branch already validated against an allowlist or cast to int before storing, so nothing was exploitable — this closes the gap ahead of that point.
  • uninstall.php assigned to $plugin, which collides with a WordPress global.
  • The settings page took a Registry it never read (the React app fetches over REST instead).
  • An invalid design-system token in the validation settings stylesheet, several unused variables and imports, and CSS selector specificity ordering in the Media Library view options.

Known follow-ups, deliberately not in this PR

  • Heading_Order and Block_Validation_Framework live under Modules/Experiments/ and are documented as Experiments, but both return Bucket::FEATURE / Track::PRACTICAL. All six modules currently report Feature/Practical, so the Experiment and Core-track badges never render in the settings UI. Left for a separate fix, since it changes behaviour rather than tooling.
  • Documentation links point at github.com/WordPress/accessibility-lab to match the plugin header's Plugin URI. Those will 404 until the repository moves to the WordPress organisation.
  • No automated test suite yet.

Testing Instructions

  1. Check out the branch and install from the lock files:

    nvm use
    npm ci
    composer install
  2. Confirm all four linters pass:

    npm run lint

    Expect no output from ESLint or Stylelint, 12 / 12 (100%) from PHPCS, and [OK] No errors from PHPStan.

  3. Confirm the build succeeds and produces all five bundles:

    npm run build
    ls build/
  4. Confirm the pre-commit hook blocks a bad commit — introduce a deliberate lint error in any file under src/, stage it, and attempt to commit. The commit should abort. Revert afterwards.

  5. Confirm CI is green on this PR. The JS job reaching the "Build" step is the meaningful signal, since it previously failed at "Install dependencies".

  6. Smoke-test the plugin itself, since this PR reformats source files. No behavioural or visual change is intended:

    • Settings → Accessibility Lab — module cards render, toggles save, snackbar confirmations appear.
    • Media Library (both upload.php and the modal) — the view-options button opens its popover; density, items-per-page and filename toggles apply and persist across reloads.
    • Block editor — validation sidebar lists issues, error-level failures still lock publishing.

Changelog Entry

Added - Build tooling: ESLint, Stylelint, PHPCS, PHPStan, GitHub Actions CI, a pre-commit hook, and contributor documentation.

Full entries for this PR are in CHANGELOG.md under [Unreleased], split across Added, Changed and Fixed.

@aduth aduth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the size of the pull request, I wasn't able to provide a scrutinous review of each change, but the general shape here looks good as a starting point for iteration. I recognize that this early in a project we may want to take some sweeping changes with project structure, which explains the scope of how the changes are presented. Where in the future we may want to split up into more focused pull requests.

For me, of my feedback, the biggest thing right now would be to evaluate whether to use @wordpress/build over @wordpress/scripts for building, as I understand it to be the preferred way of building plugins nowadays (related Developer Blog post).

Comment thread .stylelintrc.json
Comment on lines +3 to +5
"rules": {
"selector-class-pattern": null
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is overriding the BEM naming rule enforcement? Personally I think that could still be valuable to uphold. If needed we could treat existing issues as tolerated through suppressions and keep enabled for new code.

Comment thread CHANGELOG.md
@@ -0,0 +1,31 @@
# Changelog

All notable changes to this project will be documented in this file, per [the Keep a Changelog standard](http://keepachangelog.com/), and will adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we intend to follow semantic versioning, I find that a style that highlights breakage more obviously (e.g. Gutenberg's "Breaking Changes" semantics) makes it easier to understand how a change should affect the version number, or something like conventional commits.

Comment thread CONTRIBUTING.md
### Prerequisites

- Composer
- Node.js — the version is pinned in `.nvmrc`; the toolchain requires 22.12 or newer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to align to WordPress/Gutenberg here. I think some other plugins have run into problems when trying to use a different version.

https://make.wordpress.org/core/handbook/references/wordpress-branches-and-node-js-npm-versions/

Current is 20, but this will update soon to 24 with WordPress/gutenberg#72973.

Comment thread eslint.config.js
'**/build/**',
'**/node_modules/**',
'**/vendor/**',
'*.config.js',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The others make sense as vendored or transient build artifacts, but this one I think we should omit and enforce linting.

Suggested change
'*.config.js',

Comment thread src/settings/style.scss
Comment on lines +28 to +42
// ─── Snackbars ──────────────────────────────────────────────────────────
// Match the AI plugin: pin the snackbar list to the bottom-left of the
// viewport, offset just past the admin sidebar so it doesn't disappear
// behind the menu. The list stays fixed to the viewport, so it remains
// visible regardless of scroll position (up to the auto-dismiss timeout).

.components-snackbar-list {
position: fixed;
inset-block-end: 20px;
inset-inline-start: 176px; // WP admin sidebar (~160px) + 16px gutter.
inset-inline-end: auto;
width: auto;
max-width: min( 480px, calc( 100vw - 200px ) );
padding: 0;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker since it already existed and is beings shuffled around here, but as a stakeholder in the Gutenberg Components team, I'd wonder if this is signaling an issue that's better fixed upstream. Usually overriding the component styles like this is not recommended.


td span {
color: var(--wpds-color-content-onSurface-secondary, #757575);
color: #757575;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing that the lint flagged this as a violation of a non-existing token, but a better solution may be to pick an existing token instead.

One other related consideration as we set up build tooling is that @wordpress/build bakes in build-time design token fallbacks.

Generally I would expect that as part of setting up the build aparatus, we may want to prefer @wordpress/build over @wordpress/scripts for building, as it's the newer, preferred option for plugins stemming from work in WordPress/gutenberg#72032 .

@troychaplin

Copy link
Copy Markdown
Member Author

This PR should have stopped with the build tools and alignment to standards should have been done in subsequent PRs. Close this in lieu of #7

@troychaplin

troychaplin commented Aug 22, 2026

Copy link
Copy Markdown
Member Author

Apologies @aduth, I didn't realize you had a review in progress. I closed this based on it being too large and opened up #7. I will review all your comments in this PR and check them against my other PR and make note of anything that remains relevant.

I appreciate you taking the time to review, thank you!

troychaplin added a commit that referenced this pull request Aug 26, 2026
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.

2 participants