Framework: [5.5] Problem with composer script and a package

Created on 5 Sep 2017  路  12Comments  路  Source: laravel/framework

  • Laravel Version: 5.5.1
  • PHP Version: 7.0.22
  • Database Driver & Version: unrelated

Description:

This seem unrelated to laravel but please read.

When you try to install a package that also executes some scripts on install, like phpro/grumphp, you could run in errors because the autoload seems to be confused.

This ocurred to me when updating an app wich uses phpro/grumphp to laravel 5.5. I removed all the dependencies and executed composer install (without a lock file), this produced an error

[Symfony\Component\Debug\Exception\FatalThrowableError]                      
  Type error: Argument 6 passed to Symfony\Component\Process\Process::__construct() must be of the type array, null given, called in /workspace/php/test/vendor/symfony/process/ProcessBuilder.php on line 274
Exception trace:
() at phar:///usr/bin/composer/vendor/symfony/process/Process.php:141
Symfony\Component\Process\Process->__construct() at /workspace/php/test/vendor/symfony/process/ProcessBuilder.php:274
Symfony\Component\Process\ProcessBuilder->getProcess() at /workspace/php/test/vendor/phpro/grumphp/src/Composer/GrumPHPPlugin.php:182
GrumPHP\Composer\GrumPHPPlugin->runGrumPhpCommand() at /workspace/php/test/vendor/phpro/grumphp/src/Composer/GrumPHPPlugin.php:137
...

You wont find any laravel related class, but if you look you will see that Process and ProcessBuilder are readed one from the phar (the composer phar) and another from the local vendor folder. So the version used of symfony/process differ (2.8 in the phar, 3.3 for laravel) and breaks the phpro/grumphp script that should run on installation.

After trying to debug this I realized that Illuminate\Foundation\ComposerScripts::postAutoloadDump loads the autoload of composer, removing this script off composer.json makes composer install work fine again. It looks like any script executed by composer after executing ComposerScripts::postAutoloadDump will have a "messed up" autoloader (I'm not shure of this), clashing the composer phar autoloader and the local autoloader.

A workaround could be change the composer.json like this:

{
    "scripts": {
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate"
        ],
        "post-install-cmd": [
            "Illuminate\\Foundation\\ComposerScripts::postInstall"
        ],
        "post-update-cmd": [
            "Illuminate\\Foundation\\ComposerScripts::postUpdate"
        ],
        "post-autoload-dump": [
            "@php artisan package:discover"
        ]
    },
}

Seems like the order of execution of the scripts resolve the problem, the scripts of the package are executed first so there is no problem, at least for this case.

Steps To Reproduce:

$ laravel new test
$ cd test
$ composer require --dev phpro/grumphp -vvv

This is a edge case, maybe phpro/grumphp it's the only package producing errors, but I think that the problem is in the composer script defined by laravel. Maybe another package that uses symfony/process and runs on composer events would fall in the same problem.

Most helpful comment

Yeah I think this should be reopened. It was never solved.

All 12 comments

This repo is for bug reporting. What you are noting is an error with the package itself. Its not an issue with Laravel

Ya i agree with @srmklive. You should raise an issue on the package you are using instead of here.

First I blamed the package too, but couldn't find anything wrong with it. I tested it in various scenarios and everything was ok.

But you're right I need to eliminate the package from the issue. So you can reproduce this bug without the package.

Create a new app, next define something callable, like:

<?php
# app/Test.php
namespace App;
use Symfony\Component\Process\ProcessBuilder;
class Test
{
    public static function test()
    {
        $builder = new ProcessBuilder(['ls']);
        $builder->getProcess();
    }
}

Then put it in the post autoload dump event of composer, like this:

{
...
"scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "App\\Test::test",
            "@php artisan package:discover"
        ]
    }
}
...

Now run composer dumpautoload, you will get the same error. Notice the order of the scripts, if you put first App\Test::test composer wont fail.

Also it will fail only if you fall in a conflict of dependencies, in this case composer has it's own version of ProcessBuilder which is incompatible with the version used in laravel.

Like I said, I already found a workaround but I think that maybe this will produce some errors to others. And in the end I'm confused too of where to put this bug, but i think that the cause of the problem is this line of code.

@nerones kindly close the issue

I have the same problem here https://github.com/phpro/grumphp/issues/414#issuecomment-339922372

It seems this was closed without a real solution.

Yeah I think this should be reopened. It was never solved.

same here

Seems a gruphp problem, it use deprecated methods to exec process using Symfony\Component\Process\Process
I made the fix forking the repo: https://github.com/bitbull-team/grumphp/commit/47693ba9b0b0e84b244db0cbf42d97d64d04f700

I'll open a PR to grumphp to fix this issue.

I managed to replace GrumPHP easily with the plain composer.json file:

"require": {
        "brainmaestro/composer-git-hooks": "^2.4"
},
"extra": {
    "hooks": {
        "pre-commit": "composer my-script"
    }
},
"scripts": {
    "my-script": [
        "vendor/bin/php-cs-fixer fix --diff --ansi",
        "vendor/bin/phpunit --color=always"
    ]
}

Generating optimized autoload files

IlluminateFoundationComposerScripts::postAutoloadDump
@php artisan package:discover

In ResourceRegistrar.php line 360:

Object of class Closure could not be converted to string

Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1
I'm using laravel 5.6

@mohannad1995

    "require-dev": {
        "phpro/grumphp": "dev-master",
    },

will fix your problem.
Is not a Laravel issue

Was this page helpful?
0 / 5 - 0 ratings