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.

Comments

I don't know much about capistrano, but all drush commands are now a kind of RESTful API.

when you pass the --backend/-b option , you can pipe a json array with all the parameters through stdin, and it returns a json array with all the information you need to understand exactly what happened in the process, with full log information ... and you can also do this over an ssh pipe.

Heh, few more steps and we'll have a Symfony / Sinatra micro-app running. Actually, that's not a bad idea. I mean, security issues aside it could be fun to have drush available via a web interface and if it's already running through json it wouldn't be a long shot to just drop a Rack app on top and make it official.

As of this comment, deploy:cleanup does not get run as part of a normal deploy in the latest version of Capistrano. If you want your deployments to clean up after themselves, just add this to your recipe:

after 'deploy', 'deploy:cleanup'

Hey Dylan,

Backup and Migrate has Drush integration - http://drupal.org/project/backup_migrate

I haven't used the Drush integration, but I like the module. Maybe you could use it for your Cap recipes. I'm currently doing work for an organization that deploys to one of their sites with Cap, and when I get around to it I'm certainly going to try incorporating some of this stuff :)

Thanks!

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Ready for transformation?