Getting Ready for Drupal 9

With the imminent release of Drupal 9, it’s a great time to give serious consideration to your update strategy. There is much to look forward to this time around, whether you are a Drupal veteran or new to the family.

The good news is that this will be a much easier process than the most recent major version updates, so if you’ve been using Drupal a while, this should come as a relief. However, It is important to note that while it is not a painful migration process, it’s also more than just a few clicks away. Drupal 9 changes a few assumptions many of us are used to as Drupal site builders, but preparing now will take you far.

Drupal 9 is basically just Drupal 8 with updated dependencies and deprecated code removed, which makes for a fairly straightforward update process, but the devil is in the details.

Getting Started

First, there are some prerequisites you’ll want to keep in mind.

  • Your current site must be running on at least drupal 8.8 to upgrade. This means a fully up to date install.
  • You must use PHP 7.3 or higher. Drupal 9 requires php 7.3
  • In some cases, Drupal 9 needs a newer version of whatever database you're on now, so you may need to upgrade your database. See Environment requirements of Drupal 9 for details.

As you start looking for Drupal 9 compatible modules, you may find yourself a little perplexed as you browse modules on Drupal.org and notice that none seem to have a Drupal 9 compatible release.

They do, but it's a bit hidden.

(Note that you do not have to look up every module you are using on Drupal.org. We'll get to a handy reporting and scanning tool shortly, but it's important to note these changes to how modules will work with Drupal 9.)

You will find Drupal 9 compatibility in the small text under "Project Information."

The concept of modules being tied to a major release is old Drupal, and we're living in the future now. Modules can work with more than one major version of Drupal! So, you won't see a big highlighted box for a Drupal 9 release on module pages.

In the near future, you'll start seeing more module releases using semantic versioning on Drupal.org. A few are already there. The major version of core will no longer be part of the module's version number. You can see this in action on the semver_example module and on the Lightning project page.

Lightning version 5.x.x uses semantic versioning.

Evaluate Your Site

Once you have met the requirements to run Drupal 9, the next step is to evaluate your site. The first course of action is to update all modules to the latest version. There's a good chance they're already D9 compatible. Then, check for deprecations in your themes, contrib modules, and custom modules.

Deprecations are old Drupal 8 functions which have been removed from Drupal 9, and you’ll need to find them to replace them with up-to-date code. To do this, I recommend starting with the Upgrade Status module. This module will scan your codebase for deprecations and provide you with a handy report. Install it in your development environment, and note that it must be installed with composer.

$ composer install --dev
$ composer require 'drupal/upgrade_status:^2.0'

Once you've enabled Upgrade Status and navigate to its report at admin/reports/upgrade-status, you'll see some important information about your environment that will indicate your ability to run Drupal 9.

The top of the Upgrade Status report.

 

Upgrade Status will scan your custom modules and themes and all your contrib projects and give you this lovely output.

 

One warning per custom project is great news, especially when the fix is as easy as adding core_version_requirement to the project's info file. Further down the report, you'll see the a list of your contrib modules. Even though we've updated our modules, we may still see that they are not all D9 compatible, and Upgrade Status will show those errors.

You may see some text under the module that indicates its status. Module maintainers may optionally provide this very helpful information. Sometimes it might be as simple as "This module is ready for Drupal 9".

If you see something like "Version 1.x-dev is ready for Drupal 9", "dev" means the latest version isn't D9 compatible. They may also indicate which future release will be compatible, and even include a link to an issue on drupal.org with further information about the module's status, and we’ll see an example of that when we dive deeper into evaluating contributed modules.

But wait, you are probably wondering how Admin Toolbar is compatible when it shows 12 warnings!

You'll errors like this sometimes when using Upgrade Status. There are two main reasons why you'd see this:

  1. The problem might be in a test class, like in this example. Tests can't always be scanned, but you can safely ignore them because you won't run test code in production.
  2. The module might have a third party dependency that you don't have installed. That's totally okay -- those dependencies may not even be Drupal modules, so they don't matter to Upgrade Status.

Generally, you can trust the maintainers that the module is indeed "ready for Drupal 9."

You'll get lucky with some modules, and they'll have errors that are pretty easy to fix. Some may be a little more challenging or involve some refactoring, but many will have  a handy link to the API documentation, as below.

If you click one of the nice error messages, you get to the api documentation page for the deprecated function, which may also contain a helpful link to the change record with thorough examples to help you change your code the best way: 

Change records document changes to Drupal core. They will describe the change and the impact of the change. It should include any interface changes, function or hook changes, and it's helpful for understanding how to address these changes with your own code.

