Drupal Hackday – Writing DRUSH extentions

  • Bastian Feder

Today Patrick Jezek and I sat together to get a grip on one of the major problems we have when using Drupal in a continuous integration environment ‚Äď module updates involving major updates on configuration settings and database content.

Problem description

Imagine a usual Drupal installation already deployed on a live server. Imagine further that there is a demand to update at least one module of this installation without human interaction, any downtime, and data loss. The default work flow when updating configuration information would either demand human interaction and/or the complete deinstallation and reinstallation of the module which, when the hook_uninstall() correctly implemented, will cause data loss. A third option is to write a script to setup the new module after the installation process is done but this would challenge the deployment system to support some kind of a post_deployment process.

What was the goal?

The goal of this hackday was to propose a solution which enables a development team to continuously deploy and maintain a Drupal installation without being forced to uninstall modules to do a major update. Further more there should be some kind of a mechanism making it possible to update modules without human interaction when deploying the modifications.

Solution proposal

One of the most beneficial Drupal extensions is the Drupal shell (short: drush). It provides an extensive variety of commands to maintain Drupal (e.g. managing modules, users, and basic drupal configuration). The nice thing about drush it can be handled by any shell script just calling the specific commands and processing their outcome. Extending drush was therefore the most natural thing we could think about when we were confronted by this task.

So we came up with a drush extension providing a new Drupal hookhook_vm_update().

Custom hook_vm_update

Located in the *.install files the hook_vm_update() will be invoked by the drush extension. Further does the extension detect the existence of the custom hook and indicates this on the command line.

$drush vm-update  "myCustomModule, myOtherModule"

Updating myCustomModule ... no ¬Ľvm_update¬ę hook available¬†¬†¬†¬†¬†¬†¬† [warning]
Nothing to update for module ¬ĽmyOtherModule¬ę¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†[warning]

Custom scripts

In order to keep track of previous installed module versions we wrote two scripts. One does write down the currently installed version into a text file. The other one invokes drush to for modules which got changed since last deployment.

Further ideas

Add version information to hook_vm_update

Currently the update hook will always be called when the drush command is invoked and the previous installed version is smaller then the just installed one. Having only one hook implies that this hook knows which steps needed to upgrade from one version to another (including steps in between). What about a naming convention for hooks combined with version number and a logic to call them in chronological order, up to the target version (like Drupal core updates use schema update hooks).

Since the hook should not invoke actions potentially dangerous or harmful in terms of data loss et. al. this should not be much of a problem. But since we can already imagine situations where it is useful to either step through past updates or make the hook decide whether it an update is to be invoked or not one of the next steps for this drush extension will be to provide version information for an update.

Persist version information into the database

The versions.json file resists on the file system and could be potentially overwritten by a new installed package. An alternative could store the version information into the database (e.g. by using the Drupal configuration with variable_set() ?).

Final thoughts

We had some fun working on a solution for this given problem. We had the chance to look deeper into drush. We learned yet some php functionality we never used before. Unfortunately the weather was not nice and we could not fire up the grate for lunch.

Last but not least thanks L//p for this opportunity!


Qu’en pensez-vous?