Test Driven Deployment

Let me start by saying the I think TDD is the best way to develop quality software. It helps you develop a rhythm, keeps you focused, and has the nice side effect of leaving your application surrounded by unit tests. I have always felt uncomfortable doing work in environments where the rhythm of TDD was not possible. Lately, I have been feeling this pain while developing deployment scripts for a rails application. Utilizing the power of capistrano, Paul and I came up with a rather novel way to test that our deployment scripts were working.
namespace :verify do
 
  task :mongrels, :roles => :app do
    (0...mongrel_count).each do |port_offset|
      assert_status_code '200', "http://localhost:#{mongrel_port + port_offset}/pulse"
    end
  end

  task :ha_proxy, :roles => :app do
    assert_status_code '200', "http://localhost:#{proxy_port}/pulse"
  end
   
  task :apache, :roles => :app do
    assert_status_code '200', "http://localhost:#{apache_port}/monit/token"
  end
end

def assert_status_code expected, url
  assert_equal expected, %{curl -s -o /dev/null -w '%{http_code}' #{url} }
end

def assert_equal expected, command
  errors = []
  run command do |ssh_channel, stream, output|
    errors << "Expected: #{expected} but was #{output} on #{ssh_channel.connection.host}" unless output == expected
    end
  raise "Errors on servers: \n  #{errors.join("\n  ")}\n\n" unless errors.empty?
end
We then execute these 'verify' tasks after the deploy task has completed.
after :deploy do
  verify.mongrels
  verify.ha_proxy
  verify.apache
end
More on this later!
blog comments powered by Disqus