Note that not all errors will have a link to further documentation, but that's okay because a little API searching will do the trick.

The deprecation notice.

If you look at the top ten most popular Drupal 8 compatible modules, all are compatible in their dev branch, and 9 of the 10 have full compatible releases. This is incredible progress.

But, as we get further down the popularity list, we're likely to find some incompatible modules.

As you continue your discovery process, it's a great time to evaluate where your pain points will be. Get involved and try to help modules reach their Drupal 9 compatibility goals, or if a module seems stalled or the last commit was 3 years ago, have a backup plan to include a patch or re-evaluate the need for the module at all.

Acquia's Drupal 9 Deprecation Status page is also a great source of information. This shows the status of all contrib projects, and gives you an idea of where the entire Drupal ecosystem stands with regard to Drupal 9 readiness.

Fix Your Errors

Once you've equipped yourself with the prerequisite information, it's time to move on to fixing any errors you have found. I'd start with the easy ones and work your way up.

Now is a great time to introduce the Upgrade Rector module. Upgrade Rector is a UI that uses drupal-rector to help you automatically generate patches. If you install the Upgrade Rector module, since it integrates nicely with Upgrade Status, you'll be able to generate an automatic patch for some modules as you scan them. Rector is limited at this point though, so you may end up with results similar to the following screenshot, but even a couple patches could get you a little ahead of the game and save a bit of time. And, like everything in the Drupal world, development is moving fast. By the time you install Upgrade Rector and scan your site, it's likely you'll be able to automate several of your patches.

Drupal Rector output visible on the Upgrade Status report (admin/reports/upgrade-status).
Click the "patch available" link to see the generated patch.
Drupal Rector displays the patch in a modal window.

Below, you see the changed lines highlighted, and your custom code is ready to go. There is a caveat, however. If you've found a contrib module that has not yet been patched in the issue queue and you'd like to add one, I can tell you from experience that if you post a patch like this for a contrib module, an experienced maintainer is likely to ask you to make changes to it. In this case, someone could point out that these replacements use the global Drupal class, which is not always the ideal approach in contrib modules, but it's safe to use in your custom projects.

This example used a contrib project, but it's useful to remember that with contrib projects, you aren't alone, so save yourself some work and check the module issue queues to see if the deprecations have already been patched, or even committed. Some maintainers will also have an explicit link to the main Drupal 9 issue in their queue, and this will be visible on the Upgrade Status Report, on the module page, and on the Acquia Deprecation Status tool.

If they haven't, then you can make the changes yourself and submit a patch to the issue queue and do your good deed for the day. With any luck, you'll just have to focus on your custom code.

In short:

  1. Avoid duplicating work.
  2. Check the issue queue first.
  3. Then submit a patch.

Once you have gone through your list and fixed and rescanned until it's all green, or you have gotten as far as you can, next make sure all your automated tests are passing. There is a pretty good chance the Update Status results screen will never be completely green, and that's okay because static analysis is not perfect, and neither are automated tests.

Once you feel like you've exhausted all your options with static analysis, you can try actually testing with Drupal 9 core.

You can test your current status by requiring Drupal 9 like so:

$ composer require 'drupal/core:~9.0'

Now, you may have to do some composer wrestling to get this going, but you'll get there!

You may see errors like this:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Conclusion: remove drupal/cookieconsent 1.4.0
    - Conclusion: don't install drupal/cookieconsent 1.4.0
    - Conclusion: don't install drupal/core 9.0.0-beta2
    - Conclusion: don't install drupal/core 9.0.0-beta1
    - Conclusion: don't install drupal/core 9.0.0-alpha2
    - Conclusion: don't install drupal/core 9.0.0-alpha1
    - Conclusion: don't install drupal/core 9.1.x-dev
    - Installation request for drupal/cookieconsent ^1.4 -> satisfiable by drupal/cookieconsent[1.x-dev, 1.4.0].
    - Conclusion: remove drupal/core 9.0.x-dev
    - drupal/cookieconsent 1.x-dev requires drupal/core ~8.0 -> satisfiable by drupal/core[8.0.x-dev, 8.1.x-dev, 8.2.x-dev, 8.3.x-dev, 8.4.x-dev, 8.5.x-dev, 8.7.x-dev, 8.8.x-dev, 8.9.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.8.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.9.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.0.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.1.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.2.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.3.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.4.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.5.x-dev].
    - Can only install one of: drupal/core[9.0.x-dev, 8.7.x-dev].
    - Installation request for drupal/core ~9.0 -> satisfiable by drupal/core[9.0.0-alpha1, 9.0.0-alpha2, 9.0.0-beta1, 9.0.0-beta2, 9.0.x-dev, 9.1.x-dev].

