Skip to content


Keeping capistrano in check: ensuring roles are respected in sub-tasks

I’ve been knee deep in capistrano lately, and I’ve come across in interesting behavior:

<p>Say you have the following:</p>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
role :app, "app"
role :web, "web"

task :run_on_web, :roles => :web do
  do_something_on_server
end

task :run_on_app, :roles => :app do
  do_something_on_server
end

task :do_something_on_server do
  run "/usr/sbin/something"
end
<p>If you run the run_on_web task, it will execute the do_something_on_server task using all roles.  This isn&#8217;t the behavior you most expected most likely.  The secret to making this work is to set <span class="caps">ENV</span>[&#8216;HOSTS&#8217;] match your the set of hosts you are interested in.  After you are done you&#8217;ll want to set <span class="caps">ENV</span>[&#8216;HOSTS&#8217;] hosts back to it&#8217;s original contents.  I&#8217;ve whipped up a quick method to make this even easier.</p>
1
2
3
4
5
6
7
8
9

def with_role(role, &block)
  original, ENV['HOSTS'] = ENV['HOSTS'], find_servers(:roles =>role).map{|d| d.host}.join(",")
  begin
    yield
  ensure
    ENV['HOSTS'] = original 
  end
end  
<p>You can call it like this:</p>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

role :app, "app"
role :web, "web"

task :run_on_web, :roles => :web do
  with_role :web do
    do_something_on_server
  end
end

task :run_on_app, :roles => :app do
  with_role :app do
    do_something_on_server
  end
end

task :do_something_on_server do
  run "/usr/sbin/something"
end
<p>Hopefully this helps someone.</p>

Posted in Uncategorized.



Blog WebMastered by All in One Webmaster.