Thursday, September 27, 2007

Deploying with capistrano to servers behind a firewall



First lets install the rsync_with_remote_cache gem:

Check-out from source
svn co http://svn.extendviget.com/lab/trunk/gems/capistrano_rsync_with_remote_cache

Add patch so we will deploy to all roles not just the :app role(this will ensure that migration will work)
vi lib/capistrano/recipes/deploy/strategy/rsync_with_remote_cache.rb

change this:

# Step 2: Update the remote cache.
logger.trace “copying local cache to remote”
find_servers(:roles => :app, :except => { :no_release => true }).each do |server|
system(”rsync -az –delete #{local_cache}/ #{user}@#{server.host}:#{repository_cache}/”)
# TODO: an alternate version that excludes SVN, if we wanted to use an export-like strategy,
# from Andrew Kreiling - however, if we do an svn export locally and then sync it up, it wouldn’t
# include .svn anyway so this may be moot
# system(”rsync -az –delete –exclude=.svn –delete-excluded #{local_cache}/ #{user}@#{server.host}:#{repository_cache}/”)
end

to this:

# Step 2: Update the remote cache.
logger.trace “copying local cache to remote”
find_servers(:except => { :no_release => true }).each do |server|
system(”rsync -az –delete #{local_cache}/ #{user}@#{server.host}:#{repository_cache}/”)
# TODO: an alternate version that excludes SVN, if we wanted to use an export-like strategy,
# from Andrew Kreiling - however, if we do an svn export locally and then sync it up, it wouldn’t
# include .svn anyway so this may be moot
# system(”rsync -az –delete –exclude=.svn –delete-excluded #{local_cache}/ #{user}@#{server.host}:#{repository_cache}/”)
end

Create the gem
rake package

Install the gem
gem install pkg/capistrano_rsync_with_remote_cache-2.1.gem

Verify
gem list capistrano_rsync_with_remote_cache

Now inside of the capistranos deploy.rb file add this
set :deploy_via, :rsync_with_remote_cache

This strategy maintains two cache directories:

    * The local cache directory is a checkout from the Subversion repository. The local cache directory is specified with the local_cache variable in the configuration. If not specified, it will default to “.rsync_cache” in the same directory as the Capfile.

    * The remote cache directory is an rsync copy of the local cache directory. The remote cache directory is specified with the repository_cache variable in the configuration (this name comes from the remote_cache strategy that ships with Capistrano, and has been maintained for compatibility.) If not specified, it will default to “shared/cached-copy” (again, for compatibility with remote_cache.)

Deployment happens in three major steps. First, the local cache directory is processed. If it does not exist, it is created with a checkout of the revision to be deployed. If it exists, but is not a checkout from the repository specified in the configuration, the cache directory is removed, then recreated as if it did not exist. If it exists, and is a checkout from the repository specified, it is updated to the revision to be deployed.

Second, rsync runs on the local side to sync the remote cache to the local cache. When the rsync is complete, the remote cache should be an exact replica of the local cache.

Finally, a copy of the remote cache is made in the appropriate release directory. The end result is the same as if the code had been checked out directly on the remote server, as in the default strategy.