Preparing for Drupal 9.1: Testing the Alpha Release

Hello Drupal folks! I’m back after a week of vacation and I wanted to start my first post back by a look ahead a few weeks to the Drupal 9.1 release.

I know, I know, Drupal 9.0 JUST CAME OUT (and it did). Blink and you’ll miss these releases. You can read more about the cycle here. But TLDR a new minor version of Drupal comes out roughly every 6 months. This also means that Drupal 8.8.x will lose security support when 9.1 releases.

Where are you today?

As with many of my other posts related to doing an update… Updating to Drupal 9.1 is going to be varying levels of difficult depending on where you are today on your platform.

  • Drupal <7: there is no upgrade path! You’ve got to rebuild. More on this here.

  • Drupal 8.x: there IS an upgrade path, but I would suggest upgrading to Drupal 9.x first

  • Drupal 9.x: there IS an upgrade path and it should largely be NBD.

Assuming the third scenario (you’re already on Drupal 9.x) then this is a pretty “minor” update. Does that guarantee it will go smoothly? NO! Does it mean it should be pretty safe? YES! I would, as always, recommend you do some testing.

Testing the Update

To test the update, there are a few things you’ll need to do. The most direct is to update your composer.json’s definition for drupal/core to allow ^9.1, then run composer update drupal/core --with-all-dependencies. It is out of the realm that this will fail.

If it fails, then use the composer why-not drupal/core ^9.1 command to understand what in your codebase is blocking you. It could be that you will need to update something else (e.g. Acquia Lightning recently made an update to allow folks to safely update to Drupal 9.1).

So, two scenarios:

  1. you have a package blocking your update and you have to update that package (or those packages) to update to Drupal 9.1.

  2. you have a package blocking your update and even the most current version of that package doesn’t work with or support Drupal 9.1.

In scenario 2, there are a couple of things to consider. First, you should check on Drupal.org for the project and make sure there is an issue open (or recently closed) that addresses the issue. If so, great! If not, I would open one ASAP. Second, you can “fake” your way to Drupal 9.1 as a test case.

Composer allows you to alias “something” as “something else.” For instance…

"drupal/core": "9.1-alpha1 as 9.0.7"

This will install the Alpha, but for dependency calculation it will treat drupal/core as being 9.0.7 instead of the alpha1. I very strongly do not recommend doing this for reals, but doing it as a test case is A’OK.

The next thing to do after actually updating the code should look familiar. Check for database updates. Check for configuration changes. With Drush, this can be done in 2 commands:

  1. drush updb -y

  2. drush cex -y

I personally recommend testing both the clean installation use case (which might be useful for your continuous integration processes) AND you site update use case (meaning you already have a database with your existing content, configuration, etc. locally where you can run the updates).

I also hope you have automated testing that you can execute against the site after you’ve performed the update.

From here, it’s largely a waiting game. Once Drupal 9.1 comes out in early December, assuming you’ve safely done the update during this early access phase (and haven’t found problems) then you can safely pull the trigger and do the update!

If you haven’t, everything I’m posting here is still going to be relevant once Drupal 9.1 comes out in December. The biggest reason to do some testing now? It’s always useful to find problems well in advance. I actually found a problem a couple of days before one of the Drupal 8.x minor releases in 2019 because of doing testing just like this. The core team rushed a fix and it was added to the stable release (after being found in the beta). The more sites that test the update, the more safe and secure the update is going to be!

Happy updating.


Related Content

Critical Tools for Development: Environment Detector

Thinking about the entire development ecosystem can be both challenging and overwhelming. It’s one of the many things that actually stop organizations and teams from following best practices and implementing a DevOps workflow. Why? It’s non-trivial to handle conditional elements in different environments.

Environmental Differences and similarities

The most common environments on web projects are:

  • local

  • continuous integration (CI / CD)

  • development (dev)

  • testing (qa / stage / test)

  • production

