Upgrade from Drupal 8
Upgrade Pantheon Drupal 8 Sites to Drupal 9 With Integrated Composer
Contributors: Dustin LeBlanc, Greg Anderson, Tom Stovall.
Discuss in our Forum Discuss in SlackThis doc shows how to upgrade an existing Pantheon-hosted Drupal 8 site without Composer to a Drupal 9 site with Integrated Composer.
Drupal 9 sites on Pantheon have Composer built-in to manage site dependencies.
The goals of this upgrade are to:
remove dependencies that Composer will manage from the existing site's Git repository, and
have Composer manage those dependencies in the new site instead.
Note that since you are effectively migrating your site using these upgrade steps, the new site will not maintain your site's existing commit history.
Multidev Required
To maintain best practice and to avoid difficult, time-consuming repairs to the site, this doc is written for users with access to Pantheon's Multidev feature.
Pantheon support is not available to users who avoid the Multidev steps.
Will This Guide Work for Your Site?
You might encounter significant issues if the site does not match these requirements.
Before you continue, confirm that your site meets the following:
The site has the Pantheon drops-8 repo in its Upstream.
Use Terminus to Confirm the drops-8 Upstream
Run
terminus site:info $SITEto find the site'sFramework. The result should bedrupal8andUpstreamvalue should includegit://github.com/pantheon-systems/drops-8.git.This example shows a shortened version of the output:
terminus site:info $SITE ------------------ ------------------------------------------------------------------------------------- ID abdc3ea1-fe0b-1234-9c9f-3cxeAA123f88 Name anita-drupal Label AnitaDrupal Created 2019-12-02 18:28:14 Framework drupal8 ... Upstream 8a129104-9d37-4082-aaf8-e6f31154644e: git://github.com/pantheon-systems/drops-8.git ... ------------------ -------------------------------------------------------------------------------------- The site can not be set to use an empty Upstream.
The site does not use a nested docroot.
The process outlined in this guide will not work if the site repository has a
/webfolder at its root.See Serving Sites from the Web Subdirectory for information about nested docroots.
The site does not use Pantheon Search.
The site does not use another package and library manager like Ludwig.
Prepare the Local Environment
Review our documentation on Git, Composer, and Terminus, and have them installed and configured on your local computer. Pantheon requires Composer 2 at minimum.
Mac users can use Homebrew to install Git, Composer, and PHP 7.4, along with their required dependencies. Restart the shell or terminal environment after entering the following command:
brew install git composer php@7.4Windows users can install Composer and Git, and may need to install XAMPP or similar to satisfy some dependencies.
Install the Terminus Site Clone plugin.
This doc uses several commands that depend on the site name in the local command line environment.
To make this easier, set the temporary variable
$SITEin your terminal session to match the site name. Read the steps further in this doc to see which sites should be aliased (it may be more than one), then replaceanita-drupalin this example:export SITE=anita-drupal && echo "New alias set as $SITE"How to Use Terminus to Find the Site Name
Use
terminus site:listfor a list of sites you have access to:terminus site:list --------------------------- --------------------- ------------- ----------------------------------- -------------------- --------------------- ------------- ------------ Name ID Plan Framework Region Owner Created Memberships Is Frozen? --------------------------- --------------------- ------------- ------------------- ---------------- -------------------- --------------------- ------------- ------------ anita-drupal abdc80ce-286c-1234- Sandbox drupal8 Canada 3374708c-987e-1234 2020-12-15 19:40:42 d3ecc20c-395a false anita-wordpres abdc9954-fab2-1234- Sandbox wordpress United States c96ddb25-336a-1234 2020-09-02 07:18:51 d3ecc20c-395a falseThe site name is listed under
Name. In this example,anita-drupal.
Apply All Available Upstream Updates
Update the site to the latest Pantheon Drops 8 Upstream and apply all available updates.
Use Terminus to list all available updates:
terminus upstream:updates:list $SITE [warning] There are no available updates for this site.If any updates are available, apply them using the command line or via the Pantheon Dashboard:
terminus upstream:updates:apply $SITE.dev --updatedb
(Optional) Run upgrade_status to Confirm That the Site Is Ready to Be Upgraded
This section is optional, but recommended.
Before you attempt to upgrade to Drupal 9, confirm that the site is ready with the Upgrade Status Drupal module.
Converting a Drupal 8 site that is not managed by Composer (drops-8) to use Integrated Composer is time-consuming. Upgrade Status helps find potential issues before you invest the time to convert the site.
Test Drupal Upgrade Status in a Temporary Multidev
Drupal 8.8.0 and later are "Composer-ready," which means that it is possible to run composer require on a Drupal 8 site and have a site that still works.
Doing this would mean that you cannot upgrade via the Dashboard or Drush any longer, and a full Composer conversion would be required in order to apply future updates via Composer.
Since you are checking whether or not a site can be upgraded, install the Upgrade Status module in a temporary Multidev and view the results. Delete the environment when done:
Create a new Multidev:
terminus multidev:create $SITE.dev site-upstatCheck out the Multidev branch:
git checkout site-upstatAdd the Upgrade Status module:
composer require drupal/upgrade_statusAdd, commit, and push the code:
git add . && git commit -m "test site upgrade status" && git push origin site-upstatUse a web browser to visit the Drupal admin in the Multidev environment. Enable the Upgrade Status module and view the Upgrade Status page.
Delete Multidev when done:
terminus multidev:delete --delete-branch -- $SITE.site-upstat
Add the Pantheon Integrated Composer Upstream in a New Local Branch
This process involves significant changes to the codebase. We recommend you to do this work on a new branch, as it might take you some time to complete and rolling back changes can be complicated:
In your local terminal, change directories to the site project. For example, if you keep your projects in a folder called
projectsin the home directory:cd ~/projects/$SITE/Add the Pantheon Drupal Upstream as a new remote called
ic, fetch theicupstream, and checkout to a new local branch based on it calledcomposerify:git remote add ic git@github.com:pantheon-upstreams/drupal-project.git && git fetch ic && git checkout --no-track -b composerify ic/master Switched to a new branch 'composerify'If you prefer, you can replace
composerifywith another branch name. If you do, remember to adjust the other examples in this doc to match.Troubleshoot: Permission denied (publickey)
If you encounter a
Permission denied (publickey)error, check that your SSH keys are set up correctly.If you continue to encounter the error, use HTTPS to add the remote:
git remote add ic https://github.com/pantheon-upstreams/drupal-project.git && git fetch ic && git checkout --no-track -b composerify ic/master Switched to a new branch 'composerify'Copy any existing configuration from the default branch. If no files are copied through this step, that's ok:
git checkout master sites/default/config git mv sites/default/config/* config git rm -f sites/default/config/.htaccess git commit -m "Pull in configuration from default branch"Compare the old codebase's
pantheon.ymlto the newpantheon.upstream.yml:git diff master:pantheon.yml pantheon.upstream.ymlPress
qon your keyboard to exit the diff display.Copy the old
pantheon.ymlto preserve settings:git checkout master pantheon.yml git add pantheon.yml git commit -m 'Copy my pantheon.yml'Remove any values from
pantheon.ymlthat you prefer to keep listed inpantheon.upstream.yml. Then addbuild_step: truetopantheon.ymlif it is not already included.In the
pantheon.ymlfile, theapi_version: 1andbuild_step: truevalues are required.
Add in the Custom and Contrib Code Needed to Run Your Site
What makes your site code unique is your selection of contributed modules and themes, and any custom modules or themes your development team has created. These customizations need to be replicated in your new project structure.
Contributed Code
Modules and Themes
The goal of this process is to have Composer manage all the site's contrib modules, contrib themes, core upgrades, and libraries (we'll call this contributed code). The only things that should be migrated from the existing site are custom code, custom themes, and custom modules that are specific to the existing site.
The steps here ensure that any modules and themes from drupal.org are in the composer.json require list.
Once Composer is aware of all the contributed code, you'll be able to run composer upgrade from within the directory to have Composer upgrade all the contributed code automatically.
Begin by reviewing the existing site's code. Check for contributed modules in /modules, /modules/contrib, /sites/all/modules, and /sites/all/modules/contrib.
When reviewing the site, take stock of exactly what versions of modules and themes you depend on. One way to do this is to run the
pm:projectinfoDrush command from within a contributed modules folder (e.g./modules,/themes,/themes/contrib,/sites/all/themes,/sites/all/themes/contrib, etc.).This will list each module followed by the version of that module that is installed:
terminus drush $SITE.dev pm:projectinfo -- --fields=name,version --format=tableThe command
pm:projectinfoassumes Drush 8. If you encounter an issue with this command, verify and configure the Drush version before you continue.You can add these modules to your new codebase using Composer by running the following for each module in the
$SITEdirectory:composer require drupal/MODULE_NAME:^VERSIONWhere
MODULE_NAMEis the machine name of the module in question, andVERSIONis the version of that module the site is currently using. Composer may pull in a newer version than what you specify, depending upon what versions are available. You can read more about the caret (^) in the Composer documentation.Some modules use different version formats.
For older-style Drupal version strings:
Chaos Tools (ctools) 8.x-3.4Replace the
8.x-to convert this into^3.4Semantic Versioning version strings:
Devel (devel) 4.1.1Use the version directly, e.g.
^4.1.1
If you get the following error, the module listed in the error (or its dependencies) does not meet compatibility requirements:
[InvalidArgumentException] Could not find a version of package drupal/MODULE_NAME matching your minimum-stability (stable). Require it with an explicit version constraint allowing its desired stability.If there is no stable version you can switch to, you may need to adjust the
minimum-stabilitysetting ofcomposer.jsonto a more relaxed value, such asbeta,alpha, ordev(not recommended). You can read more aboutminimum-stabilityin the Composer documentation.If a dev version of a module fails because it requires a dev version of a dependency, allowlist the dev dependency in the same
composer requireas the module:composer require drupal/some-module:^1@dev org/some-dependency:^2@dev
Libraries
Libraries can be handled similarly to modules, but the specifics depend on how your library code was included in the source site. If you're using a library's API, you may have to do additional work to ensure that library functions properly.
Custom Code
Manually copy custom code from the existing site repository to the Composer-managed directory.
Modules and Themes
Modules:
git checkout master modules/custom
git mv modules/custom web/modules/
git commit -m "Copy custom modules"Themes:
git checkout master themes/custom
git mv themes/custom web/themes/
git commit -m "Copy custom themes"Follow suit with any other custom code you need to carry over.
settings.php
Your existing site may have customizations to settings.php or other configuration files. Review these carefully and extract relevant changes from these files to copy over. Always review any file paths referenced in the code, as these paths may change in the transition to Composer.
We don't recommend that you completely overwrite the settings.php file with the old one, as it contains customizations for moving the configuration directory you don't want to overwrite, as well as platform-specific customizations.
git status # Ensure working tree is clean
git show master:sites/default/settings.php > web/sites/default/original-settings.php
diff -Nup --ignore-all-space web/sites/default/settings.php web/sites/default/original-settings.php
# edit web/sites/default/settings.php and commit as needed
rm web/sites/default/original-settings.phpThe resulting settings.php should have no $databases array.
Deploy
You've now committed the code to the local branch. Deploy that branch directly to a new Multidev (called composerify in the steps below) and test the site in the browser.
Deploy to a Multidev
Push the changes to a Multidev called
composerifyto safely test the site without affecting the Dev environment:git push -u origin composerify && terminus env:create $SITE.dev composerifyMake a small change to
pantheon.yml:pantheon.ymldatabase: version: 10.4 # add a comment to trigger a change and buildCommit and push the change to trigger an Integrated Composer build on the Multidev:
git commit -am "trigger composer build" git push origin composerify
Since the commit history of the composerify Multidev has no commits in common with the master branch, you cannot view the Multidev commit history from the Dashboard or the Integrated Composer logs.
If the site is not working, try this Composer command on the local composerify branch:
composer --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist --ansi installIf Composer runs into an error or if any files have been changed (files that are not ignored by .gitignore), resolve those issues before you continue. See the Integrated Composer Troubleshooting section for more information about troubleshooting Integrated Composer.
Move composerify to the Main Dev Branch
Once you have confirmed that the site works in the Multidev, replace the master branch and its commit history with the composerify Multidev's commit history.
Retrieve the most recent commit hash from the local
composerifybranch:git log --format="%H" -n 1This will give you a commit hash like
fd3636f58f5b275b998bb1c9267bff8808353840.Reset the
masterbranch to match that commit then force push that to the Dev environment:git checkout master git reset --hard fd3636f58f5b275b998bb1c9267bff8808353840 git push --force origin master
Now the site's Dev environment has a Drupal 9 codebase.
Inspect Site Logs to Troubleshoot
If the site doesn't load properly, before you do too much work to investigate issues, clear the cache and try again.
Use Terminus to inspect the site's logs;
terminus drush $SITE.composerify -- wd-showSee our logs collection documentation for more information.
Change Upstreams
Set the site to use the Drupal 9 Upstream:
terminus site:upstream:set $site drupal9Enter yes when prompted:
Are you sure you want change the upstream for anita-drupal to Drupal 9? (yes/no) [no]:Note that the User in Charge, Site Owner, or Organization Administrator can change the Upstream.
Ongoing Core Updates
One-click core updates can be made through the Dashboard.
Navigate to Code in the Dev tab of the site's Dashboard. Click Check Now. If updates are available, click Apply Updates.
Troubleshooting
As packages pulled by Composer are updated (along with their dependencies), version compatibility issues can pop up. Sometimes you may need to manually alter the version constraints on a given package within the require or require-dev section of composer.json in order to update packages. See the updating dependencies section of Composer's documentation for more information.
As a first troubleshooting step, try running composer update to bring composer.lock up to date with the latest available packages (as constrained by the version requirements in composer.json).