Mike Clark made a recent post on his blog about how to handle Rails versions with Capistrano. Very nice stuff. I’ve put his code samples to immediate use with an app I’m preparing to convert to Rails 1.2.1.
I’ve run into some trouble this week, though, as I want to update one of my client projects that still runs version 1.1.6 of Rails. Mike’s Capistrano task takes a revision number so checking out a fresh copy with his script looks something like this.
rake deploy_edge REVISION=5990 RAILS_PATH=/path/to/shared/rails
This checks out 1.2.1 into the specified directory. After spending a few minutes trying to find the revision number for 1.1.6 (and chatting briefly with my Campfire peeps about the best way to proceed) I’ve decided that it’s safer to use tags instead of revisions. Deploys now look like this:
rake deploy_edge TAG=rel_1-1-6 RAILS_PATH=/path/to/shared/rails
Much more readable. The only downside, of course, is losing revision granularity. I’m essentially tied to the whim of the Core team as to when they decide to create new tags. But on the other hand, most of my projects aren’t currently running on Edge so this is suitable for my needs at the moment.
I’ve included my rewrite of the task below. Just drop it in common.rake
or wherever you prefer to put your custom tasks. Reading Mike’s post would be a good idea too since he explains how to get this working with a remotely deployed Rails application.
desc "freeze rails edge" task :deploy_edge do ENV['SHARED_PATH'] = '/var/www/apps/shared' unless ENV['SHARED_PATH'] ENV['RAILS_PATH'] ||= File.join(ENV['SHARED_PATH'], 'rails') export_path = "#{ENV['RAILS_PATH']}/#{ENV['TAG']}" symlink_path = 'vendor/rails' unless File.exists?(export_path) puts "checking out rails tag #{ENV['TAG']}" get_framework_for export_path do |framework| system "svn export http://dev.rubyonrails.org/svn/rails/tags/#{ENV['TAG']}/#{framework}/lib " << "#{export_path}/#{framework}/lib --quiet" end end puts 'linking rails' rm_rf symlink_path mkdir_p symlink_path get_framework_for symlink_path do |framework| ln_s File.expand_path("#{export_path}/#{framework}/lib"), "#{symlink_path}/#{framework}/lib" end touch "#{symlink_path}/TAG_#{ENV['TAG']}" end def get_framework_for(*paths) %w( railties actionpack activerecord actionmailer activesupport activeresource actionwebservice ).each do |framework| paths.each { |path| mkdir_p "#{path}/#{framework}" } yield framework end end
Lately we’ve been developing against edge via svn externals. It hasn’t been a problem. You lock the externals to a revision and tag it when you deploy, then point it back to head for development.
Nice enhancement, Matthew! I experienced differences between a Rails tag and the Subversion revision that corresponds to it and Mike pointed me to your solution.
I merged your solution and Mike’s, so that you can specify either a tag or a revision number. Here’s what I came up with: http://pastie.caboo.se/116805
WDYT?
Ed