I recently wrote about a common question I get: “When Should I Update to Drupal 9?” Today I thought it would be fun to go through the actual process and update the Drupal4Gov.us website from Drupal 8.9.2 to Drupal 9.0.2. This blog will cover the process!
A few overview type things for the project:
PHP 7.3
Lando VM
Composer Managed
Config Split Managed
BLT Project
Hosted on Acquia
Here’s a quick snapshot of my dependencies before I started anything:
"require": { "php": ">=7.3", "acquia/blt": "^11.0", "acquia/drupal-spec-tool": "^2.0.0", "acquia/lightning": "^4.0", "acquia/memcache-settings": "*", "drupal-composer/drupal-scaffold": "^2.5.4", "drupal/acquia_connector": "^2", "drupal/acquia_purge": "^1.0", "drupal/admin_toolbar": "^2.0", "drupal/adminimal_admin_toolbar": "^1.11", "drupal/cog": "^1.0.0", "drupal/config_ignore": "^2.1", "drupal/config_split": "^1.0.0", "drupal/core": "~8.9.0", "drupal/devel": "^2.1", "drupal/easy_breadcrumb": "^1.6", "drupal/environment_indicator": "^3", "drupal/field_group": "^3.0", "drupal/google_analytics": "^2.2", "drupal/multiple_fields_remove_button": "^1.0@alpha", "drupal/paragraphs": "^1.2", "drupal/qa_accounts": "^1.0.0-alpha1", "drupal/recaptcha": "^2.2", "drupal/seckit": "^1.0.0-alpha2", "drupal/shield": "^1.2" },
I have spent some effort over the past few months updating “some” of these modules to their D9 compatible versions. However, I definitely didn’t catch all of them (and I knew this going in).
My first step was to update the few packages I “knew” had to change. These were:
drupal/core: ^9.0
acquia/lightning: ^5.0
acquia/blt: ^12.0
From here I just ran composer update. (Yes, I did! I know I pretty regularly say “don’t do this.” This is one of those “special cases” where you probably do need to do it). In fact, I also removed my vendor folder and composer.lock folder!
composer update 1/1: https://packages.drupal.org/8/drupal/provider-2020-2$54e0987bd27ea96fed794fd76bc1d3347177dd144e8119351e4f15fad1314e19.json Finished: success: 1, skipped: 0, failure: 0, total: 1 Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages. Problem 1 - Conclusion: don't install drupal/core 9.0.2 - Conclusion: don't install drupal/core 9.0.1 - acquia/lightning 5.0.0 requires drupal/core ~9.0.1 -> satisfiable by drupal/core[9.0.1, 9.0.2, 9.0.x-dev]. - acquia/lightning 5.0.x-dev requires drupal/core ~9.0.1 -> satisfiable by drupal/core[9.0.1, 9.0.2, 9.0.x-dev]. - acquia/lightning 5.0.0-beta3 requires drupal/core ~9.0.1 -> satisfiable by drupal/core[9.0.1, 9.0.2, 9.0.x-dev]. - Conclusion: don't install drupal/core 9.0.x-dev - Conclusion: don't install acquia/lightning 5.0.0-beta2 - Conclusion: don't install acquia/lightning 5.0.0-beta1 - acquia/lightning 5.0.0-alpha1 requires drupal/lightning_api 4.x-dev -> satisfiable by drupal/lightning_api[4.x-dev]. - Installation request for acquia/lightning ^5.0 -> satisfiable by acquia/lightning[5.0.0, 5.0.0-alpha1, 5.0.0-beta1, 5.0.0-beta2, 5.0.0-beta3, 5.0.x-dev]. - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-alpha2 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-beta1 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-beta2 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-beta3 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-rc1 - Installation request for drupal/devel ^2.1 -> satisfiable by drupal/devel[2.x-dev, 2.1.0]. - drupal/lightning_api 4.x-dev requires drupal/core ^8.8.8 || ^9.0.1 -> satisfiable by drupal/core[8.8.x-dev, 8.9.x-dev, 9.0.1, 9.0.2, 9.0.x-dev, 9.1.x-dev]. - Can only install one of: drupal/core[9.0.0-alpha1, 8.8.x-dev]. - Can only install one of: drupal/core[9.0.0-alpha1, 8.9.x-dev]. - Can only install one of: drupal/core[9.1.x-dev, 9.0.0-alpha1]. - acquia/lightning 5.0.0-alpha1 requires drupal/core ~9.0.0 -> satisfiable by drupal/core[9.0.0, 9.0.0-alpha1, 9.0.0-alpha2, 9.0.0-beta1, 9.0.0-beta2, 9.0.0-beta3, 9.0.0-rc1, 9.0.1, 9.0.2, 9.0.x-dev]. - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0
Well, that’s ugly output. It’s also incredibly misleading. I only post it here to show you how critical it is to read the ENTIRE output. I know that Lightning 5.x is D9 compatible (but composer is complaining about it). Here’s the line in all that output that matters:
- Installation request for drupal/devel ^2.1 -> satisfiable by drupal/devel[2.x-dev, 2.1.0].
I ran over to Drupal.org and checked the Devel page and checked compatible versions. The 2.x branch of Devel is not D9 compatible (but the 4.x branch is). So I updated my dependencies to:
drupal/devel: ^4
I can composer update again:
composer update 1/6: http://repo.packagist.org/p/provider-latest$667607470b8450e352ba0bb4d9be8ef724f594ce203c1ae0acf017c07bfd19fb.json 2/6: http://repo.packagist.org/p/provider-2015$998e908be5ed1d999705eb5039e1562f72b7f2df22472345e8b2e03fbf7fe9f9.json 3/6: http://repo.packagist.org/p/provider-2019-10$ac58178771b15cbac8e0f299f5280470155557cb4069d847b6209b2cca25ffb1.json 4/6: http://repo.packagist.org/p/provider-2020-01$913e600e6fb18a7590db2514dc9dbff45228bbd1fdcacaa0634efbb9682a79af.json 5/6: http://repo.packagist.org/p/provider-2020-04$842a312d966f942398f1e5514fc4e442876933c455e2bb88eae10a5eb8c4b3b4.json 6/6: http://repo.packagist.org/p/provider-2019$c6b1fc2327466423c40f17f29b688fa7e9a3b07e2799bc28f1c7e40906549d14.json Finished: success: 6, skipped: 0, failure: 0, total: 6 Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages. Problem 1 - Conclusion: don't install drupal/core 9.0.2 - Conclusion: don't install drupal/core 9.0.1 - acquia/lightning 5.0.0 requires drupal/core ~9.0.1 -> satisfiable by drupal/core[9.0.1, 9.0.2, 9.0.x-dev]. - acquia/lightning 5.0.x-dev requires drupal/core ~9.0.1 -> satisfiable by drupal/core[9.0.1, 9.0.2, 9.0.x-dev]. - acquia/lightning 5.0.0-beta3 requires drupal/core ~9.0.1 -> satisfiable by drupal/core[9.0.1, 9.0.2, 9.0.x-dev]. - Conclusion: don't install drupal/core 9.0.x-dev - Conclusion: don't install acquia/lightning 5.0.0-beta2 - Conclusion: don't install acquia/lightning 5.0.0-beta1 - acquia/lightning 5.0.0-alpha1 requires drupal/lightning_api 4.x-dev -> satisfiable by drupal/lightning_api[4.x-dev]. - Installation request for acquia/lightning ^5.0 -> satisfiable by acquia/lightning[5.0.0, 5.0.0-alpha1, 5.0.0-beta1, 5.0.0-beta2, 5.0.0-beta3, 5.0.x-dev]. - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-alpha2 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-beta1 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-beta2 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-beta3 - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0-rc1 - Installation request for drupal/recaptcha ^2.2 -> satisfiable by drupal/recaptcha[2.x-dev, 2.2.0, 2.3.0, 2.4.0, 2.5.0]. - drupal/lightning_api 4.x-dev requires drupal/core ^8.8.8 || ^9.0.1 -> satisfiable by drupal/core[8.8.x-dev, 8.9.x-dev, 9.0.1, 9.0.2, 9.0.x-dev, 9.1.x-dev]. - Can only install one of: drupal/core[9.0.0-alpha1, 8.8.x-dev]. - Can only install one of: drupal/core[9.0.0-alpha1, 8.9.x-dev]. - Can only install one of: drupal/core[9.1.x-dev, 9.0.0-alpha1]. - acquia/lightning 5.0.0-alpha1 requires drupal/core ~9.0.0 -> satisfiable by drupal/core[9.0.0, 9.0.0-alpha1, 9.0.0-alpha2, 9.0.0-beta1, 9.0.0-beta2, 9.0.0-beta3, 9.0.0-rc1, 9.0.1, 9.0.2, 9.0.x-dev]. - Conclusion: don't install drupal/lightning_api 4.x-dev|don't install drupal/core 9.0.0
Again, that’s pretty messy (and a lot of fingers pointed at Lightning). Did you notice the thing that changed?
- Installation request for drupal/recaptcha ^2.2 -> satisfiable by drupal/recaptcha[2.x-dev, 2.2.0, 2.3.0, 2.4.0, 2.5.0].
So, again I ran to Drupal.org and checked out the Recaptcha page. Again, I was running the 2.x branch and in this case only the 3.x branch is compatible with D9. So I updated that as well, and re-ran composer update.
This time, composer ran successfully! I tweaked a few other composer dependencies (e.g. BLT broke out a few of its packages in 12.x, so I had to manually add phpcs and behat back in).
"require": { "php": ">=7.3", "acquia/blt": "^12.0", "acquia/blt-behat": "dev-master", "acquia/blt-phpcs": "dev-master", "acquia/drupal-spec-tool": "^4.0.0", "acquia/lightning": "^5.0", "acquia/memcache-settings": "^1", "drupal/acquia_connector": "^2", "drupal/acquia_purge": "^1.0", "drupal/admin_toolbar": "^2.0", "drupal/adminimal_admin_toolbar": "^1.11", "drupal/cog": "^1.0.0", "drupal/config_ignore": "^2.1", "drupal/config_split": "^1.0.0", "drupal/core": "^9.0", "drupal/devel": "^4.0", "drupal/easy_breadcrumb": "^1.6", "drupal/environment_indicator": "^3", "drupal/field_group": "^3.0", "drupal/google_analytics": "^2.2", "drupal/multiple_fields_remove_button": "^1.0@alpha", "drupal/paragraphs": "^1.2", "drupal/qa_accounts": "^1.0.0-alpha1", "drupal/recaptcha": "^3.0", "drupal/seckit": "^1.0.0-alpha2", "drupal/shield": "^1.2" },
The next step is to update my configuration. Theoretically, there are not going to be “many” changes since Drupal 8.9.x and Drupal 9.x are feature identical. But, with any core update you should always run database updates and export config (just to be sure you didn’t miss anything).
Since this is a Lando + BLT project, I ran the following commands:
lando blt sync:db
This command pulls my database from the cloud. Note that I didn’t run a full blt sync (because that will do more things than I want, here). This JUST does a sql-sync and a sql-sanitize. Then stops.
lando drush updb -y
I ran any database updates related to my core/contrib changes in the above composer changes.
lando drush cex -y
I exported the configuration changes.
Since there were quite a few database updates and a few config changes, I also took the additional step of doing a clean installation and re-exported config, just to be sure that nothing else slipped through. This is very important when you’re doing a complete config sync! Ensuring that your config on disk exactly matches the config in the db is critical.
Doing this exposed several additional issues:
The libraries module was a part of Lightning 4.x but is not D9 compatible (and Lightning 5 doesn’t require it). I still had config attempting to use this module.
Several media entity fields were missing in my config dump. I have documented this issue and the solution on the Acquia Knowledge Base. I basically worked through this process (by installing and exporting config and re-installing) until all the needed config was in place.
The final step before pushing to the cloud was to add the MySQL Driver package to composer. Acquia has documented this as a requirement for running Drupal 9 on the platform.
Here’s the pull request for the final set of changes.
Troubleshooting Update Issues
A few additional problems cropped up while trying to actually update the codebase and perform database updates.
[error] The module libraries does not exist.
I should have seen this one coming (oops). Remember, you can’t uninstall a module from your Drupal site if you’ve already removed it from the codebase. The most expedient option for me here is to uninstall it from my staging environment and then re-deploy that database down to my lower environments to test again. Note: this requires Lightning Media 4.x or higher to safely uninstall Libraries without turning off other Lightning Media features.Lightning recommended modules.
Lightning has a few modules that they recommended adding (and I ended up doing a separate PR to add these in).
Where Should You Start?
The first thing that you have to do is run a tool like Upgrade Status or Drupal Check. These will give you some indication of how much of your custom (and contrib) code is ready for D9. Hopefully it’s as smooth sailing for you as it was for me here! Good luck! Let me know how it goes.