Posts tagged Ruby/Rails

Using capistrano for drupal deployment

UPDATE: This post was written using Capistrano 1, which has since been superseded. An updated version—covering deployment of Drupal with Capistrano 2—can be found here.

It’s easy to get spoiled building rails apps. Tools like migrations make it so much easier to keep databases in sync, the way environments are managed helps considerably, and there’s Capistrano which makes rapid deployments a breeze. I miss those things when I have to work with other systems.

A few months back there had been a brief conversation about using capistrano with drupal and there are several blog posts (like this one) about using it with PHP. So today, tired of resolving folders full of uploaded files, I decided to write a quick deploy.rb to use capistrano with drupal.

I’m presuming here that we already have capistrano installed locally, that a recent version of drupal is set up on the server, and that we’re deploying to the sites folder. Within that we’re going to end up with capistrano’s standard ‘releases’ and ‘shared’ folders, but in this case ‘current’ will actually take on the domain name of our app and shared will contain ‘files’ rather than the usual system, log and pids.

So here’s how it goes. Firstly we want to define some variables

set :application, "MyApp"
set :site_name, "www.example.com"
set :svn_user, "james.stewart"
 
# I like to have capistrano prompt me for the password.
# You can replace this with a standard assignment
set :svn_password, Proc.new { Capistrano::CLI.password_prompt("SVN Password for #{svn_user}: ") }
 
set :deploy_to, "/home/mp_app/public_html/sites"
role :web, "www.example.com"

So far, so much like a regular deploy.rb file. But if we want the app’s folder within sites to be called something other than ‘current’, we’ll need to add:

set :current_path, "#{deploy_to}/#{site_name}"

So that’s our configuration taken care of. Next we need to override a few of capistrano’s default tasks since we probably won’t be wanting to restart lighttpd/fastcgi, or change the permissions:

task :set_permissions, :except => { :no_release => true } do
  # do nothing
end
 
task :restart do
 # do nothing 
end
 
task :deploy do
  update
  # restart
end

And finally we want to update the setup and update_code tasks to make use of our altered directory structure.

desc < <-DESC
Update all servers with the latest release of the source code. All this does
is do a checkout (as defined by the selected scm module).
DESC
task :update_code, :except => { :no_release => true } do
  on_rollback { delete release_path, :recursive => true }
 
  source.checkout(self)
 
  set_permissions
 
  run < <-CMD
    rm -rf #{release_path}/files
    ln -nfs #{shared_path}/files #{release_path}/files
  CMD
 
  # uncache the list of releases, so that the next time it is called it will
  # include the newly released path.
  @releases = nil
end
 
desc "Set up the expected application directory structure on all boxes"
task :setup, :except => { :no_release => true } do
  run < <-CMD
    umask 02 &&
    mkdir -p #{deploy_to} #{releases_path} #{shared_path} #{shared_path}/files
  CMD
end

Now we can save this file somewhere appropriate and deploy new versions as simply as:

% cap -f /my/path/deploy.rb deploy

People using one sites folder to run multiple applications may need to make some further alterations so their ‘shared’ and ‘releases’ folders don’t clash, but I’ll leave those as an exercise for the comments or related blog entries!

Shiny gems

There’s something going round, with people sharing the list of gems they have installed locally. To be honest, I’m not quite sure why, but I decided to join in and who knows? Maybe it’ll inspire me to write a little more about a few of my favourites?.

So without further delay…

  • abstract (1.0.0)
  • actionmailer (1.3.2, 1.3.1, 1.3.0, 1.2.5)
  • actionpack (1.13.2, 1.13.1, 1.13.0, 1.12.5)
  • actionwebservice (1.2.2, 1.2.1, 1.2.0, 1.1.6)
  • activerecord (1.15.2, 1.15.1, 1.15.0, 1.14.4)
  • activesupport (1.4.1, 1.4.0, 1.3.1)
  • acts_as_searchable (0.1.0)
  • acts_as_versioned (0.2.3)
  • atom (0.3)
  • builder (2.0.0)
  • cached_model (1.3.1)
  • calibre-bbcode (1.0.0)
  • camping (1.5.180, 1.5)
  • camping-omnibus (1.5.180)
  • capistrano (1.4.0, 1.3.1, 1.2.0)
  • cgi_multipart_eof_fix (2.1, 2.0.2, 1.0.0)
  • cheat (1.2.1)
  • daemons (1.0.4, 1.0.3, 1.0.2, 1.0.1)
  • ebayapi (0.9.4, 0.9.3)
  • erubis (2.1.0)
  • fastercsv (1.1.1, 1.1.0, 1.0.0)
  • fastthread (0.6.3, 0.6.2, 0.6.1, 0.4)
  • ferret (0.10.14, 0.10.13)
  • flickr (1.0.0)
  • gem_plugin (0.2.2, 0.2.1)
  • gruff (0.2.8, 0.2.4, 0.1.2)
  • hoe (1.1.7, 1.1.6, 1.1.2, 1.1.1, 1.1.0)
  • hpricot (0.5, 0.4.92, 0.4)
  • icalendar (0.98, 0.97)
  • isbn-tools (0.1.0)
  • json (0.4.2)
  • libxml-ruby (0.3.8.4, 0.3.8)
  • markaby (0.5)
  • memcache-client (1.2.1, 1.2.0)
  • metaid (1.0)
  • mime-types (1.15)
  • mofo (0.1.2)
  • money (1.7.1)
  • mongrel (1.0.1, 1.0, 0.3.17, 0.3.13.4)
  • mongrel_cluster (0.2.1, 0.2.0)
  • mt-capistrano (0.0.2)
  • mysql (2.7)
  • needle (1.3.0)
  • net-sftp (1.1.0)
  • net-ssh (1.0.10)
  • paginator (1.0.8, 1.0.7, 1.0.1)
  • parseexcel (0.5.1.1)
  • piston (1.3.0, 1.2.1)
  • production_log_analyzer (1.3.0)
  • rails (1.2.2, 1.2.1, 1.2.0, 1.1.6)
  • rails_analyzer_tools (1.1.0)
  • rake (0.7.1)
  • rcov (0.7.0.1)
  • RedCloth (3.0.4, 3.0.3)
  • rfm (0.1.0)
  • rmagick (1.15.2, 1.15.0, 1.14.1, 1.14.0, 1.13.0)
  • Rubilicious (0.2.0)
  • ruby-openid (1.1.4, 1.1.3)
  • ruby-prof (0.4.1)
  • ruby-yadis (0.3.4, 0.3.3)
  • rubyforge (0.4.0, 0.3.2, 0.3.0)
  • rubyosa (0.2.0, 0.1.0)
  • slave (1.2.0, 1.0.0)
  • sources (0.0.1)
  • sqlite3-ruby (1.2.1, 1.2.0, 1.1.0.1)
  • streamlined_generator (0.0.5)
  • tattle (1.0.1)
  • termios (0.9.4)
  • tzinfo (0.3.3)
  • uuidtools (1.0.0)
  • wirble (0.1.2)
  • xml-mapping (0.8.1)
  • xml-simple (1.0.10, 1.0.9)
  • ZenTest (3.4.3)