Pattern: Conditional Configuration

Posted by Jamis on Monday, July 14

Here’s a pattern that I’ve been using and seeing more and more often. The problem it solves is this: how do I configure Capistrano differently for some set of predetermined scenarios? The most common usage of it is when configuring Capistrano to deploy to different staging locations, and you want to configure each stage differently.

The cleanest solution simply involves creating a different task for each scenario. Within each task, you set variables, declare roles, and load files:

1
2
3
4
5
6
7
8
9
10
11
task :scenario_a do
  set :deploy_to, "/path/to/scenario_a"
  role :web, "scenario_a.web"
  role :app, "scenario_a.app"
end

task :scenario_b do
  set :deploy_to, "/path/to/scenario_b"
  role :web, "scenario_b.web"
  role :app, "scenario_b.app"
end

When you then go to invoke a task (like deploy), you simply invoke the scenario task you want first:

  $ cap scenario_a deploy

Capistrano simply invokes the task in the same order they were specified, so in this case, it will first call scenario_a (which will set up the deploy_to variable and the roles) and then will call deploy, which will use the settings you gave.

It’s really a quite powerful pattern for conditional configuration.

Comments

1 Manish 27 Jul 2008
I typically create difference config file as I call it, where I define all the variables need to install my builds on different machine and then invoke cap using cap -f cap_server1 deploy cap -f cap_server2 deply One more pattern I see but could not find better way solution to this is of copying files from one machine to other. The situation goes like this: I run cap scripts on my work station. I need to copy the latest builds from our build server to test machine were I need to install the builds. The way I have done currently is that, I wget the build binary, copy it to local machine and then push it to the remote machine where I have cap connection to. By the way, last time I tried copying big files using cap, it used fail, so I use rsync in system command to do this. Anyways, I was wondering if there is way in cap, where in I can interact with more than two machines using same cap task? This will be really helpful in executing some of my tests, which need to do lots of verification on multiple machines. Thanks for the great tool, anyways. manish at gslab dot com
2 Matthias Marschall 11 Sep 2008
We use an environment variable DEPLOY_ENV similar to RAILS_ENV with values like "development", "reference" and "production". There is one file for every environment, which defines the environment specific roles and variables. This is a little less elegant as the task based solution, but it works well for us so far.
3 Brenton 15 Sep 2008
The only drawback we've found to this pattern is that it makes it tricky to override the local variables (such as :deploy_to above) via command-line arguments, because the variables are being set from within tasks. In such cases, it seems like you would need to use environment variables set from the command-line.