[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.
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