Posted by Jim Morris
Sun, 18 Feb 2007 23:32:00 GMT
I have updated the Capistrano local subversion module and added a perforce one.
The original article is here.
I have added rsync as an option to speed up
the deployment to remote servers, To use that option install this
version,
in the example below I have installed the file into my rails projects
lib/tasks directory.
When the rsync option is set the deployment method will use rsync over
ssh to synchronize between a local cache of the subversion project and
a remote cache, minimizing the amount of data uploaded to the server.
To use rsync use this in the deploy.rb...
require 'lib/tasks/local_subversion_rsync.rb'
set :scm, Capistrano::SCM::LocalSubversionRsync
set :repository_is_not_reachable_from_remote, true
set :use_rsync, true
set :local_rsync_cache, "/home/user/projects/aproject/cache"
set :remote_rsync_cache, "/var/www/webapp/cache"
set :rsync_username, "ausername"
set :rsync_excludes, ["*.bak", "*.log"]
The rsync_username and rsync_excludes are optional.
The :rsync_username option sets the username that ssh uses to login
to use rsync. Leave it blank if it is the same as your current login
name.
The :rsync_excludes option allows you to pass --exclude options to
rsync, using the rsync syntax for exclusions, this is an array of
patterns to exclude.
Note you must do a local SVN checkout to the directory specified by
local_rsync_cache at least once before using this method.
Also the directory specified by remote_rsync_cache must exist on the server.
The perforce version of the scm module that allows the perforce server
to be accessed locally only is
here,
note that this does not currently support the rsync option
or write to the revisions.log.
Read more...
Posted in Rails | Tags capistrano | 1 comment | no trackbacks
Posted by Jim Morris
Thu, 07 Dec 2006 05:42:00 GMT
UPDATE 2007-06-09 This method has been deprecated in Cap 2.0.
UPDATE 2007-02-21 I have updated the files to correctly update revisions.log
UPDATE I added rsync as suggested see end of article for more info.
I previously published a custom deploy recipe that allowed subversion
to checkout from a local repository and send to the remote server.
This was a suboptimal solution, as it wouldn't work with things like
deprec.
So here is the way I should have done it in the first place. It is a
modified version of the standard subversion scm module, it should be
backward compatible with the built in version, but adds a couple of
features.
- Handles the subversion repository only being accessible from the local
machine
- If the subversion repository is accessible from the remote server
allows for different URLs for access from the local and remote
machines.
If you use a standard deploy.rb and your subversion is accessible
from the server, then it should work exactly as the built-in version
(no need to use it then, but it should work)
However if you have your subversion server behind your local firewall,
you just add these three lines to your deploy.rb
require 'lib/tasks/local_subversion_rsync.rb'
set :scm, Capistrano::SCM::LocalSubversionRsync
set :repository_is_not_reachable_from_remote, true
And everything will work as before, even though the server has no idea
what subversion is.
Of course for this to work you need to download
this de-tar
it and put it in your lib/tasks directory. (That's where the require
line gets this extension from). There is also a unit test for the
new_subversion module which is extended from the one shipped with
Capistrano, which passes.
Everything else in deploy.rb should be the same as before, except
that you set the repository to the URL your local machine uses to
access your locally accessible subversion server or repository.
(Should even work with the URL file://...), for instance...
set :repository, "svn://your.svnserver.host/#{application}/trunk"
The assumption is that both the local and remote machines can create
files and directories in /tmp, if this is not true then one or both
of these should be set...
set :tmpdir_local, "/usr/tmp"
set :tmpdir_remote, "/home/user/tmp"
The way this module works is to export the relevant version of the
project from Subversion into a temporary directory on the local
machine (default is /tmp/unique_name). Then I create a gzip'd tar
archive into the temp directory. The tar file is then transferred to
the target servers, using the Capistrano put command into a
temporary directory (/tmp by default) on the server. I then create the
target directory on the server and un-tar the file into that
directory. Then clean up the various temporary files. From the
perspective of the server the end result should be identical to doing
an svn export into the target directory on the server.
The other facility this SCM Module provides is when your subversion
server is accessible from the server as is the "normal" use case (per
the Capistrano developers, but bad practice IMHO), but you need a
different URL to access the SVN repository from the local machine vs
the remote server, eg
server accesses with this URL svn://localhost/myapp/trunk
local machine accesses with this URL svn+ssh://myserver.com/myapp/trunk
in this case you add these lines...
require 'lib/tasks/local_subversion_rsync.rb'
set :scm, Capistrano::SCM::LocalSubversionRsync
set :local_repository_path, "svn+ssh://myserver.com/myapp/trunk"
set :repository, "svn://localhost/myapp/trunk"
In addition if the actual SVN binary is different on server and local
you can add these for instance...
set :remote_svn, "/usr/local/bin/svn"
set :local_svn, "/usr/bin/svn"
If the relevant configuration variable is not set then the standard
svn configuration variable is used, and then just "svn" if that is not set.
Please beware I have not fully tested the use cases other than the
first one, where I use my local subversion server to deploy to my
remote servers that know nothing about subversion, however the unit
tests do pass for the other use cases.
UPDATE 2007-02-15 check this article for using the rsync option.
Posted in Rails, Ruby | Tags capistrano, subversion | 26 comments | no trackbacks
Posted by Jim Morris
Wed, 15 Nov 2006 22:04:28 GMT
One of the things that bugs me about Capistrano is the requirement
that access to the remote subversion repository have the same path
from the local machine and the remote machine. This is never the case
in my experience.
I have been getting around it by setting the path to
svn://localhost/... and running ssh locally to port forward the SVN
port to the remote host. This sucks as I usually forget to run ssh in
another window first.
So I added an optional configuration variable to be set in deploy.rb
called local_repository_path, so now you set the repository path as
normal, which is the path the remote server uses to access the SVN
repository, and you set the path that the local machine (your
workstation) uses to access the same repository...
set :repository, "svn://localhost/#{application}/trunk"
set :local_repository_path, "svn+ssh://myremotehost.com/path/to/repostitory/#{application}/trunk"
Ideally one would patch the Capistrano distribution to achieve this,
but thanks to the magic of ruby you can patch it from your own
setup so I put the following into lib/tasks/patch_capistrano.rb
module Capistrano
module SCM
class Subversion
def latest_revision
@latest_revision ||= begin
configuration.logger.debug "querying latest revision..."
match = svn_log(configuration[:local_repository_path]).scan(/r(\d+)/).first or
raise "Could not determine latest revision"
match.first
end
end
def diff(actor, from=nil, to=nil)
from ||= current_revision(actor)
to ||= "HEAD"
`svn diff
end
end
end
end
Then simply add this line to your config/deploy.rb...
require 'lib/tasks/patch_capistrano'
and everything works fine now.
Note there are only two scm methods that access SVN from the local
machine, latest_revision and diff. I have patched both.
I'll tidy this up, make the default for local_repository_path be
repository, and submit the patch to the Capistrano folks, who will
hopefully commit it to the source code, as it won't affect existing
users, but will make the rest of us a little happier.
Posted in Rails | Tags capistrano, rails, subversion | 2 comments | no trackbacks
Posted by Jim Morris
Sat, 27 May 2006 00:08:00 GMT
UPDATE 2006-12-06 I have replaced this with a full blown SCM module that works much better, see this posting
It seems that many people are in the same position as I was, they want
to deploy to a remote server farm that does not have access to the
SCCM (subversion,CVS,perforce etc), which is usually behind a corporate firewall.
The following recipe overcomes this by checking out the source code
from the local repository (using svn in this case) and goes into your
deploy.rb.
What it does is checkout the latest copy of the application from your
local subversion repository, tars it up, and copies the tar file to
the remote server, then detars it and does the normal deploy tasks
from then on.
desc <<DESC
Update all servers with the latest release of the source code.
This is a modified version that copies a local copy to the remote site
DESC
task :update_code, :roles => [:app, :db, :web] do
on_rollback { delete release_path, :recursive => true }
#puts "doing my update_code"
temp_dest= "tmp_code"
#puts "...get a local copy of the code into #{temp_dest} from local svn"
# but this could also just be your local development folder
system("svn export -q #{configuration.repository} #{temp_dest}")
#puts "...tar the folder"
# you could exclude files here that you don't want on your production server
system("tar -C #{temp_dest} -c -z -f code_update.tar.gz .")
#puts "...Sending tar file to remote server"
put(File.read("code_update.tar.gz"), "code_update.tar.gz")
#puts "...detar code on server"
run <<-CMD
mkdir -p #{release_path} &&
tar -C #{release_path} -x -z -f code_update.tar.gz &&
rm -rf code_update.tar.gz &&
rm -rf #{release_path}/log #{release_path}/public/system &&
ln -nfs #{shared_path}/log #{release_path}/log &&
ln -nfs #{shared_path}/system #{release_path}/public/system
CMD
#puts "...cleanup"
system("rm -rf #{temp_dest} code_update.tar.gz")
end
This recipe does what many people need todo which is replace the database.yml with the production version, and also repalces the .htaccess with the production version (YMMV)
desc "fix up database and .htaccess"
task :after_update_code do
run "cp #{release_path}/config/database.yml.templ #{release_path}/config/database.yml"
run "cp #{release_path}/public/dot.htaccess.deploy #{release_path}/public/.htaccess"
end
Posted in Rails, Ruby | Tags capistrano, deployment, rails, ruby | no comments | no trackbacks