Deployment with Capistrano Part 2: Drush integration, Multistage, and Multisite

In my last post, a basic intro to to running cap deploy was presented. Now, let's look at some more advanced scenarios. (See Part 1 for the actual task definitions described here).

  • Multistage: Deploy to different environments (such as testing vs. production).
  • Drush Integration: Use the power of Drush to extend Cap's reach into Drupal's internals.
  • Multisite: Run many sites from a single code base.

Multistage

"Stages" are different server instances of your code. You may have different servers for development, content entry, and production. With the Multistage extension, you only need one small config file for each stage.

First, make sure the Multistage extension is installed:

gem install capistrano-ext

It also needs to be included in your Capfile with

require 'capistrano/ext/multistage'

Then, declare the stages in config/deploy.rb. The stages can use any names you wish:

set :default_stage, "development"
set :stages, %w(production testing development)

For each stage you've defined, copy the config/deploy/development.rb file from Part 1 to config/deploy/[STAGE].rb.

Here, I've set the default to "development", which means that cap deploy will target that stage. For other stages, just add the stage name like this: cap production deploy. The same syntax works for other tasks too, such as cap production deploy:web:disable.

Capistrano + Drush == Win!

While cap works great for pulling strings on the server, it of course knows nothing of Drupal's internals (being from ruby-land). Adding Drush with a bit of glue can help a great deal.

Here are three tasks included with the Capfile in Part 1:

cap deploy:web:disable       # Set Drupal maintainance mode to off-line.
cap deploy:web:enable        # Set Drupal maintainance mode to online.
cap deploy:cacheclear        # Flush the Drupal cache system.

To make this work, first cap needs know where to find Drush. Since this is potentially different on each server, it's placed in config/deploy/[STAGE].rb:

set :drush, "cd #{current_path} ; /usr/bin/php /data/lib/php/drush/drush.php"

Further, these tasks can be chained to other commands. For example, caches are cleared automatically following each deployment by adding this statement to the Capfile:

after "deploy", "deploy:cacheclear"

Making backups

cap download_db              # Download a backup of the database(s).

This task also leverages Drush, and is handy for backups or for keeping a local sandbox in sync with the production or staging environment. The SQL file will contain both the stage name and site name, to help keep things organized.

Multisite

If you have a multi-site install, some tasks need to be repeated for each site. This is where the domains variable in config/deploy.rb comes in.

set :domains, ["pterodactyl.com", "brontosaurus.com"]

This variable is used by several tasks: For example deploy:setup creates a shared directory for each domain; similarly deploy:cacheclear will clear the caches for all listed domains.

Bonus tasks

Here's 3 more tasks included with Capistrano that are kind of nifty:

cap deploy:pending           # Displays the commits since your last deploy.
cap deploy:pending:diff      # Displays the `diff' since your last deploy.
cap deploy:cleanup           # Clean up old releases.

The cleanup task is run automatically after a deployment. It keeps the latest 5 releases, and deletes the rest so they don't fill up your disk.

Future work

Ideally, I'd like to extend this Capfile to support more database operations. First priorities are probably a task for uploading / restoring database dumps, and including a database restore in the deploy:rollback task.

Ready to get started?