Best way of Managing Drupal Workflow

Ankit Jain
Ankit Jain DevOps Engineer @Razorpay | CommunityBridge Mentee @Keptn | @Drupal GSoC Alum | #GitHubCampusExpert Alum | GCI & GSoC'19 Mentor @Drupal | Speaker | Writer

Best way of Managing Drupal Workflow

One of the struggles that developers face when moving to Drupal 8 is the lack of best practices in deploying Drupal sites. The Challenges in deployment- Dependency Management, Drupal Contrib Modules/Themes, Configuration Management and of course Code Base. Drupal 7 has no such problems. Ahhh, Drupal 8 comes with lots of stuff to manage. One of the biggest change in Drupal 8 is the adoption of Composer. Good things come at a price.

We will use one codebase for one Drupal site and use git for version control and deployment.

Composer

Composer is a dependency manager for PHP (like npm for Node, pip for Python). Drupal core uses Composer to manage core dependencies like Symfony components and Guzzle. Composer allows us to systematically manage a list of dependencies and their subsidiary dependencies. Composer install these dependencies via a manifest file called as composer.json.

Composer workflow

This composer.json file contains the dependencies that the project requires which is installed by running -

composer install

for the first time. It locates, downloads, validates and loads the packages. It also ensures that exactly the right versions for each package are used and maintains the log file called composer.lock.

Note: Always Commit your composer.lock file because it contains the exact version of the dependencies that you have defined in the project.

If you want to update any specific package, it’s a good practice to run this command -

composer update package/package-name

You should never run composer update because composer will try to update every single dependency which can cause problems to your site.

Drupal Composer

drupal-composer/drupal-project is the life-saver project for managing your site dependencies with Composer.

To install this project template, Run this command -

composer create-project drupal-composer/drupal-project:8.x-dev drupal8 --stability dev --no-interaction

It will automatically install a Drupal site with all the dependencies and also install Drupal console and Drush locally.

Composer is one of the fastest ways to install dependencies as it caches the dependencies and next time loads data from the cache.

Directory Structure:

Directory structure

It is different from the Drupal directory structure. You can resemble web directory with the public directory which contains Drupal files. All third party dependencies are outside the web folder.

You can install any Drupal Modules, themes, and profiles through composer which will be downloaded in the contrib folder inside the modules, themes, profiles respectively. In this way, composer.lock file will have a record of all the Drupal contrib modules along with the third party dependencies.

To download any modules, themes using composer-

composer require drupal/mediumish_blog

# For installing theme, we will use drupal console

drupal theme:install mediumish_blog

Gitignore:

As all the dependencies and Drupal contrib modules, themes are managed by composer so we will not push these content to git.

# Ignore directories generated by Composer  
/drush/contrib  
/vendor/  
/web/core/  
/web/modules/contrib/  
/web/themes/contrib/  
/web/profiles/contrib/  
/web/libraries/

# Ignore sensitive information  
/web/sites/*/settings.php  
/web/sites/*/settings.local.ph

Configuration Management

Deployment and configuration management are common actions of a project life cycle. We have installed various modules and configure our local site but our production site has no such configuration.

In Drupal 7, we have features module which is used to sync configuration. But Drupal 8 has an inbuilt solution for managing configurations which allows you to export complete website configurations and store them in YAML files. Exported files can be imported to another website to get the same result. Drupal’s configuration system helps to solve the config files synchronization problem in two ways: a unified way to store configuration and a process to import/export changes between instances of the same site.

How to synchronize config files

Open /web/sites/default/settings.php and set $config_directories[‘sync’]

$config_directories['sync'] = '../config/sync';

It’s good practice to store config files outside of the web directory to avoid making them accessible from the Internet.

Now Use Drupal console to export the configuration -

drupal config:export

# import on prod server

drupal config:import

Note: It is required that both the production and local Drupal site should have same UUIDs. More info

Note: Drupal configuration management has a bug i.e custom blocks’ data neither be imported nor be exported.Issue Link

Git

We will use git to add, commit and push the local site’s data with all the configuration which will be pulled from the prod server/site. Let’s see the flow-

# Local

git add .

git commit -m"Add commit message"

git push origin HEAD

# Server

git pull otigin HEAD

composer install                         # to install any new dependencies, drupal contrib modules, themes

drupal config:import                   # to import the configuration

drupal cache:rebuild all              # rebuild the cache

Update Modules, themes, and profiles

composer update drupal/mediumish_blog

drupal update:execute mediumish_blog

drupal update:execute all

Update Drupal Core

Generally, we face problems in updating Drupal core, composer has a simple way to manage this too-

composer update drupal/core --with-dependencies

It will update the  Drupal core and all its associated dependencies.

Managing Environment Configuration

The best part that I was looking for as a developer in Drupal is managing different environment configuration. This can be done by using vlucas/phpdotenv module which also comes with drupal composer template.

Anything that is likely to change between deployment environments – such as database credentials or credentials for 3rd party services – should be extracted from the code into environment variables Basically, a .env file is an easy way to load custom configuration variables that your application needs without having to modify any other files.

Rename .env.example to .env file and add all the credentials as a key-value pair in .env file.

load.environment.php file in the root will load this .env file and make it available for you.

How to use .env file

Open /web/sites/default/setting.php and add this set of code-

$databases['default']['default'] = [  
  'database' => getenv('MYSQL_DATABASE'),  
  'driver' => 'mysql',  
  'host' => getenv('MYSQL_HOSTNAME'),  
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',  
  'password' => getenv('MYSQL_PASSWORD'),  
  'port' => getenv('MYSQL_PORT'),  
  'prefix' => '',  
  'username' => getenv('MYSQL_USER'),  
];

Open .env file and sets credentials-

MYSQL_DATABASE='db_name'  
MYSQL_HOSTNAME='localhost'  
MYSQL_PASSWORD='secret'  
MYSQL_PORT='3306'  
MYSQL_USER='root'

Now as all our credentials are stored in .env file, we can push our settings.php to the server and manage its configuration through .env file.

We generally enable twig debugging while development and disable on production, This can also be done easily and smoothly through a .env file.

Add new key value pair in .env file-

APP_ENV='local'

Now copy web/sites/example.settings.local.php to web/sites/default/settings.local.php and add this code in web/sites/development.services.yml under parameters 

twig.config:  
    debug: true  
    auto_reload: true  
    cache: false

Now open web/sites/default/settings.php and add this code-

$env = getenv('APP_ENV');

$base_path = $app_root . '/' . $site_path;  
$settingsFile = $base_path . '/settings.' . $env . '.php';

if (file_exists($settingsFile)) {  
  include $settingsFile;  
}

So, in this way, if you set your APP_ENV=’local’, Twig debug will be enabled and on production, you can disable by setting APP_ENV=’prod’. You can also configure different configuration for different environments.

Conclusion

Drupal 8 offers a built-in solution for exporting and importing site configurations which is way better than what you can do in D7. Dependencies and contrib modules/themes are managed by the composer itself. It’s not yet perfect, there is no standard approach, but the workflow described above is a simple and efficient solution. You can define your own workflow based on your need.

For reference, I have pushed code to repo- Here its link - drupal-best-practices

I hope you have found this article useful. I would love to hear your feedback :)

Categories:
comments powered by Disqus