Using Composer to debug issues updating Drupal core
Share:
This week whilst trying to update one of our projects to the latest version of Drupal 8 core, we had some issues.
We use Composer to manage our dependencies, modules etc, and on this particular occasion, things weren't straightforward.
In order to solve it, we had to use some of the lesser known features of Composer, so decided to share.
by
lee.rowlands
/ 11 August 2017
The problem
So updating Drupal core with composer is normally pretty simple. And on this occasion, we had no reason to suspect it would be anything different.
Normally we'd just run
composer update "drupal/core" --with-dependencies
But this time, nothing happened.
So we checked that there was a newer version available
composer show -a "drupal/core"
And sure enough, we can see 8.3.6 in the available versions.
Time to dig deeper.
The why
Luckily, composer will tell you why it won't install something.
composer why-not "drupal/core:8.3.6"
Which yielded
drupal/core 8.3.6 conflicts drush/drush (
Aha, so drush is the issue.
So maybe we just update both
composer update "drupal/core" "drush/drush"
Nope.
Digging deeper
So after trying a few different combinations of version constraints etc, we decided to remove drush, update and then add it back.
composer remove --dev "drush/drush"
Which worked.
composer update "drupal/core" --with-dependencies
Ok, nice, we now have Drupal 8.3.6
composer require --dev "drush/drush"
Nope.
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Installation request for drush/drush 8.1.12 -> satisfiable by drush/drush[8.1.12].
- Conclusion: remove phpdocumentor/reflection-docblock 3.2.2
- Conclusion: don't install phpdocumentor/reflection-docblock 3.2.2
- drush/drush 8.1.12 requires phpdocumentor/reflection-docblock ^2.0 -> satisfiable by phpdocumentor/reflection-docblock[2.0.0, 2.0.0a1, 2.0.0a2, 2.0.0a3, 2.0.1, 2.0.2, 2.0.3, 2.0.4, 2.0.5].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.0, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.0a1, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.0a2, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.0a3, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.1, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.2, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.3, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.4, 3.2.2].
- Can only install one of: phpdocumentor/reflection-docblock[2.0.5, 3.2.2].
- Installation request for phpdocumentor/reflection-docblock (locked at 3.2.2) -> satisfiable by phpdocumentor/reflection-docblock[3.2.2].
Installation failed, reverting ./composer.json to its original content.
Hm, so we have a version of phpdocumentor/reflection-docblock in our lock file that is too high for drush.
composer why "phpdocumentor/reflection-docblock"
Yields
phpspec/prophecy v1.6.1 requires phpdocumentor/reflection-docblock (^2.0|^3.0.2)
Aha, so prophecy - but it allows either version .. but our lock file has pinned it to the 3.x branch
So lets force composer to downgrade that
composer require --dev "phpdocumentor/reflection-docblock:^2.0"
Now lets see if we can add drush back
composer require --dev "drush/drush"
Success!
Now all that remains is to clean up, because we don't really want to depend on phpdocumentor/reflection-docblock
composer remove --dev "phpdocumentor/reflection-docblock"
Done - quick - commit that lock file while you're winning!
Summary
So while it might be easy to curse Composer for not letting you upgrade, its actually doing exactly what you told it to do.
Your lock file has a pinned version, it is honoring that.
And in order to resolve it, Composer provides all the tools you need in the form of the why and the why-not commands.
Tagged
Posted by
lee.rowlands
Senior Drupal Developer
Dated 11 August 2017
Comments
Comment by
Brian
Dated 11 August 2017
Wow, never knew about the "why" and "why-not" commands. Very good to know for future debugging! Thanks
Comment by
James Williams
Dated 14 August 2017
As long as your package version constraints in your composer.json file are appropriate - e.g. drupal/core could be "~8.3.3", and drush/drush at "~8.1.10" then updating both at the same time, like this, should have worked:
composer update drupal/core drush/drush --with-dependencies
You did mention updating them both in a single command, but not with the 'with-dependencies' bit, perhaps that's all that was needed? (As it's a common dependency that needed changing.)
Or maybe there's something else in your repo / configuration / composer files that was causing this?
Comment by
Benji Fisher
Dated 15 August 2017
Sometimes the dependency chains are a lot longer. If you do not want to use "composer why" three times to figure out that sugar/white is required by pancake/blueberry, which is required by sunday/brunch which is required by your project, then you can use the --recursive (-r) flag:
composer why -r sugar/white
Also, I wonder how different the results would have been if you had let composer deal with it:
rm composer.lock && composer install
Comment by
greg.1.anderson
Dated 15 August 2017
Thanks for a great explanation of `composer why` and `composer why-not`. This is a good guide on how to diagnose and get around problems with updates and the composer.lock file.
However, running `composer update "drupal/core" --with-dependencies` is in general not something that you want to do on your Drupal site. The reason is that the Drupal core developers only update Drupal's dependencies on minor releases -- e.g. from 8.3.x to 8.4.0. If you use `composer update` to get a newer patch release of Drupal core, then you will end up with a different set of dependencies than Drupal is currently using. While this should, in general work, your configuration will not be exactly the same as the one that the core committers are testing, so you become more likely to encounter new dependency bugs before the rest of the community. If your goal is to update a site that is in production, this is generally not what you want.
To work around this problem, try using https://github.com/webflo/drupal-core-strict. This project contains tagged releases that strongly constrain the versions of all of Drupal's dependencies to match what is being tested in Drupal core. If you require this project in your Composer-managed Drupal site, then you will be able to use `composer update` to update your non-Drupal-core-releated dependencies without bringing in more updates than intended.
For additional background on phpdocumentor version constraints and Drush, see https://github.com/drush-ops/drush/pull/2877
Comment by
kim.pepper
Dated 15 August 2017
We had an issue where a Guzzle security update was needed, but we didn't want to wait for a core release in order to fix it. If core sets its version ranges correctly, updating patch versions should not be a problem.
Pagination
Add new comment