The secret to seamless deployments after production launch

Filed in: drush, bash, release scripts, drupal, php

Deploying a set refinements to a production site is tricky because you often need to deploy a bunch of configuration changes to Drupal that aren’t stored in version control. You can make these changes by hand (bad), write custom, long-winded hook_update_N()s (non-awesome), or throw a combination of Features and custom drush bash release scripts at the problem (awesome).

A custom drush release script is a bash script that combines the power of bash scripts (yay!) with everyone’s favorite command line interface for Drupal (tm), Drush. While you can track about 90% of the configuration changes you need to make in a typical release with the Features module, there is frequently a gap of configuration that Features is unable to capture. And there is no better place to run one-time cleanup routines then a drush release script.

Here is a release script from a recent deployment:


# Used for file paths
RELEASE_TAG=`basename $0`

# Show when we started
RELEASE_START=$(date +%s)

# Run current updates after code push.
drush updatedb -y

# New node object caching and views export module for report.
drush en object_cache views_data_export -y

# Revert features
drush features-revert MYPROJECT_my MYPROJECT_ask_and_share_v0_9 MYPROJECT_datamart MYPROJECT_home MYPROJECT_gallery MYPROJECT_offers MYPROJECT_site -y

# Enable Permissions API and Maintenance modules (only enable once).
drush en -y permissions_api MYPROJECT_maintenance

# Remove unused rules.
drush php-script 'remove-deprecated-rules.php' --script-path="releases/${RELEASE_TAG}" --user=admin

# Menu item cleanup
drush php-script 'menu-cleanup.php' --script-path="releases/${RELEASE_TAG}" --user=admin

# Remove showroom profiles for non-showroom people.
echo "Removing showroom profiles for non-showroom users."
drush remove-unneeded-showroom-profiles --user=admin
echo "Done removing showroom profiles for non-showroom users."

# Favoriting Ask module.
drush php-script 'favorite-questions-answers.php' --script-path="releases/${RELEASE_TAG}" --user=admin

# Offers permissions changes
drush php-script 'offers.php' --script-path="releases/${RELEASE_TAG}" --user=admin

# Update links to registration to support nojs failback.
drush php-script 'login-registration-nojs.php' --script-path="releases/${RELEASE_TAG}" --user=admin

# Refine some permissions for reports.
drush php-script 'adjust-all-users-report-permissions.php' --script-path="releases/${RELEASE_TAG}" --user=admin

# Refine some permissions for reports.
drush php-script 'adjust-all-users-report-permissions.php' --script-path="releases/${RELEASE_TAG}" --user=admin

# Remove showroom profiles for non-showroom people.
echo "Resave all professional profiles created before 6/14/2012 to trigger export to Salesforce."
drush vset sf_queue_enabled 0 -y
drush salesforce-professional-profile-cleanup --user=admin
drush vset sf_queue_enabled 1 -y
echo "Done with professional profile Salesforce cleanup."

# Disable Permissions API and Maintenance modules since it's only needed for releases.
drush dis -y permissions_api MYPROJECT_maintenance

# Time we ended
RELEASE_END=$(date +%s)
echo "Deployment script completed! It took $RELEASE_DURATION minutes."

The first part of the script uses bash variables to store the start time of the script so that when the release scripts ends we get an execution time. It is helpful to know the script execution time when we are practicing the script on the dev server so we can schedule our production launch.

The script enables the Permissions API just for the release script. This is a useful Drupal 6 module that provides helpful functions to easily make Drupal permissions changes. The drush php-script command is a handy way to run a custom PHP script for complex but one-time changes while still having access to the full Drupal API.

You may balk at creating a release script for a simple module status change, but once you get into the habit of using them all sorts of changes will become easy to automate, test, and deploy seamlessly.