Adding code revision header to your apps

Posted by Dan Sosedoff on January 25, 2012

Sometimes its necessary to have a code revision tag somewhere on the website. Use cases are usually different and vary from just checking against the current revision, automatic upgrades and such.

If you’re rolling deployments with capistrano, it will insert the REVISION file under the app’s root dir with git sha or svn revision or whatever tag based on SCM of your choice.

Here is the simple rack middleware that injects that revision as a ‘X-REVISION’ header in responses.

module Rack
  class Revision
    @@revision = nil
    File = ::File
 
    def initialize(app, &block)
      @app   = app
      @block = block
      @file  = File.join(Dir.pwd, 'REVISION')
    end
 
    def call(env)
      status, headers, body = @app.call(env)
      headers['X-Revision'] = revision
      [status, headers, body]
    end
 
    protected
 
    def revision
      @@revision ||= read_revision
    end
 
    def read_revision
      File.exists?(@file) ? File.read(@file).strip : 'UNDEFINED'
    end
  end
end

For instance, just put that file as lib/rack/revision.rb and change your config.ru file:

require ::File.expand_path('../config/environment',  __FILE__)
use Rack::Revision
run YOUR_APP::Application

You’ll need to restart the app to apply the changes.

To test if it works just run:

curl -i -X HEAD "http://YOUR_WEBSITE/"

Sample output would be:

ETag: "8d6228d86642025c31e3d54e9a67b14b"
Cache-Control: max-age=0, private, must-revalidate
X-Runtime: 0.001491
X-Rack-Cache: miss
X-Revision: f8c51630843898e88848261dd5ebac3fdebc5e48

Using capistrano-unicorn with multistage environment

Posted by Dan Sosedoff on January 21, 2012

Awhile ago i create a capistrano-unicorn plugin for Capistrano that allows you to deploy your rails application using Unicorn. It works fine until you define multiple stages in your deployment configuration.

The issue – capistrano loads default configuration and then executes your staging task and overrides previously defined variables. Default environment before executing stage task is set to :production. So unless you define :rails_env, :unicorn_env, :app_env in your stage config it will use a wrong environment.

Lets take a look at sample deploy.rb file:

set :stages, %w(production staging)
set :default_stage, "staging"
require 'capistrano/ext/multistage'

You’ll need to add config/deploy/staging.rb and production.rb files:

set :domain,      "YOUR_HOST"
set :rails_env,   "staging"
set :unicorn_env, "staging"
set :app_env,     "staging"
 
role :web, domain
role :app, domain
role :db,  domain, :primary => true
 
set :deploy_to,   "/home/#{user}/#{application}/#{fetch :app_env}"
set :current_path, File.join(deploy_to, current_dir)

This should fix the problem with wrong rails env being passed to unicorn server.

Homebrew upgrade failure fix

Posted by Dan Sosedoff on January 19, 2012

If you have an old homebrew installation, upgrade method for package will fail with something like this:

Error: undefined method `include?' for nil:NilClass
Please report this bug:
    https://github.com/mxcl/homebrew/wiki/checklist-before-filing-a-new-issue
/usr/local/Library/Homebrew/formula.rb:417:in `canonical_name'
/usr/local/Library/Homebrew/formula.rb:449:in `factory'
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7:in `map'
/usr/local/Library/Contributions/examples/brew-upgrade.rb:7
/usr/local/bin/brew:47:in `require'
/usr/local/bin/brew:47:in `require?'
/usr/local/bin/brew:80

This happens because of old brew-update command. Pretty annoying, so to fix it just run the following script:

cd `brew --prefix`/Library/Contributions/examples
git clean -n
git clean -f