You may see errors like this. Any modules that don't declare compatibility with Drupal 9 will not install. They need to do that with core_version_requirement in their info file. As a workaround, you could temporarily remove them until they do, and test the rest, or you could bring them in without using composer, and check them that way. That will allow you to identify any missing core_version_requirement keys in sub modules, or other issues that may have slipped through.

Once you have a Drupal 9 codebase, you are not necessarily home free, as static code analysis doesn't catch everything. At this point, you may face errors when trying to run your site. In fact, it's likely. A good way to check for errors is to run drush cr once you've upgraded. In my experience, references to deprecated services may have slipped through, and they'll pop up once you've switched to Drupal 9.

At this point, you may face errors when trying to run your site. In fact, it's likely. A good way to check for errors is to run drush cr once you've upgraded. In my experience, references to deprecated services may have slipped through, and they'll pop up once you've switched to Drupal 9.

For example:

You have requested a non-existent service "entity.manager".
 
 
You have requested a non-existent service "path.alias_manager".

Next Steps

If errors are coming from a contrib module, your first stop should be the module's issue queue. Report the error if it has not already been reported. Active maintainers and other contributors are likely to respond to the error quickly, especially in popular modules. If you need to explore further, run the module's tests.

If the error is in your custom code, as in contrib modules, some of these changes will be easier, like simply replacing the old service with the new, and sometimes you'll have to rethink your code a little bit. You may find some guidance in the change records: https://drupal.org/list-changes

Once you have your fixes in place, you should again be ready to make sure any automated tests are passing with Drupal 9. Then, give things a manual test for good measure.

But what if it hasn't gone so smoothly? What other challenges might we face?

The differences between getting custom projects ready for D9, versus contrib projects, are pretty clear. You are in charge of your custom code, and you can define your own timeline for a Drupal 9 compatible release. With contrib projects, the maintainers are the gatekeepers, and you may find yourself temporarily blocked while waiting for patches to be committed. The upside is that once ready, it's an easy update away!

Almost all Drupalers are kind and generous people, as you know, but some are a little busy. Ultimately, it's going to take the efforts of many to get the contrib modules you need ready. And in the meantime, you probably have enough custom code to tackle.

Making Sense of Contrib

As someone who used to spend a lot more time using Drupal than looking at issue queues, I can understand how the process of evaluating a module's readiness, or progress toward readiness can be less straightforward. But I'll show you some key places where I go digging for this information.

Search API is a great example of a helpful status message. You'll find the status when using Upgrade Status and at Acquia's deprecation status page.

You'll see that this module has included a link to an issue which will tell you what you need to know about the status of its Drupal 9 compatibility. This is very convenient.

But now, let's look at reCAPTCHA. You'll notice there is no indication of Drupal 9 compatibility on the module page.

Next, we can check it on Acquia's Deprecation Status page.

This suggests reCAPTCHA is ready to go, but let's try and verify. Note that no Drupal 9 plan is provided to indicate the status of its compatibility.

It's always a good idea to check the issue queue for Drupal 9 progress when it's not linked from the status message. We got lucky, and this post is right near the top. 

There are some good signs in this issue. There's a patch and it was committed.

There are also some less good signs. What are these D9 composer require failures? We don't really know the status based on this. And remember, just because this test isn't running does not necessarily mean this test won't work for you. The only way to know for sure will be when you try it.

So, let's go back to the module page. 

The modules automated tests are another important source of truth.

This page looks less promising. The module's tests currently fail with Drupal 9. If we click the failure notice, we'll see the test failures in detail. 

Here we can see the problem. reCAPTCHA can't be Drupal 9 ready until its depedency, CAPTCHA is. So now's a good time to head over to the CAPTCHA module's page and check its status.

Maybe you could help them move it along!

In this post, I've laid out the major steps toward getting your site ready for Drupal 9.

  1. Update core and all your modules, and satisfy Drupal 9 minimum requirements.
  2. Remove all deprecations in your custom code, and make sure all your contrib modules are ready for Drupal 9.
  3. Upgrade to Drupal 9 and test manually.

In summary, if you start this process now, you'll be a little ahead of the game. If your projects are ready, it's a pretty seamless update, and if not, now is the time to get them there. Keeping your current Drupal 8 site up to date will get you far.

Resources

Drupal 9 resources

 

Drupal 9 Overview Page

Upgrade Status Module

Upgrade Rector Module

Acquia's Drupal 9 Deprecation Status Tool

Powered by Drupal Lightning