Now, obviously environment names are all made up and they don’t really matter anyway. So you could have 4 environments or you could have 10. The point is, there are some things between environments that should be identical and others that should be quite different.

The challenge: knowing the difference.

For instance! If I were to write a simple hello world function in PHP, it might look something like this.

<?php
print “Hello World!”;

Obviously, there is nothing special or conditional about this statement. It just prints Hello World 100% of the time. Now as we think about application development… simple print statements like this one aren’t often useful. We usually want to customize them to say hello to the specific user. We want to conditionalize them to not appear unless certain conditions are met. In other words, we want to make our code as dynamic and responsive as possible!

This is the same concept for environments. There are certain aspects of your application that can (and should) behave very differently based on the environment that they are running in. Here are a few examples:

  • caching configuration - caching should be turned WAY up in production and other cloud environments (for parity) but disabled or turned way DOWN in local / CI environments for easier development. similarly, you may want to keep javascript / css files un-minified locally (as you are developing on them) vs. in production (where performance matters)

  • security configuration - due to domain restriction, SSL certificates, etc. some of your application’s security settings may need to be relaxed locally or during CI

  • API keys - many integrations (e.g. e-commerce) mirror your web application’s multi-environment setup. you absolutely do not want your development web application communicating with your production e-commerce platform!

  • database / other settings - if you’re using a virtual solution locally (like Lando or Drupal VM) you may have an entirely different containerization strategy locally than you do in the cloud. You also likely have different database names and passwords (or you should) for local and CI environment than you do in the “real” hosting environments.

So the question becomes… just like with customizing that Hello World statement if we want to customize these scenarios… we need a way in code to differentiate between environments AND we need code that is smart enough to handle that differentiation.

Environment Detectors to the rescue

Most quality hosting organizations provide some sort of environment variables. These vary from organization so you’ll want to carefully review their documentation. But they do typically exist! Acquia’s documentation is online and shows how to do it on our platform.

TLDR: there is a super global AH_SITE_ENVIRONMENT variable that can be accessed via PHP code that spits out the environment that the code is currently running in.

Acquia also provides an open source / extendable Environment Detector. If you host with Acquia? Cool! Use ours. If you don’t, also cool! Use ours as an example for your own.

Basically, the environment detector uses the environment variables to figure out where we are. Like so:

  /**
   * Is AH prod.
   *
   * @param string|null $ah_env
   *   Environment machine name.
   *
   * @return bool
   *   TRUE if prod, FALSE otherwise.
   */
  public static function isAhProdEnv($ah_env = NULL) {
    if (is_null($ah_env)) {
      $ah_env = self::getAhEnv();
    }
    // ACE prod is 'prod'; ACSF can be '01live', '02live', ...
    return $ah_env == 'prod' || preg_match('/^\d*live$/', $ah_env);
  }

Then, you can use the method in your code. So…

<?php

use Acquia\DrupalEnvironmentDetector\AcquiaDrupalEnvironmentDetector;

public function test() {
  if (AcquiaDrupalEnvironmentDetector::isAhProdEnv()) {
    print "Hello on Prod!";
  }
  else {
    print "Hello World";
  }
}

In this case, our Hello World could be customized to say hello from prod (if we are on prod) and Hello World everywhere else.

You can take this model even farther (like BLT has) and use the Environment Detector to:

You can also use the Environment Detector in custom code!

Getting Started

So the biggest thing to know when you get started with Environment Detection is that while you CAN and SHOULD use it “a lot of places” in your Devops and Development pipelines… if you aren’t using it now it can be non-trivial to begin integrating it.

Why? Because it can change really significant portions of your workflow. Change settings files conditionally in all environments? That can (and likely) means that all of your environments are temporarily going to break while you iron out the details. I mean, that’s ok! Just know before you go in (and maybe don’t allocate a super junior person to do it).

So the take away here that I would suggest is that you plan your architecture and think through how you want to implement the conditional aspects of environments.

