Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deploy to a single specific server using Capistrano

I have a system in production that has several servers in several roles. I would like to test a new app server by deploying to that specific server, without having to redeploy to every server in production. Is there a way to ask Capistrano to deploy to a specific server? Ideally I'd like to be able to run something like

cap SERVER=app2.example.com ROLE=app production deploy 

if I just wanted to deploy to app2.example.com.

Thanks!

[update] I tried the solution suggested by wulong by executing:

cap HOSTS=app2.server.hostname ROLE=app qa deploy  

but capistrano seemed be trying to execute tasks for other roles on that server in addition to app tasks. Maybe I need to update my version of cap (I'm running v2.2.0)?

like image 844
Pete Hodgson Avatar asked Jan 09 '09 21:01

Pete Hodgson


People also ask

Why use Capistrano?

Capistrano is a Ruby based remote server automation tool which can be easily used to automate mundane deployment and system management tasks. Using Capistrano, you can almost entirely automate all actions you would normally take to get your product live.

How does Capistrano work?

How does Capistrano work? Capistrano is a framework written in Ruby that provides automated deploy scripts. It connects to your web server via SSH and executes a bunch of tasks that will make your app ready to shine.

How do I run Capfile?

Navigate to your application's root directory in Terminal and run the following command: capify . This command creates a special file called Capfile in your project, and adds a template deployment recipe at config/deploy.


2 Answers

I ended up posting a question on the capistrano users list here, and got the following response from Jamis (edited a bit by me here for clarity):


Try the HOSTS environment variable:

cap HOSTS=app2.example.com production deploy 

Note that doing this will treat app2 as being in every role, not just whichever role(s) it happens to be declared in.

If what you want is to do a regular deploy, but only act on app2, and only as app2 is declared in your recipe file, you can use the HOSTFILTER variable instead:

cap HOSTFILTER=app2.example.com production deploy  

[...]

Consider this concrete example. Suppose your script defines three servers, A, B, and C. And it defines a task, "foo", that (by default) wants to run on A and B, but not C. Like this:

role :app, "A", "B" role :web, "C"  task :foo, :roles => :app do   run "echo hello" end 

Now, if you do cap foo, it will run the echo command on both A and B.

If you do cap HOSTS=C foo, it will run the echo command on C, regardless of the :roles parameter to the task.

If you do cap HOSTFILTER=C foo, it will not run the echo command at all, because the intersection of (A B) and (C) is an empty set. (There are no hosts in foo's host list that match C.)

If you do cap HOSTFILTER=A foo, it will run the echo command on only A, because (A B) intersected with (A) is (A).

Lastly, if you do cap HOSTFILTER=A,B,C foo, it will run the echo command on A and B (but not C), because (A B) intersected with (A B C) is (A B).

To summarize: HOSTS completely overrides the hosts or roles declaration of the task, and forces everything to run against the specified host(s). The HOSTFILTER, on the other hand, simply filters the existing hosts against the given list, choosing only those servers that are already in the tasks server list.

like image 118
Pete Hodgson Avatar answered Nov 23 '22 15:11

Pete Hodgson


The following should work out of the box:

cap HOSTS=app2.example.com ROLE=app deploy 

If you want to deploy to >1 server with the same role:

cap HOSTS=app2.example.com,app3.example.com,app4.example.com ROLE=app deploy 
like image 23
wulong Avatar answered Nov 23 '22 15:11

wulong