It's not actually that straightforward to serialize deployment in capistrano, which likes to parallelize all of its operations between servers. To restate the issue, it seems like you have a handful of servers and want to take each one offline in sequence to update the deployment.
The trick is to override the deploy:create_symlink
task in your deployment configuration:
def perform_task_offline options
sudo "take_this_server_offline", options
yield
sudo "put_this_server_online", options
end
def create_symlink_task options
# does what your existing deploy:create_symlink did, something like:
run "rm -f /web/current && ln -s #{release_path} /web/current", options
end
namespace :deploy do
task :create_symlink, {once: true, except: {no_release: true}} do
deployed_servers = Array.new
roles[:app].servers.each do |current_server|
options = {hosts: current_server}
deployed_servers.push current_server
perform_task_offline(options) { create_symlink_task options }
end
end
end
In this case perform_task_offline
includes commands that execute on the server specified in options
that remove it from the load balancer while it yield
s the block including create_symlink_task
, which creates the deployment symlink.
You should then be able to run the standard cap
command to deploy, and you'll see the servers sequentially go offline, create the "current" symlink, then come back up.
Note that the above code tracks the servers that have successfully been deployed to with deployed_servers
. If you want to be able to rollback an active failed deployment (that is, the failure happens during deployment itself) on only the servers that had previously been deployed to, you'll need a similar loop inside of an on_rollback do
block, but over only the deployed_servers
.