I would also recommend that you use Acquia’s Build and Launch Tools (BLT) as a model. We use environment detection everywhere in BLT and it really makes it quite powerful. Obviously, if you consistently host in “many” different hosting environments this gets more challenging. But just because it’s challenging doesn’t mean you shouldn’t do it!

My recommendation: start very small and very simple. Especially if you have to write your own environment detector. Make sure it works. Make sure it works up and down your stack. THEN start trying to write some simple code. THEN get more fancy and start integrating it into your devops and deployment workflows.

Related Content

An Absolute Beginner's Guide: Working with IDEs

I recently presented at Drupal GovCon on this topic! If you missed it, here’s a quick write up and the video (thanks to Drupal4Gov for sharing on YouTube.

What is an IDE

Let’s start simple!

There are essentially three types of tools that you might use to write code:

  1. Terminal

  2. Text Editor

  3. IDE

An IDE, if you aren’t familiar, is:
An integrated development environment (IDE) is a software application that provides comprehensive facilities to computer programmers for software development. An IDE normally consists of at least a source code editor, build automation tools and a debugger. - https://en.wikipedia.org/wiki/Integrated_development_environment

IDEs are particularly well suited for object oriented programming because of their ability to index the various methods and classes that you will be using in your code and giving you tons of useful hints, autocompletion, deprecation warnings, documentation, and more!

Warning: not all IDEs are well suited for PHP development. Here are a few to check out…

  • PHPStorm

  • Visual Studio

  • Netbeans

  • Aptana

  • Eclipse (w/ PHP)

Personally, I use PHPStorm.

Why Not Use a Text Editor (like Sublime Text)?

First of all, Sublime Text is awesome and you should totally use it! I’ve used it for a long time. BUT it’s not an IDE. It’s just a text editor.

Because it’s just a text editor, Sublime isn’t going to give you nearly as much useful information as you’re writing code. Worse, you can’t use it to debug and step through your code (which is critical in Drupal 8 and 9).

Here’s a hands on example of the same deprecated code written in Sublime vs. PHPStorm:

Sublime Text:

Screen Shot 2020-10-20 at 12.50.53 PM.png

PHPStorm:

Screen Shot 2020-10-20 at 12.50.58 PM.png

Notice how in the two screenshots the getStorage method is scratched out in PHPStorm (but not in Sublime Text)? This is because it’s a deprecated method. The IDE is going to tell you that immediately so as you write the code you can see it and go… “OH MAYBE I SHOULDN’T USE THIS METHOD.” Sublime is going to let you go blissfully along and not warn you that it’s a problem.

Using a Debugger

Another pretty significant part of using an IDE is the ability to tie in a Debugger (like XDebug).

The main use of a debugger is to run the target program under controlled conditions that permit the programmer to track its operations in progress and monitor changes in computer resources (most often memory areas used by the target program or the computer's operating system) that may indicate malfunctioning code. Typical debugging facilities include the ability to run or halt the target program at specific points, display the contents of memory, CPU registers or storage devices (such as disk drives), and modify memory or register contents in order to enter selected test data that might be a cause of faulty program execution. - https://en.wikipedia.org/wiki/Debugger

In a Drupal context, in the old days (D6/D7) a debugger wasn’t critical because basically all custom PHP as written in hooks (which essentially always execute, and have fairly simple data models). In D8/D9, NOT everything is a hook and aside from that, there’s a lot of ambiguous stuff going on outside the scope of the method you’re in (thanks to Symfony) that you may not know to try and print out with Devel. Enter Debugging.

Debugging lets you get a much more in depth look at everything that is going on at the moment of your breakpoint. Obviously your code has to execute to pause (which itself can be a challenge) but you aren’t limited to “just the thing you print.” It shows you all the things going on. It lets you step through the code. It lets you watch variables. It’s really powerful!

Demonstration

Have a look at my talk from GovCon. In it, I take time to walk through PHPStorm and show hands on how to Debug using PHPStorm, Lando, and XDebug.

Related Content