composer: [Regression] class loading does not work since 2.1.0-RC1

Using composer 2.0.12 it works fine and starting with 2.1.0-RC1 and all the next ones it does not work anymore

Example fail: https://github.com/phpmyadmin/phpmyadmin/runs/2753645987?check_suite_focus=true#step:13:672

See pass/fails: https://github.com/phpmyadmin/phpmyadmin/actions/workflows/other-tools.yml?query=branch%3AQA_5_1

On the phpMyAdmin release script we create a sandbox folder for phpunit: https://github.com/phpmyadmin/phpmyadmin/blob/QA_5_1/scripts/create-release.sh#L234

And then we run phpunit using it’s path in the actual bundled release: https://github.com/phpmyadmin/phpmyadmin/blob/QA_5_1/scripts/create-release.sh#L440

Now it throws a strange error Uncaught Error: Class 'PhpMyAdmin\Tests\Stubs\DbiDummy' not found in /home/runner/work/phpmyadmin/phpmyadmin/release/phpMyAdmin-ci/test/bootstrap-dist.php:54: https://github.com/phpmyadmin/phpmyadmin/runs/2745731618?check_suite_focus=true#step:13:628

As you can see we require the autoloader file before calling the actual code: https://github.com/phpmyadmin/phpmyadmin/blob/QA_5_1/test/bootstrap-dist.php#L46

It never failed before, and now that all composer binaries are updated, it fails everywhere we test it

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 16 (8 by maintainers)

Commits related to this issue

Most upvoted comments

array_shift(https://seld.be/wishlist)

Ok, I’d perhaps recommend using --no-dev explicitly on the last dump-autoload just for making it more self documenting but otherwise looks good I guess 😃

Just tested and the fix is quite slim thanks to you: https://github.com/phpmyadmin/phpmyadmin/commit/1397588a17da297fea8cfd001db76fdecb4f07e3

I just changed composer dump-autoload into composer dump-autoload --dev and after tests ran composer dump-autoload.

To detail our process for the record (a bit simplified):

  • require the minimal php version extracted from the php require restriction composer config platform.php "$PHP_REQ"
  • install without dev modules composer update --no-interaction --no-dev --optimize-autoloader
  • install optional packages in the vendor folder composer require --no-interaction --optimize-autoloader --update-no-dev $PACKAGES_VERSIONS
  • restore original composer.json because previous commands have affected it
  • do things
  • clean up vendor folders and files nobody cares about in production (.github, tests folders, and so much more crap)
  • create the phpunit test sandbox
  • backup vendor folder (not usefull but more security is good)
  • dump autoload in dev mode to make test classes load nicely (thanks !!)
  • run tests
  • dump it back
  • restore vendor folder
  • do things

Finished !!

Just as a hint in case you didn’t see it, when using composer require you can also pass --dev to add it to require-dev, making sure whatever req you add it’ll be removed when doing an install --no-dev.

We need to do this, any composer command would screw up the vendor folder we ship to our users

I would say you could archive before you run composer install to restore dev dependencies, so as to avoid screwing up the archive… Or you could install fully, run tests, then composer install --no-dev to remove dev dependencies before archiving if the tests passed. Then you would still not need the phpunit in a separate directory.

Anyway I can see why someone may under weird circumstances want autoload-dev active even though dev requirements are not installed, so I added a flag and you can now call composer dump-autoload --dev to ensure you get autoload-dev included. This will however “screw up” your vendor dir too in a sense as it makes things autoloadable which IMO shouldn’t be in a prod context, so I would still advise you to take a good look at my first paragraph here 😃 This’ll be in 2.1.2 which I’ll go and release now.

Yes, that explains why you do this, thanks 😃

Perhaps one misunderstanding on your end though is that installing your dev requirements again does not alter your require, but it does make more packages available, which may mean that your tests pass even though they would not without require-dev in case some of your code inadvertently depends on some code from a dev dependency. That may still be the case if you implicitly depend on something that phpunit also depends on though, so the safe way to check for this IMO is to use https://packagist.org/packages/maglnet/composer-require-checker - not to require phpunit in a separate directory.

Makes sense?

Oh sorry, the phpunit require happens in a different directory… So https://github.com/phpmyadmin/phpmyadmin/blob/master/scripts/create-release.sh#L410 using --update-no-dev definitely seems to be the culprit.

This broke due to https://github.com/composer/composer/pull/9714 because you then do a dump-autoload at https://github.com/phpmyadmin/phpmyadmin/blob/master/scripts/create-release.sh#L439 and it now does not include your autoload-dev rules anymore because the dev dependencies are not installed.

We do not have a way to force autoload-dev rules to be dumped though in dump-autoload… So for now the workaround would be to use composer install instead of composer dump-autoload, which will install your dev dependencies and redump the autoloader including dev dependencies and your autoload-dev rules.

If you do see a real use case for having a vendor dir without require-dev dependencies, but with your autoload-dev rules, I’d be interested in the details of that… IMO if you run dev stuff you should have the dev dependencies installed. In this instance you install phpunit in another dir so it kinda skews this by bypassing require-dev. But if there’s a valid case I guess we could add a --dev flag to dump-autoload.

I can’t reproduce it like that though, the last require without --update-no-dev dumps autoload-dev rules correctly… So I am not entirely sure what is going on, but you do so many installs in a row I believe it’s related to that somehow.