Skip to content

fix(coding-standard): install the standard beside the code, not in it - #397

Merged
marcelmtz merged 1 commit into
mage-os:mainfrom
marcelmtz:fix/coding-standard-isolated-install
Nov 12, 2026
Merged

marcelmtz merged 1 commit into
mage-os:mainfrom
marcelmtz:fix/coding-standard-isolated-install

Conversation

@marcelmtz

Copy link
Copy Markdown
Contributor

Coding Standard has been red since May 2026, on main as well as on PRs. It has only run twice since, because its paths filter rarely matches — #396 touches _test/demo-package/**, which brought it back into view.

It fails on the PHP 8.4 matrix entries and passes on 8.3:

composer require "magento/magento-coding-standard:*" "magento/php-compatibility-fork"
  Problem 1
    - magento/framework 103.0.7-p4 requires php ~8.1.0||~8.2.0||~8.3.0
      -> your php version (8.4.27) does not satisfy that requirement.

Why

The action installs the standard into the project under test, so composer require has to solve against that project's lock. _test/demo-package/composer.lock pins magento/framework 103.0.7-p4, which caps PHP at 8.3, so on a PHP 8.4 runner there is no solution — and the check fails before a single sniff runs.

Refreshing the fixture's lock would make this particular red go green, but the coupling is the actual defect, and it recurs for every consumer repository whose lock lags the runner's PHP. phpcs reads files statically and never autoloads the project, so it has no reason to share the project's dependency tree.

What changes

The standard is installed into a directory of its own under RUNNER_TEMP, and phpcs runs from there against path. A project that already vendors the standard still uses its own copy, as before.

Two related fixes in the steps this moves:

  • installed_paths is only written when nothing else wrote it. dealerdirect/phpcodesniffer-composer-installer registers every installed standard, PHPCSUtils among them, which the Magento2 sniffs need. The old step overwrote that with a hand-written pair of paths and dropped it:
    installed_paths: ../../magento/magento-coding-standard,../../magento/php-compatibility-fork,../../phpcsstandards/phpcsutils
    
  • The vendor ignore pattern is quoted. Unquoted, bash expands *vendor/* against the working directory whenever a vendor directory is present, turning --ignore=*vendor/* into a list of real paths plus stray arguments.

Severity inputs now reach the script through env rather than being interpolated into it.

Verified

Locally, with the standard installed in a directory of its own and phpcs run against _test/demo-package:

The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz,
Zend, Magento2, Magento2Framework, PHPCompatibility and PHPCSUtils

No project vendor directory involved, and the demo package's own PHP reports no errors. This PR touches coding-standard/**, so the workflow runs on it and checks itself against the PHP 8.4 entries that were failing.

The check could not run on PHP 8.4. composer require resolves against the
lock of the project under test, so a project locked to a magento/framework
that caps PHP below the runner's version fails to solve:

    - magento/framework 103.0.7-p4 requires php ~8.1.0||~8.2.0||~8.3.0
      -> your php version (8.4.27) does not satisfy that requirement.

phpcs reads files statically and never autoloads the project, so it does
not need to share the project's dependency tree. Installing the standard
in a directory of its own under RUNNER_TEMP removes the coupling: the
check no longer inherits the constraints of the code it is checking. A
project that already vendors the standard still uses its own copy.

Two related fixes in the steps this moves:

Registering installed_paths now only happens when nothing else has.
dealerdirect/phpcodesniffer-composer-installer registers every installed
standard, PHPCSUtils among them, which the Magento2 sniffs need;
overwriting that with a hand-written pair of paths dropped it.

The vendor ignore pattern is quoted. Unquoted, bash expanded it against
the working directory whenever a vendor directory was present, turning
--ignore=*vendor/* into a list of real paths plus stray arguments.
@marcelmtz
marcelmtz requested a review from a team as a code owner November 5, 2026 15:57
@marcelmtz

Copy link
Copy Markdown
Contributor Author

Green on all three matrix entries, including the two PHP 8.4 ones that were failing: run 42060304736.

From the 2.4.9 (PHP 8.4) job:

PHPCS: /home/runner/work/_temp/magento-coding-standard/vendor/bin/phpcs
installed_paths: ../../magento/magento-coding-standard,../../magento/php-compatibility-fork,../../phpcsstandards/phpcsutils

The standard resolved and installed with no reference to the project's lock, and the registration guard found the paths the composer plugin had already written and left them alone — PHPCSUtils included, which is what the old overwrite dropped. phpcs then ran the Magento2 standard over _test/demo-package and exited clean.

@rhoerr rhoerr 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.

LGTM

@marcelmtz
marcelmtz merged commit 901564a into mage-os:main Nov 12, 2026
5 checks passed
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