Moving the code base between major versions

by Gisle Hannemyr

This chapter provides tells how to upgrade the code base of a website built with Drupal from one major version of Drupal to another.

Table of contents

Drupal project discussed in this chapter: Upgrade Status.

Introduction

Going from a major version of Drupal to another (e.g. from Drupal 9 to Drupal 10) is called an “upgrade”.

This chapter is about the specialized tools and procedures that exists for doing an upgrade of the code base. An alternative strategy is to rebuild the target code base from scratch (i.e. not upgrading the code base), and then migrate the legacy content data into the new code base.

The steps for migrating a site are:

  1. Create an inventory of extensions and content.
  2. Set up a clean install of the new major version.
  3. Install new versions all the extensions you still need.
  4. Migrate the contents (see Migrating content data).

One of the major obstacles to an succesful upgrade is that some of the extensions you need is not be available or usable for the new version, or that they exist, but no migration path for legacy data exists. This chapter discusses how to get around that obstacle.

Some functionality may also shift around between versions. See this forum post on Drupal.org about modules moved between core and contrib.

Upgrading a website

The first step is to create a staging website with the latest stable version of the Drupal version you want to use.

Upgrading a website from Drupal 7 to Drupal 10

Upgrading from Drupal version 7 of Drupal to Drupal 10 (Drupal 8 and 9 is deprecated) is hard. Unless your Drupal site is very small, and you haven't extended Drupal in any way, it is a major undertaking. Below are links to some documentation about this process:

Upgrading a website from Drupal 9 to Drupal 10

To be able to upgrade, first make sure that these conditions are satisfied.

Make sure your site already is maintained with Composer and fully composerized using the template drupal/core-recommended, and that it also is updated to the latest minor version of the Drupal 9 branch (currently 9.5.11). You do this with this command:

$ composer depends drupal/core-recommended
drupal/recommended-project - requires drupal/core-recommended (^9.5.11) 

If you get an error, you need to corrct that before proceeeding.

Also make sure all extensions are updated to their latest stable version, and that the version that is installed is compatible with Drupal 10. Those that are not compatible with need to be dealt with on a individual basis (e.g. patched, using dev-versions, uninstalled, etc.).

Before you start you should make an inventory of all contributed extensions and their configuration. You may need to remove them in order to able to update using composer. With an inventory, you can reinstall after updating.

To check if your site is ready, use the Upgrade Status module.

tipThe project page suggests that you need to install Drupal's developer dependencies. In my experience, it works better without. You don't need to install these.

If installed on a Drupal 8 site, it will check readyness for Drupal 9. If installed on a Drupal 9 site, it will check readyness for Drupal 10. You must install it using composer, and then enable it:

$ composer require  'drupal/upgrade_status:^4.0'
$ drush en upgrade_status

To use it from the CLI, it requires Drush ver. 11. If the site is not running that version, you can make it a requirement with this composer command:

$ composer require 'drush/drush:^11.0'

However, I recommend using it from the GUI. To do so, navigate to Reports » Update status and select the project to scan. It will produce a status report. If a website is ready to be upgraded, it will show "100 %" in the circle on the right edge of the page:

upgradestatus.png
When a site is ready to be upgraded, it is indicated by 100 %.

If the reports complains about "Deprecated or obsolete core extensions installed", uninstall these before upgrading. To uninstall hidden deprecated themes, edit the theme's .info.yml and set the "hidden" key false.

Before proceeding with the upgrade uninstall and remove Upgrade Status:

$ drush pmu upgrade_status
$ composer remove  drupal/upgrade_status

Provided the Drupal 9 website is maintained using Composer using the template drupal/core-recommended, and Upgrade Status reports it being 100 % ready, you shall now be able to upgrade it to Drupal 10 with the following steps:

First change directory to the siteroot (the directory where composer.json lives).

Temporarily add write access to protected files and directories:

