composer / composer

Dependency Manager for PHP

Home Page:https://getcomposer.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[feature] Build and distribute scoped version of Composer

mxr576 opened this issue · comments

Today I bumped into an interesting error in my Composer Plugin's test suite:

PHP Fatal error:  Declaration of React\Promise\Internal\FulfilledPromise::then(?callable $onFulfilled = null, ?callable $onRejected = null): React\Promise\PromiseInterface must be compatible with React\Promise\PromiseInterface::then(?callable $onFulfilled = null, ?callable $onRejected = null, ?callable $onProgress = null) in /home/runner/work/monorepo/monorepo/php-libraries/package-installer/tools/test/vendor/react/promise/src/Internal/FulfilledPromise.php on line 37

(Spoiler: reactphp/promise@4ab99a6)

The Composer Plugin has a similar setup that you can see in https://github.com/Roave/BetterReflection, dev dependencies are isolated from the root composer.json to avoid unexpected dependency conflicts.

image

Both the root composer.json and the tools/test/composer.json requires composer/composer:^2.6.0 with the same version constraint because
the plugin is tested in isolation in a similar way that can be seen here https://github.com/drupal/core/blob/10.2.4/tests/Drupal/Tests/Composer/Plugin/Scaffold/Fixtures.php

Based on CI logs, what happened is that:

  • root composer.json installed react/promise:2.1.0 (from composer.lock)
  • tools/test/composer.json instealled react/promise:3.1.0 (from its own composer.lock)

and it seems this confused the autoloader...

Proposed solution

Rector/PHPStan and other popular CLI command providers already generates and distributes scoped version of packages to avoid similar problems by leveraging https://github.com/humbug/php-scoper.

https://github.com/rectorphp/rector-src/blob/main/.github/workflows/build_scoped_rector.yaml