Hello!
I am using Mercurial as scm and it really bothered me to transfer
complete copy of local repository to servers on every deploy.
So I hacked together a general (I think so) deployment strategy which
does a local checkout (or even better: export) and copies it using
rsync to remote cache.
As an added bonus the file contains few lines that cut the transfer
size in half - support for Mercurial export. I really don't know why
this isn't in official distribution, but I am newbie regarding
Mercurial and maybe somebody will enlighten me to the potential
problems in my code.
Also, since I am newbie regarding modifications of cap sources, I
welcome any comments about problems with the strategy code. It works
for me, but since capistrano helps me a lot, I thought it would be
nice to contribute something back.
capify.org is down and #rubyonrails is full, so no patch/pastie
coolnes. I just include the file source below. Paste it into file
$RAILS_ROOT/capistrano/recipes/deploy/strategy/
copy_with_rsync_and_remote_cache.rb
and use
set :deploy_via, :copy_with_rsync_and_remote_cache
in your deploy.rb.
Regards,
izidor
#
# addition for Mercurial :export
#
require 'capistrano/recipes/deploy/scm/mercurial.rb'
module Capistrano
module Deploy
module SCM
class Mercurial < Base
# hg archive - cuts the directory size in half (at least)
compared to :checkout
def export(revision, destination)
scm :archive, verbose, "-r", revision, destination
end
end
end
end
end
#
# Copying to remote cache with rsync
#
# (Implementation shamelessly borrows code from Remote, RemoteCache
and Copy)
#
require 'capistrano/recipes/deploy/strategy/base'
require 'fileutils'
require 'tempfile' # Dir.tmpdir
module Capistrano
module Deploy
module Strategy
# Implements the deployment strategy that keeps a cached copy of
# the source code on each remote server. Each deploy does the
following:
# - makes local checkout to temporary directory,
# - copies the local checkout using rsync to each remote server,
# - on each remote server copies from the cached copy to the
final deployment location.
class CopyWithRsyncAndRemoteCache < Base
# Obtains a copy of the source code locally (via the
#command method),
# copies (with rsync) that directory to cached directory on
all target
# servers, and then copy from cached directory to the
deployment
# directory.
def deploy!
logger.debug "getting (via #{copy_strategy}) revision #
{revision} to #{destination}"
system(command)
File.open(File.join(destination, "REVISION"), "w") { |f|
f.puts(revision) }
logger.trace( "copying data with rsync" )
# get all servers for our current task and copy the files
using rsync
# TODO Is there a better way to implement the following
code, some canonical predefined methods we can use?
servers = find_servers :roles => :app, :except =>
{ :no_release => true }
servers.each do |dest_server|
logger.trace( "copying to #{dest_server}" )
raise unless system( rsync_command_for(dest_server) )
end
logger.trace( "copying data with rsync - finished" )
copy_repository_cache
ensure
FileUtils.rm_rf destination rescue nil
end
def check!
super.check do |d|
d.remote.writable(shared_path)
d.local.command( "rsync" )
d.remote.command( "rsync" )
end
end
private
# Returns the basename of the release_path, which will be
used to
# name the local copy and archive file.
def destination
@destination ||= File.join(tmpdir, File.basename
(configuration[:release_path]))
end
# Returns the value of the :copy_strategy variable,
defaulting to
# :checkout if it has not been set.
def copy_strategy
@copy_strategy ||= configuration.fetch
(:copy_strategy, :checkout)
end
# Should return the command(s) necessary to obtain the
source code
# locally.
def command
@command ||= case copy_strategy
when :checkout
source.checkout(revision, destination)
when :export
source.export(revision, destination)
end
end
# The directory to which the copy should be checked out
def tmpdir
@tmpdir ||= configuration[:copy_dir] || Dir.tmpdir
end
# The directory on the remote server where cached copy
should reside
def repository_cache
File.join(shared_path, configuration[:repository_cache]
|| "cached-copy")
end
#
def copy_repository_cache
logger.trace "copying the cached version to #
{configuration[:release_path]}"
run "cp -RPp #{repository_cache} #{configuration
[:release_path]} && #{mark}"
end
# Returns the command which will write the identifier of the
# revision being deployed to the REVISION file on each host.
def mark
"(echo #{revision} > #{configuration[:release_path]}/
REVISION)"
end
#
def rsync_command_for( server )
"rsync -az --delete '#{destination}/' '#{configuration
[:[EMAIL PROTECTED]:#{repository_cache}'"
end
end
end
end
end
--~--~---------~--~----~------------~-------~--~----~
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/capistrano
-~----------~----~----~----~------~----~------~--~---