Skip to content

Fix broken phpcs excludes and speed up linting - #771

Open
obenland wants to merge 5 commits into
WordPress:trunkfrom
obenland:update/phpcs-config-and-ci
Open

Fix broken phpcs excludes and speed up linting#771
obenland wants to merge 5 commits into
WordPress:trunkfrom
obenland:update/phpcs-config-and-ci

Conversation

@obenland

@obenland obenland commented Aug 7, 2026

Copy link
Copy Markdown
Member

Problem

The WPCS 3 upgrade renamed several sniffs, and PHPCS never validates error-code-level excludes — it just sets severity 0 for whatever string it's given. Two excludes in phpcs.xml.dist referenced the old sniff names and had been silently doing nothing:

  • WordPress.WhiteSpace.PrecisionAlignment.Found → now Universal.WhiteSpace.PrecisionAlignment.Found
  • WordPress.Arrays.ArrayDeclarationSpacing.SpaceBeforeArrayCloser → now NormalizedArrays.Arrays.ArrayBraceSpacing.*

As a result, ~450 alignment-related violations the config explicitly documents as allowed ("Aligning things can make the code more readable") were surfacing again — the ArrayBraceSpacing ones as errors, failing phpcs-changed CI for anyone touching an aligned line.

Separately, a full-repo composer run lint ran out of memory at the default 128M limit, and CI scanned files one phpcs invocation at a time with no dependency caching.

Changes

phpcs.xml.dist

  • Reference the WordPress meta-standard, explicitly excluding the four sniffs it auto-includes beyond Core/Docs/Extra (DirectDatabaseQuery, SlowDBQuery, ValidatedSanitizedInput, I18nTextDomainFixer), and restore the alignment excludes under their current sniff names. Verified: per-sniff violation output over wp-content is identical to the old config, except the six alignment codes dropping to zero.
  • Remove the JS/CSS exclude patterns. PHPCS doesn't escape dots in patterns, so *.js[x]? matched any path containing "js" and accidentally hid four real PHP files from linting (plugin-directory/block-json/class-parser.php, class-validator.php, wporg-gp-customizations/.../class-export-json.php, wporg-gp-js-warnings.php). With extensions=php the patterns were redundant for their stated purpose anyway.
  • Add parallel=10, result caching, basepath, and a 512M memory limit. Full-repo lint: previously OOM → now ~27s cold, <1s warm.
  • Drop the phpcbf-only exclude for PEAR.Functions.FunctionCallSignature, so composer run format can fix multi-line call formatting.

CI

  • .github/bin/phpcs-branch.php: batch new-file scans into a single phpcs invocation so parallel processing applies (per-file invocations never fork workers).
  • .github/workflows/phpcs.yml: cache Composer dependencies keyed on composer.lock.

