What Is Capistrano Designed For?

Seems like every time I try to make use of it I am hacking around it.

To deploy to different environments, one must either do a switch or define an extra task to set the necessary variables. It’s a bit of code duplication but not really very bad. It gets a little bit worse when you also would like to be able to deploy from a branch or tag. The smarter way, of course, would be to have a built-in feature for defining different deployment environments, I don’t know anybody who has only one environment.

Where it starts to get annoying is when you want to deploy similar things that have some small difference between them, for example a debug version of a website as well as staging and production. Staging and production are just duplicating some settings and changing some paths, for debug currently you need to mark a server as debug and do something different for it, you end up setting a global variable and adding a branch anywhere that needs to check that code. For some reason using something like


task :stage do
  role :web, "staging.example.com"
end

task :dev do
  role :web, "debug.example.com", :debug => true
end

task :set_debug, :only => { :debug => true } do
  set :debug, "1"
end

namespace :deploy do
  task :before_symlink do
    set_debug

    p debug # WRONG: always prints "1"
  end
end

doesn’t work because it is always called regardless of this “only” business, so you have to resort to branching and global variables set at the top. Even if somebody offers up a solution or workaround to that particular bug the issue remains that one should simply be able to do something based on properties of the current host rather than having to define a sub-task to filter actions.

Furthermore, the /real/ annoyance begins when you have to deploy differing environments from the same code in the same deployment. Due to the same reasons as above I cannot do something with an intention like

role :front, "front.example.com", :readonly => true
role :web, "web.example.com"

task :set_debug, :only => { :debug => true } do
  set :readonly, "1" # this will fail because it sets it for both
end

namespace :deploy do
  task :before_symlink do
    set_readonly

    p readonly # WRONG: always prints "1"
  end
end

without resorting to environment variable hackery based on role or hostname checking.

Obviously what we all want from a deployment tool is a way to declaratively define the servers and their attributes and capistrano just falls flat on its face when faced with any of these very average deployment scenarios.

Update Hmm, Vlad the Deployer sounds nice