Box does not work with Composer 2.2 (allowed-plugins)
Bug report
| Question | Answer |
|---|---|
| Box version | 3.14.0 |
| PHP version | 8.0 |
| Github Repo | https://github.com/infection/infection/pull/1623 |
Box fails compiling a prefixed PHAR with the brand new Composer 2.2 is used:
? Dumping the Composer autoloader
In ComposerOrchestrator.php line 92:
Could not dump the autoloader.
In ComposerOrchestrator.php line 92:
The command "'/usr/local/bin/composer' 'dump-autoload' '--classmap-authorit
ative' '--no-dev'" failed.
Exit Code: 1(General error)
Working directory: /tmp/box/Box46412
Output:
================
Error: require(/tmp/box/Box46412/vendor/phpstan/phpstan/bootstrap.php):
Failed to open stream: No such file or directory
Error Output:
================
For additional security you should declare the allow-plugins config with a
list of packages names that are allowed to run code. See https://getcompose
r.org/allow-plugins
You have until July 2022 to add the setting. Composer will then switch the
default behavior to disallow all plugins.
[ErrorException]
require(/tmp/box/Box46412/vendor/phpstan/phpstan/bootstrap.php): Failed t
o open stream: No such file or directory
dump-autoload [-o|--optimize] [-a|--classmap-authoritative] [--apcu] [--apc
u-prefix APCU-PREFIX] [--dev] [--no-dev] [--ignore-platform-req IGNORE-PLAT
FORM-REQ] [--ignore-platform-reqs]
compile [-c|--config CONFIG] [--debug] [--no-parallel] [--no-restart] [--dev] [--no-config] [--with-docker] [-d|--working-dir WORKING-DIR]
make: *** [Makefile:253: build/infection.phar] Error 1
Note: Infection had issues with Composer 2.2 too, fixed by adding allowed-plugins configuration: https://github.com/infection/infection/pull/1624
I've reproduced this problem in a minimal repo: https://github.com/ondrejmirtes/composer-issue/actions/runs/1765720462
I can offer some funds towards fixing this problem, so don't hesitate to reach out. Thanks.
Should be fixed with 3.15!
@theofidry
I still reproduce it in Infection repository with 3.16.0 both with make compile (PHP 8.1, Composer 2.2) and with make compile-docker (PHP 7.4)
In ComposerOrchestrator.php line 175:
The command "'/usr/local/bin/composer' 'dump-autoload' '--classmap-authoritative' '--no-dev' '--ansi'" failed.
Exit Code: 1(General error)
Working directory: /tmp/box/Box39427
Output:
================
Error Output:
================
[ErrorException]
require(/tmp/box/Box39427/vendor/phpstan/phpstan/bootstrap.php): Failed to open stream: No such file or directory
dump-autoload [-o|--optimize] [-a|--classmap-authoritative] [--apcu] [--apcu-prefix APCU-PREFIX] [--dev] [--no-dev] [--ignore-platform-req IGNORE-PLATFORM-REQ] [--ignore-platform-reqs]
I agree. This isn't related to allow-plugins. It still doesn't work with latest Box and Composer.
Ok finally found the issue.
The problem is that dump-autoload does not really care about the --dev|--no-dev flag. It looks like it only cares about it for the actual dumped autoload, but before that, i.e. when autoloading the code, it does not and instead just loads everything that is registered in installed.json|installed.php.
The way Box works is:
- copy the source code
- remove dev deps
- dump the autoload
This means that if you have a dev plugin, e.g. phpstan/extension-installer, when dumping the autoload, the plugin will be attempted to be loaded. This of course cannot work since it's a dev dep and Box removed it.
I think this could be solved in Composer, but I also cannot just wait for a fix there so I'll likely need to temper the content of installed.json & installed.php
What if you add --no-plugins to the autoload command?
@jaapio in which case this would break the bundling of any Symfony app which uses Flex. I'm not familiar enough with other frameworks, but this makes me believe there could be other affected too so it's not really the solution.
Have just run into this here as well.
I've worked around it by:
- creating a clean copy of the package (I'm using
git clone, but any method where the package is duplicated without itsvendordirectory should work) - running
composer install --no-devin the clean copy - running
box compilein the clean copy
Composer's behaviour here isn't unreasonable, though. I wouldn't expect a package manager to remain operational if critical files were deleted, and from the discussion here and a quick read of the documentation, it seems reasonable for composer commands to fail if an enabled plugin is removed from the filesystem.
Would it be feasible to use composer --no-dev install to create the initial state of a package instead of removing dev dependencies at the filesystem level?
Would it be feasible to use composer --no-dev install to create the initial state of a package instead of removing dev dependencies at the filesystem level?
Yes and no.
Currently the whole process is:
- load the Box config a first time
- copy the whole project; excluding the unnecessary files, the copied files are processed by the compactors
- dump the autoloader
- ship the files to the PHAR
What the above entails would mean:
- load the Box config a first time
- copy the whole project
- install the no-dev deps
- reload the Box config and apply the compactors (which can include the scoping) and remove the unnecessary files
- ship the files to the PHAR
So it's really not a trival amount of changes and probably a big performance hit too.