Dependencies

  • wp-coding-standards/wpcs ^3.3.0^3.4.1 (constraint catch-up to PR #742); pin phpcompatibility/phpcompatibility-wp *^2.1.
  • Lock update moves PHP_CodeSniffer 3.13.5 → 3.13.6, which fixes CVE-2026-67434 (high-severity command injection; 3.13.5 is affected).

Testing

  • Validated all error-code-level excludes against the installed WPCS 3.4.1 / PHPCSExtra 1.5.1 sniff sources.
  • Diffed per-sniff and per-file phpcs output over wp-content between old and new config: only the intended alignment codes change, plus the four rescued files entering scope.
  • Exercised the batched CI path locally with synthetic added files (violations reported, exit status propagates) and the phpcs-changed modified-file flow end-to-end.
  • Confirmed the phpcs result cache is content-hash keyed (md5_file), so CI's rewrite-temp-file pattern cannot be served stale results.

🤖 Generated with Claude Code

Update: full WordPress standard for new code (supersedes #714)

Since CI enforces this ruleset only on changed lines and new files (via phpcs-changed), sniff exclusions only ever shield newly written code. This PR now removes all of them, adopting the goal of #714 without its second config file — a single config can't drift from what CI enforces (exactly the failure mode this PR fixes), and local composer run lint matches CI.

The only deliberate deviations kept: WordPress.DB.DirectDatabaseQuery/SlowDBQuery (custom tables are the architecture here), WordPress.Utils.I18nTextDomainFixer (config-driven rewrite utility), short array syntax (used throughout the codebase), and WordPress.WP.Capabilities.Unknown (pending the allowlist in #583).

…p linting.

WPCS 3 renamed several sniffs, so excludes referencing the old names were
silently ignored: ~450 alignment-related violations the config documents as
allowed were surfacing again, failing PRs that touch those lines. PHPCS never
validates error-code-level excludes, so this went unnoticed.

- Reference the WordPress meta-standard, explicitly excluding the four sniffs
  it auto-includes beyond Core/Docs/Extra, and re-add the alignment excludes
  under their current sniff names. Sniff coverage is otherwise unchanged.
- Remove the JS/CSS exclude patterns. PHPCS does not escape dots in patterns,
  so `*.js[x]?` matched any path containing "js" and hid four PHP files
  (block-json parser/validator, export-json CLI, gp-js-warnings) from linting.
  With `extensions=php` the patterns were redundant anyway.
- Add parallel, result caching, basepath, and a 512M memory limit. A full-repo
  lint previously ran out of memory; it now completes in ~27s cold and under
  a second warm.
- Let phpcbf fix multi-line function call formatting (drop the phpcbf-only
  exclude for PEAR.Functions.FunctionCallSignature).
- Batch new-file scans in CI into a single phpcs invocation so parallel
  processing applies, and cache Composer dependencies in the workflow.
- Update wp-coding-standards/wpcs to ^3.4.1 and pin phpcompatibility-wp to
  ^2.1. The lock update moves PHPCS to 3.13.6, which fixes CVE-2026-67434.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 7, 2026 02:54
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props obenland.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Updates the repository’s PHPCS configuration and CI workflow to restore intended excludes after the WPCS 3 rename, reduce false “alignment” failures, and significantly speed up linting locally and in GitHub Actions. It also bumps PHPCS/WPCS-related dev dependencies (including a PHP_CodeSniffer security fix).

Changes:

  • Fixes/modernizes phpcs.xml.dist (new sniff codes, switch to WordPress meta-standard, remove overly-broad JS/CSS exclude patterns, enable parallel + caching + higher memory limit).
  • Speeds up CI linting by caching Composer dependencies and batching new-file PHPCS scans into a single invocation.
  • Updates dev dependencies (WPCS constraint, PHPCompatibilityWP pin, and PHPCS patch release in composer.lock).

Reviewed changes

Copilot reviewed 3 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
phpcs.xml.dist Restores intended sniff excludes post-WPCS-3 rename and adds PHPCS performance settings (parallel, cache, basepath, memory limit).
composer.json Updates dev dependency constraints for WPCS and PHPCompatibilityWP.
composer.lock Locks updated toolchain versions (including PHP_CodeSniffer patch).
.gitignore Ignores the new PHPCS result cache file.
.github/workflows/phpcs.yml Adds Composer dependency caching to speed up CI.
.github/bin/phpcs-branch.php Batches new-file scans to allow PHPCS parallelism to actually take effect.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/bin/phpcs-branch.php
Paths come from git and are interpolated into a shell command; a filename
containing a space or shell metacharacter would split into bogus arguments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 6 changed files in this pull request and generated no new comments.

obenland and others added 3 commits August 6, 2026 22:03
Same issue class as the previous commit: run_phpcs_changed() interpolates
git-reported file paths (and names derived from them) unescaped into five
shell commands, including redirect targets. A crafted filename among a PR's
modified files would break the scan the same way it did for new files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CI only enforces the ruleset on lines a branch touches and on new files,
so sniff exclusions only ever shield newly written code. Remove them all,
keeping just the deliberate deviations: direct/meta DB queries (custom
tables are the architecture here), the I18nTextDomainFixer utility, short
array syntax, and unknown capabilities pending the allowlist in PR WordPress#583.

Supersedes PR WordPress#714, which proposed the same standard via a second config
file; a single config can't drift apart from what CI enforces and keeps
local lint results identical to CI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@obenland obenland changed the title Fix PHPCS excludes silently broken by the WPCS 3 upgrade, and speed up linting Fix PHPCS broken excludes and speed up linting Aug 7, 2026
@obenland obenland changed the title Fix PHPCS broken excludes and speed up linting Fix broken phpcs excludes and speed up linting Aug 7, 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