$ chmod 777 web/sites/default
$ chmod 666 web/sites/default/*settings.php
$ chmod 666 web/sites/default/*services.yml

Next, require the Drupal 10 version of these three packackages with dependencies. We use --no-update to avoid a chicken-and-egg problem with mutual dependencies.

$ composer require 'drupal/core-recommended:^10' --update-with-dependencies --no-update
composer.json has been updated
$ composer require 'drupal/core-composer-scaffold:^10' --update-with-dependencies --no-update
./composer.json has been updated
$ composer require 'drupal/core-project-message:^10' --update-with-dependencies --no-update
./composer.json has been updated

It is not recommended to have the package drupal/core-dev installed on a production site. If you have, remove it, or require that as well.

Update to the code base:

$ composer update

Update the database:

$ drush updb

You may need to add the isolation_level key to the project's settings.php:

$databases['default']['default'] = array (
  …
  'isolation_level' => 'READ COMMITTED',
  …
)

If the status report complains about the "SameSite cookie attribute" not being set, set it in the project's services.yml. If services.yml doesn't exist already, copy default.services.yml to services.yml. For background, see this CR: Drupal now defaults to "Lax" for the SameSite session cookie attribute.

Restore read-only access to relevant files and directories:

$ chmod 755 web/sites/default
$ chmod 644 web/sites/default/*settings.php
$ chmod 644 web/sites/default/*services.yml

Check version:

$ drush core-status --field=drupal-version
10.1.7

This procedure has so far worked OK for me for upgrading a dozen Drupal 9 webites to Drupal 10.

Sources on DO: Upgrading from Drupal 9 to Drupal 10, Overview, Upgrading a Composer-based-site.

CKEditor

After upgrading, "CKEditor" need to be restored as the Text editor for the formats "Full HTML" and "Basic HTML", and the Active toolbar restored. The illustration below show how it should be by default:

ckeditor16.png
Default buttons to appear on the toolbar.

All headings except H1 should be enabled.

Troubleshooting

If there is a dependency on a earlier version of core, you may get this:

drupal/core-recommended 9.2.7 requires drupal/core 9.2.7 -> found drupal/core[9.2.7] but it \
  conflicts with your root composer.json require (^8.8.0).

Fix it be whitelisting a compatible version:

$ composer require 'drupal/core:^9' --update-with-dependencies --no-update
composer.json has been updated

If you have extensions installed, you may get this, even if all of them are upgraded to version that is supposed to be compatible:

$ composer update
Your requirements could not be resolved to an installable set of packages.
  Problem 1
  - …

You may uninstall and remove the problematic extension, but unmet dependencies will probably prevent you from doing so. If this hits you, you may go back to Drupal 8:

$ composer require 'drupal/core-recommended:^8' --update-with-dependencies --no-update
composer.json has been updated
$ composer require 'drupal/core-composer-scaffold:^8' --update-with-dependencies --no-update
./composer.json has been updated
$ composer require 'drupal/core-project-message:^8' --update-with-dependencies --no-update
./composer.json has been updated

You should now be able to uninstall and remove.

If any of the packages does not have a release explicitly declared as D9-compatible, you will likely run into a dependency error when trying to update your codebase. There may already be a patch in the issue queue that you can use if you use to upgrade the project to be Drupal 9 compatible. Please refer to this blog post by Damien McKenna for more details on how to handle this situation: How to Fix the Catch-22 Problem of Drupal 9 Fixes in Composer.

For trouble with the update data base step, see this DO Forum post.

Upgrading third party extensions

For extensions (i.e. contributed projects) you do not maintain yourself, the following options exist (sorted from the best to the worst):

  1. Use core (provided the upgraded core provide suitable functionality).
  2. Install an upgraded project.
  3. Find a replacement project.
  4. Become a co-maintainer and upgrade the project yourself.
  5. Fork and upgrade the project yourself.

In some cases, a migration path exists, in others you must be prepared to migrate data yourself, as descriped in the chapter Migrating content data.

Upgrading first party extensions

For extensions maintained by yourself, here are some notes about upgrading.

From Drupal 7 to 10

This topic has its own page.

From Drupal 9 to 10

Start out by reading the following:

A tool for creating a Drupal 9 Deprecated Code Report for Contrib Modules was initially available, but it has evolved into the Project Update Bot that posts reports with patches to the project issue queue.

tipThere is not a separate Drupal 9 branch for extensions. You may continue to make releases within the 8.x-* branch, or (better!) switch to semantic versioning. Composer metadata is now used to sort out version dependencies instead of branches.

In addition, the Upgrade Status (introduced above) can be used to scan the code base.

To use it, navigate to Reports » Update status and select the project or projects to scan. It will produce a status report about the code, along with suggestions.

Final word

You may also want to read this DO Forum post for more information.


Last update: 2023-11-01 [gh].