Monday, May 05, 2008

Deploying Rails from git

Git being the new kind on the block, information about capistrano with git isn't as plentifully as cap with subversion. Here is how I setup my project to deploy from git.

Garry Dolley wrote a git module for Capistrano, but it is included in version 2.1 so you don't need to do anything special to use it. In your gem directory it's at capistrano-2.2.0/lib/capistrano/recipes/deploy/scm/git.rb, and I'd suggest reading the doc header because it has some nice ways to play with variables that take advantage of the distributed nature of git.
  1. Set the scm type and replace your repository variable with the URI of your git repository:
    1. set :scm, :git
    2. set :repository, ""
    3. set :deploy_via, :remote_cache
  2. If you are using git 1.5.3 or higher on all your machines, you can use submodules by
    1. set :git_enable_submodules, true
  3. Set the branch to deploy from:
    1. set :branch, "master"
The "set :deploy, :remote_cache" also works with subversion (would have been nice to know), but is really important with git, otherwise you clone the whole repository on each deploy which takes a long time. "remote_cache" makes incremental deploys much faster. It clones the repository in shared/cached_copy and then just updates it and copies it into place on each future deploy. It also has a very nice advantage over "set :git_shallow_clone, 1" which I'll talk about later.

If you are using multi stage deployment you can put the "set :branch, 'master'" in the stage files and could even point each stage at a different branch that you merge to when the code is ready.

You can use the normal scm_user/scm_password options and capistrano will handle the authentication via ssh. Another option is setting up password-less public keys on the target servers with a restricted shell on the git server. Git will give you trouble if your HTTP repository is authenticated (needs ~/.netrc) or has an SSL certificate that doesn't validate (doesn't work if the CN differs from the dns name) so I didn't go that route.

Remove any :checkout, or other :deploy_via variables you have in your deploy.rb file and you're set.

No comments: