Posts tagged deployment

Selected (belated, extended) Saturday Links

The past two weeks haven’t really left time to compile my selected links, though there have been many. A few days at SxSWi (on which more, later) followed by travelling with the family and the inevitable work backlog moved blogging way down the priority list. So here’s a mammoth selection to get me caught up. Particularly interesting has been the discussion around the future of newspapers (represented here by Clay Shirky, Steven Johnson and Russell Davies), which seem to have finally pushed beyond “how t ind a good business model for papers” to looking at where the real value for society lies and how we can preserve and extend that in a changing landscape.

Selected Saturday Links

Big themes this week have mostly revolved around twitter, facebook, and openness. Some have focussed on facebook redesigning to embrace a more twitter-like “web of flow” approach, and others on the fact that they’re jumping on various open web bandwagons. It’s been interesting to see some tie in with the government transparency thinking going around, as particularly noted by Chris Messina on FactoryCity. Meanwhile there are quite a few nice new tools emerging, and I really must try heroku one of these days.

Deploying a Drupal Site with Capistrano 2

A little over a year ago I wrote up some instructions for deploying drupal sites using capistrano. It’s proved a popular entry, still getting a good bit of traffic, but in the time since I wrote it Capistrano 2 has joined us and my techniques have moved on, so it seemed high time I updated the instructions with some new ones.

As before, I’m going to presume that anyone reading this already has capistrano installed and has shell access to their server. If you need help with the former, I’d recommend stopping by the Capistrano website, and for the latter you should probably talk to your hosting company.

My approach is to keep each site’s assets (modules, themes, etc) within that site’s folder, and then store each site in version control (git or subversion). In common with capistrano-based rails deployments, I then have the site’s files and images stored in a shared folder and symlinked into the site, so that they can be preserved between deployments.

To get started go into the folder for the site you want to be able to deploy (eg. /path/to/drupal/sites/mysite.com) and type at the command line:

mkdir config
capify .

That will create the basic files for deployment, which you will then need to edit with your configuration details. I start by opening the file config/deploy.rb and deleting everything in it, so as to start with a blank slate. I then put in some overrides to capistrano’s default deployment methods so that they work better with drupal:

set :asset_folders, %W(images files)
 
namespace :deploy do
  desc "Link the asset folders from the shared folder into our site"
  task :finalize_update, :except => { :no_release => true } do
    logger.info 'finalizing update with custom method'
    run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
 
    asset_folders.each do |asset|
      run "rm -rf #{release_path}/#{asset}"
      run "ln -nfs #{shared_path}/#{asset} #{release_path}/#{asset}"
    end
  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}
    CMD
    asset_folders.each do |asset|
      run "mkdir #{shared_path}/#{asset}"
    end
  end
 
  task :set_permissions, :except => { :no_release => true } do
    # do nothing
  end
 
  task :restart do
   # do nothing 
  end
end

You then need to set some basic configuration, so also in deploy.rb place:

set :deploy_to, '/path/to/your/drupal/sites'
 
# Make sure this is the domain name of your app as it is 
# what your sites folder will be named
set :site_name, 'staging.scodigo.com'
role :web, "your.server.com"
set :current_path, "#{deploy_to}/#{site_name}"
set :shared_path, "#{deploy_to}/shared/#{site_name}"
set :repository, "svn://your.svn.com/path/to/repos/trunk"

With that in place you’re all ready to go. But there was an extra step I decided to add this time around. Since I am frequently setting up new staging/test sites and often need to upgrade them to new versions of drupal, I wanted to be able to install and update the drupal files using capistrano.

To do that, I wrote a recipe that will grab the tarball for a given release, unpack it and install it, without wiping out an existing sites folder. To add that you will need to put the following code into your deploy.rb file:

namespace :drupal do
  desc <<-DESC
  Grab the specified version of drupal and install it
 
  This presumes that the variables drupal_version and drupal_path have been set
  DESC
 
  task :install do
    run "cd #{shared_path} && curl -O http://ftp.drupal.org/files/projects/drupal-#{drupal_version}.tar.gz"
    run "cd #{shared_path} && tar xzvf drupal-#{drupal_version}.tar.gz"
    run "rm -rf #{shared_path}/drupal-#{drupal_version}/sites"
    run "cd #{drupal_path} && rm -rf !(sites)"
    run "mv #{shared_path}/drupal-#{drupal_version}/* #{drupal_path}"
    run "mv #{shared_path}/drupal-#{drupal_version}/.htaccess #{drupal_path}/.htaccess"
    run "rm -rf #{shared_path}/drupal-#{drupal_version}"
  end
