Skip to content

Implement includes, config file support & .distignore parsing (#1108, #1159)#1181

Open
faisalahammad wants to merge 4 commits into
WordPress:trunkfrom
faisalahammad:feature/1108-1159-include-exclude-options
Open

Implement includes, config file support & .distignore parsing (#1108, #1159)#1181
faisalahammad wants to merge 4 commits into
WordPress:trunkfrom
faisalahammad:feature/1108-1159-include-exclude-options

Conversation

@faisalahammad

@faisalahammad faisalahammad commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

Description

This PR introduces comprehensive enhancements to how the Plugin Check tool filters files. It adds support for CLI include options, configuration files (.plugin-check.json), and automatic .distignore parsing. This addresses both #1108 (CLI includes) and #1159 (Admin UI exclusions via backend logic).

Why This Change Is Needed

Currently, the tool only supports excluding files/directories via CLI flags. There is no way to:

  1. Whitelist files: Check only specific files or folders (useful for CI/CD or focused development).
  2. Persist settings: Save exclusion/inclusion rules so they don't need to be typed every time.
  3. Respect distribution rules: Automatically ignore files that won't be in the final plugin zip (like tests/, node_modules/, etc.) by reading .distignore.

How It Solves The Issue

1. New CLI Options

Added --include-files and --include-directories to the check command.

  • These are mutually exclusive with their exclude counterparts to prevent ambiguity.
  • --include-directories works recursively.

2. Configuration File Support

The tool now looks for a .plugin-check.json file in the plugin root.
Example:

{
  "exclude-directories": ["tests", "vendor"],
  "include-files": ["plugin.php"]
}

3. .distignore Support

If a .distignore file exists, its patterns are automatically parsed and added to the exclusion list.

  • Supports standard glob patterns (e.g., *.md, build/).
  • Converted to regex internally for precise matching.

4. Hybrid Priority System

To ensure predictable behavior, we implemented a strict priority order:

  1. CLI Arguments (Highest priority - overrides everything)
  2. Configuration File (.plugin-check.json)
  3. .distignore (if present)
  4. Defaults (Lowest - e.g., .git, node_modules)

Verification

I have added comprehensive unit tests to verify:

  • CLI Validation: Ensures you can't mix include/exclude options.
  • Config Parsing: Validates JSON structure and merging logic.
  • Distignore Parsing: Tests standard gitignore-style patterns (comments, globs, directories).
  • Integration: tested the full file scanning and filtering pipeline.

Run the new tests:

vendor/bin/phpunit --bootstrap tests/phpunit/includes/isolated-bootstrap.php tests/phpunit/tests/Utilities/Distignore_Parser_Tests.php
vendor/bin/phpunit --bootstrap tests/phpunit/tests/Checker/Checks/Abstract_File_Check_Ignore_Test.php

Before vs After

Before:
User has to manually type long exclude strings every time:

wp plugin check my-plugin --exclude-directories=tests,bin,node_modules,vendor

After:
User can just run:

wp plugin check my-plugin

(And the tool automatically respects .distignore and .plugin-check.json)

OR user can check just one file:

wp plugin check my-plugin --include-files=includes/admin.php

Checklist

  • Documentation updated (CLI help)
  • Unit tests added
  • Code follows WordPress coding standards
Open WordPress Playground Preview

@github-actions

github-actions Bot commented Feb 12, 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.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: faisalahammad <faisalahammad@git.wordpress.org>
Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org>
Co-authored-by: davidperezgar <davidperez@git.wordpress.org>

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

Comment thread includes/CLI/Plugin_Check_Command.php Outdated
@davidperezgar

Copy link
Copy Markdown
Member

Thanks for your contribution!
You need to fix tests before we review this PR.

- Rewrite tests to use WP_UnitTestCase (fixes PHP 8.0 CI failure)
- Delete isolated-bootstrap.php (broken mock approach)
- Fix Plugin_Check_Command: remove extra blank lines (reviewer feedback)
- Fix Plugin_Check_Command: load_filters_from_config() not just distignore
- Fix Plugin_Request_Utility: @SInCE 1.1.0 -> 1.9.0 on include methods
- Fix Plugin_Request_Utility: remove duplicate docblock, trailing whitespace
- Fix Plugin_Request_Utility: inline comment punctuation, alignment
- Fix Abstract_File_Check: alignment, single quotes for string
- Fix docs/CLI.md: remove leading : on continuation lines
- Add .gitignore entry for wp-tests-config.php
@faisalahammad faisalahammad force-pushed the feature/1108-1159-include-exclude-options branch from c3410b8 to 71d32a2 Compare May 31, 2026 04:43

@faisalahammad faisalahammad left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changes Applied

Fixes for CI failures (blocking review)

  1. Rewrote all tests to use WP_UnitTestCase (was PHPUnit\Framework\TestCase with broken mock bootstrap)

    • Plugin_Request_Utility_Config_Tests.php — 17 tests covering config, distignore, regex, and integration
    • Abstract_File_Check_Include_Tests.php — 6 tests covering include/exclude file filtering
    • Include_Test_File_Check.php — test helper class (testdata)
    • Deleted: isolated-bootstrap.php, old test files
  2. Fixed config loading bug — CLI was calling load_distignore_filters() instead of load_filters_from_config(), so .plugin-check.json was never loaded from CLI path

Reviewer feedback

  1. Removed extra blank lines in Plugin_Check_Command.php (mukeshpanchal27 review)

Code quality

  1. Plugin_Request_Utility.php: Fixed @since 1.1.0@since 1.9.0, removed duplicate docblock, fixed trailing whitespace, fixed inline comment punctuation, added phpcs:ignore for file_get_contents
  2. Abstract_File_Check.php: Fixed variable alignment and string quotes (PHPCS)
  3. docs/CLI.md: Removed leading : on continuation lines

Verification

  • ✅ PHPUnit: 504/504 tests pass (1396 assertions)
  • ✅ PHPCS: 0 errors
  • ✅ Rebased on trunk (v2.0.0) — branch is now up to date

Add @SuppressWarnings annotations for NPathComplexity and CyclomaticComplexity
on get_files() (includes/exclude filtering adds inherent branching) and
TooManyPublicMethods on Plugin_Request_Utility (config/distignore/include
support requires public API surface).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@davidperezgar

Copy link
Copy Markdown
Member

@faisalahammad

There is an issue with this PR. We cannot create automatic exclusions from the .distignore, .gitignore and .plugin-check.json files. These should be flagged by a command in wpcli.

Remember that we load this plugin in the automatic scanner for new and updated plugins in wordpress.org, and we don't want users to be able to change the scanner's behaviour.

I understand that you could remove the self-automatic checks, but they must be set.

…onfig flag

Plugin authors could ship .distignore or .plugin-check.json to silently
exclude files from checks. The WordPress.org automated plugin-check scanner
runs on every new/updated plugin, so author-controlled config loading
broke the scanner's trust model.

Address @davidperezgar's blocker (comment 4697859757):

- Add explicit --use-config CLI flag, off by default
- Extract gate to testable maybe_load_plugin_config() static method
- Remove unconditional load_filters_from_config() call from admin
  (admin reverts to trunk behavior)
- Add 6 PHPUnit tests covering gate (flag false, flag true, missing
  files, empty fixtures, no config files)
- Document flag in docs/CLI.md and CLI help text

Refs WordPress#1181
@faisalahammad

Copy link
Copy Markdown
Contributor Author

Thanks for the blocker feedback — addressed in commit 6f2a24b1.

Changes

  • New --use-config CLI flag (off by default). Only when set, the tool reads .plugin-check.json and .distignore from the plugin root.
  • Admin path reverted to trunk — no config loading from Admin_AJAX::configure_runner anymore. Plugin authors cannot silently affect the admin check either.
  • Refactor: gate logic extracted to Plugin_Check_Command::maybe_load_plugin_config( $plugin_path, $use_config ) static method, fully testable without WP-CLI mock.
  • 6 new PHPUnit tests for the gate: flag false (default), flag true, missing files, no config files, empty plugin path, missing directory.
  • Docs updated: --use-config documented in CLI help text and docs/CLI.md.

How this addresses the blocker

Default behavior now matches trunk — .distignore and .plugin-check.json are never read automatically. WordPress.org scanner (or any other automated caller) gets predictable behavior unless the operator explicitly opts in.

Manual --use-config invocation is unchanged from your previous mental model: when the user types the flag, the tool reads the config files just like before. Difference is that the read now requires an explicit CLI argument, not just presence of the files in the plugin tree.

Verification

  • PHPCS: 0 errors
  • PHPStan: 0 errors (caught and fixed 1 real bug during dev: $config undefined before array_merge)
  • CodeRabbit review: 0 actionable findings
  • New tests: tests/phpunit/tests/CLI/Plugin_Check_Command_Config_Tests.php
  • Full PHPUnit run needs MySQL, validated locally via PHPCS + PHPStan + syntax checks only

Refs #1181

@davidperezgar

Copy link
Copy Markdown
Member

Thanks! Update the versions of the classes to 2.1.0

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.

3 participants