composer require fails with Composer 2
Steps to reproduce
comp require --update-no-dev --update-with-dependencies --no-plugins drupal/entity drupal/smtp drupal/spambot drupal/webform:^6.0 wikimedia/composer-merge-plugin
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
Fatal error: Uncaught Error: Call to undefined method Composer\DependencyResolver\Operation\UpdateOperation::getJobType() in /home/stelnews/public_html/core/lib/Drupal/Core/Composer/Composer.php:170
Stack trace:
#0 phar:///home/stelnews/public_html/composer/src/Composer/EventDispatcher/EventDispatcher.php(319): Drupal\Core\Composer\Composer::vendorTestCodeCleanup(Object(Composer\Installer\PackageEvent))
#1 phar:///home/stelnews/public_html/composer/src/Composer/EventDispatcher/EventDispatcher.php(216): Composer\EventDispatcher\EventDispatcher->executeEventPhpScript('Drupal\\Core\\Com...', 'vendorTestCodeC...', Object(Composer\Installer\PackageEvent))
#2 phar:///home/stelnews/public_html/composer/src/Composer/EventDispatcher/EventDispatcher.php(123): Composer\EventDispatcher\EventDispatcher->doDispatch(Object(Composer\Installer\PackageEvent))
#3 phar:///home/stelnews/public_html/composer/src/Composer/Installer/InstallationManager.php(386): Composer\EventDispatcher\EventDispatcher->dispatchPackageEvent('post-package-up...', in /home/stelnews/public_html/core/lib/Drupal/Core/Composer/Composer.php on line 170
Proposed resolution
Downgrade to composer 1. But that fails with same error!
Remaining tasks
Fix composer2
User interface changes
API changes
Data model changes
Release notes snippet
An incompatibility with Composer 2, which affects a minority of sites when trying to update certain packages, has been fixed in Drupal 9.2.N, 9.3.N, and later. This incompatibility may cause fatal errors similar to:
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
Fatal error: Uncaught Error: Call to undefined method Composer\DependencyResolver\Operation\UpdateOperation::getJobType()
This problem can be fixed permanently by running these commands on any version of Drupal 9:
composer config --unset scripts.post-package-install
composer config --unset scripts.post-package-update
composer require drupal/core-vendor-hardening:^9
Other workarounds require updating Drupal to 9.2.N, 9.3.N, or later, and are documented at https://www.drupal.org/node/3267857.
Comments
Comment #2
jackson.cooper commentedThis patch fixes the issue for me.
Comment #3
jasonhoward7 commentedThis patch worked for me, too. Be sure to run
composer clearcacheafter patching.Comment #4
jasonhoward7 commentedThis patch worked for me, too.
Comment #5
nanakAccording to #3183290: Drupal\Core\Composer\Composer::vendorTestCodeCleanup NOT compatible with Composer 2 you should not rely on vendorTestCodeCleanup anymore but require drupal/core-vendor-hardening instead
Comment #6
drupgirl commented+1 RTBC, as patch in #2 solved this issue.
Comment #7
bendev commentedpatch #2 also working in my setup. Thank you
Comment #8
alezu commentedRemoving "zaporylie/composer-drupal-optimizations" fixed such error for me.
Comment #9
jigariusSeems to be a API change and I think patch #2 is doing a good job at fixing the problem. Since many participants on this issue confirm that patch #2 solves the problem for them, I'm marking this as RTBC.
Comment #10
freelockI'm getting this on every single site I try to update with Composer 2. The patch works. Can we get it committed, please?
Comment #11
pslcbs commentedI also get that error on all my sites when using Composer 2.
Patch work ok.
Please commit.
Thanks
Comment #12
freelockUpdated patch for 9.1.8.
Comment #13
freelockMoving this issue to Core -- what even is the "Composer" project???
Comment #14
amanire commentedI can't believe this isn't a higher priority. This patch doesn't even seem to get applied before the error occurs. I'm finding that I have to manually apply the change to get composer to complete far enough that composer-merge-plugin can start applying patches.
Comment #15
longwaveThanks to everyone for reporting and testing this patch.
If you are running Composer 2 and you have something like the following in composer.json:
then you
composer requirea new package, Composer crashes withThis script predates Drupal 8.8 but there are obviously cases where it is still in use, and we never formally deprecated it. I think this should be committed to all actively supported branches including 8.9.x in order to it easier for people to upgrade to Composer 2.
It should be feasible to add a build test for this script, we have no test coverage for this in core it seems.
Comment #16
longwaveComment #17
longwaveHeavily influenced by ComposerProjectTemplatesTest, this probably needs some refactoring into a trait but this works locally and proves the problem.
Comment #18
longwaveComment #20
amanire commented@longwave just to confirm, you are saying that this call can be safely removed from
composer.jsonin Drupal 8.8+?Comment #21
longwave@amanire: yes, this script has been migrated to a Composer plugin; if you
composer require drupal/core-vendor-hardeningthen you can remove those two lines from your composer.json. See https://www.drupal.org/node/3059717 for more information.Comment #22
amanire commentedGot it, many thanks @longwave!
Comment #24
xjmDoes this still need to be addressed?
Tentatively adding it to the D10 requirements scope as a should-have, in case this is still preventing folks from using Composer 2.
Comment #25
xjmComment #26
phenaproximaI've reviewed this issue, and the code, and I think I understand what's happening here and what the next steps should be.
Who's affected by this bug
Anyone who started a site using the
drupal/drupalComposer project before Drupal 8.8 was released. Before Drupal 8.8,drupal/drupalhad thisvendorTestCodeCleanupscript defined in the root composer.json. It was removed in Drupal 8.8, which introduceddrupal/recommended-projectanddrupal/legacy-project, which don't have this script. (recommended-projectdoesn't need it in the first place, andlegacy-projectincludes thedrupal/core-vendor-hardeningplugin, which does the same thing as the script did.)How to test this
I think that @longwave's build test is sufficient for automated test coverage. However, this should have a manual test to ensure it works when upgrading. The following commands should produce the error, which roughly map to "start a Drupal 8.7 site from
drupal/drupalwith Composer 1, then update to Composer 2 and try to update to Drupal 9":At this point, edit composer.json to remove the
replacesection. Then continue:Without the patch, this should produce the fatal error from the issue summary.
Is there a workaround?
Yes, there are three.
#1: Replace the broken script with the
drupal/core-vendor-hardeningplugin, as @longwave said in #21. Assuming you're running Drupal 9, the following commands oughta do the trick:This is the more permanent fix.
#2: When this patch is committed -- let's say it's released in 9.3.8 -- disable scripts while upgrading core to that version:
#3: When this patch is committed, use Composer 1 to update to the fixed version. As far as I can tell, Composer 1 is unaffected by this bug. So you could do something like:
Next steps
Comment #27
xjmAwesome, thanks @phenaproxima. So I think the next steps are:
Comment #28
phenaproximaDraft change record written: https://www.drupal.org/node/3267857
We'll need to update it with the real core versions that will contain the fix.
Comment #29
phenaproximaAdded release note to the issue summary.
Comment #30
phenaproximaKicking this back to "needs work", since the patch is not passing Drupal CI.
Comment #31
phenaproximaI agree with @longwave that this (and a bunch of other stuff in the test) should all be refactored into a trait, since it came from another build test, but it's out of scope here. We should probably open a follow-up issue for that.
We could also modify the existing build tests to add that script, which would allow us to not duplicate code. But then we'd be testing legacy junk in our non-legacy tests, which isn't great. But then again, Composer scripts are not like other "legacy" code -- if developers don't explicitly remove them from composer.json, they stay there forever. So they occupy a weird middle ground between legacy and non-legacy. So maybe what we have is fine, except for the copypasta we should clean up later.
Otherwise, code looks great to me. No objections at all to RTBC, once the patch is passing tests.
Comment #32
phenaproximaAdded #3268426: Abstract common build test logic into a trait.
All this needs now is for the spelling error to be fixed ("SUT" can be replaced with "system under test" or "site under test") and, when tests pass, IMHO this is ready to be committed.
Comment #33
spokjeRan with site under test in attached patch.
Comment #34
spokjeComment #35
phenaproximaNice, let's get this in.
Committers, this is tagged "needs change record updates" so that we will say which tagged versions of core introduced this fix.
Comment #36
longwaveOnce this is done we should work on deprecating these scripts and migrating users to the plugin equivalents over in #3076684: Remove deprecated vendor cleanup scripts
Comment #37
alexpottCommitted and pushed 05ff954188 to 10.0.x and 55bb63f889 to 9.4.x and 6dd760025e to 9.3.x. Thanks!
Comment #41
alexpottI went to update the change record - but I'm really not sure that the CR serves any purpose. The CR is announcing a bug is fixed. From Drupal 9.3.x onwards no one is going to need to do anything as the bug has been fixed - right? I think the CR will be more applicable to #3076684: Remove deprecated vendor cleanup scripts - where we'll need to issue a deprecation and tell people to remove the old script from their root composer.json. For similar reasons I'm not sure what the release note is telling people. Like now this has been fixed what does someone actually need to do?
Comment #42
phenaproximaAs per discussion with @xjm, the CR is there to tell people about the workarounds for the bug, so that they can actually stay up to date in the interim until this is released. Or, in trickier scenarios, so that they can update at all.
Comment #43
alexpott@phenaproxima I guess the problem is is that CR's are for telling people to make changes in response to changes we've made. I'm not sure why someone would look for a CR to work-around a bug that is fixed by the issue that is linked to the CR. If you have this problem you are way more likely to go to the issue queue and, fingers-crossed, find this issue. Which hopefully documents the work-arounds in the issue summary.
Comment #45
quietone commentedthe change record has been updated, removing tag.