Composer plugin tasks not executed using the PHP version Composer is invoked with
Given:
- two PHP versions installed side by side -
8.2and8.3 /usr/bin/phpinvokes PHP8.2(managed viaalternatives), so that's the default version- Composer is explicitly invoked with PHP
8.3, i.e./usr/bin/php8.3 ./composer.phar install
In this setup GrumPHP git:init and configure scripts are executed using PHP 8.2 because the plugin calls vendor/bin/grumphp directly instead of using the PHP binary Composer is using for the current invocation.
I'm not familiar with Composer Plugin API enough to tell if Composer exposes internally the PHP binary it was invoked with. However it looks like there is @php syntax for scripts that does something similar to what ${MAKE} would do in a Makefile, so Composer must maintain some sort of reference to the current PHP binary.
Thanks for reporting @echernyavskiy.
The composer plugin is currently indeed not taking into account what PHP version you are executing with. See https://github.com/phpro/grumphp/blob/d6ba4be604db16a4a3fc0d2fc505c0667bbe95c4/src/Composer/GrumPHPPlugin.php#L210 on how this works.
Care to take a dive into the code and craft a PR that fixes this?
@veewee, yeah, that's the file I was looking at, and that's how I arrived at the conclusion above. Any pointers on how to approach this? Like I said I'm not familiar with the Composer Plugin API.
@echernyavskiy It boils down to scrolling through the files in composer/composer.
- vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php
- getPhpExecCommand()
- It seems to be just using '\Symfony\Component\Process\PhpExecutableFinder' (but with additional logic)
The plugin has been created a long way back. Since then, composer has changed a lot. it might make sense to re-evaluate how it works at some point. Here's for example a snippet on how it could be done by using composer dependencies only:
$composer = $event->getComposer();
$loop = $composer->getLoop();
$command_executor = $loop->getProcessExecutor();
$command_executor->executeTty(implode(' ', [
(new PhpExecutableFinder())->find(),
...array_map(static fn(string $argument): string => ProcessExecutor::escape($argument), [
$this->detectGrumphpExecutable(),
'arg...'
]),
]));
(it should probably contain some additional logic for Windows and .exe support)
@veewee from what I can tell PhpExecutableFinder already handles PHP on Windows, so my PR is pretty concise: #1171.