end
 
after "deploy:setup", "drupal:install"
set :drupal_path, File.join(deploy_to, '../')
set :drupal_version, "5.8" # Or whatever version you want to install

(You can download a copy of the combined deploy.rb file here or view it as a pastie here)

Now, to set up your drupal site you just need to change directory to your site and type and command line:

cap deploy:setup

and to deploy a new version:

cap deploy

In practice, I tend to use these techniques in combination with the Capistrano Multistage extension, so that I can deploy a site to a staging server first, and then a production server. I’d highly recommend that approach, but for now will leave it as an exercise for the reader.

Please note that this technique is also designed to support a multi-site drupal set up, but hasn’t been extensively tested in that context. It should work, but no guarantees!

Book Review: Pro Drupal Development

It’s surprising given drupal’s popularity that there aren’t more books covering it in detail. Site launches and contributions by the likes of lullabot and bryght have pushed the CMS’ profile and recent releases have emphasised the Web 2.0 potential, but a quick look at amazon reveals only four related titles. Of the four, Pro Drupal Development is definitely the most developer focussed.

This isn’t a book for a drupal newbie. Going in you’ll want to have spent at least a little time setting up a drupal site or two, and while there’s no need to be a PHP guru the authors do presume you’re not going to need help understanding their code samples. They focus on drupal’s internals, with a lot of time spent writing modules, understanding the user, node, menu, theme and related systems, and a little attention for performance optimisation.

There’s a lot of ground to cover and most chapters are short, giving just the essentials on each area. You’ll probably want to pause from time to time to try out the code samples unless you’re already experienced at writing drupal modules. Having written a number of modules and run into various problems I found I was able to focus on the new information and how it would have affected my approach, but if this is new ground the structure of the book may make it rather overwhelming.

The writers are keen to encourage their readers to read the book in order, and some chapters certainly do build on their predecessors, but the real strength of this is likely to be as a reference guide. A quick once-through will help newcomers to module development get a sense of how everything fits together, but chances are you’ll then want to refer back when you actually encounter problems that a given chapter can help with.

I was disappointed not to see more coverage of testing drupal code. As I mentioned yesterday, the lack of attention paid to automated testing in the drupal community frustrates me and it seems that for a book like this to not to provide some coverage of sensible testing regimens is a missed opportunity. Similarly, it would be really good to have some coverage of deployment tips, particularly relating to upgrading active sites. Both of those seem to me like core topics for any book purporting to provide a guide for professionals, but the priorities of the book mirror those of the drupal community where neither topic appears to be a significant concern.

For any experienced developer who needs to get to grips with the insides of drupal and/or write custom extensions, this book will be invaluable. The style won’t suit those looking for a broader scope or lengthier tutorials, but it will help you get to grips with each of the major components quickly and provide enough information to set you on your way. Hopefully it will also trigger further writing about drupal, which may cover more ground and help developers bring some other vital practices to their drupal work.

Disclaimer: I was sent a copy of this book for review by the publisher. You can find it at apress, amazon US, amazon UK and all sorts of other places.

Protecting static files when deploying with Capistrano

There’s one project I work on where the client wants to be able to edit HTML files in the root folder, but I want to be able to deploy with capistrano. It’s a pain to have to log into the server and check whether those files have changed before each deployment so last night, I added the following to my deploy.rb:

desc "Make sure we don't overwrite manual static file changes"
task :before_deploy do
  captured = false
 
  run "svn status #{deploy_to}/current/public" do |ch, stream, data|
    if stream == :out and data.chomp.match(/^M/)
      captured = true 
    end
  end
 
  if captured
    run "svn commit #{deploy_to}/current/public -m 'Storing manual changes to static HTML before deploy'"
  end
end

It’s not the most elegant, but it’ll make sure that any files the client has changed (which were already in the repository) are committed, and it makes the deployment process just that little bit easier.

(thanks to Jonathan Weiss for a recent blog entry that reminded me to implement this.)