Hi, welcome to Word of Mike, my little corner of the internet. I am a Software/Web Developer working in North Yorkshire. I mainly write about programming but my other passion is politics so beware. (click to hide)

2015-02-27 17:46:45 UTC

Rake Tasks to Version Your Rails App

I've used git tags to store the version number of my app for a while now. It's a minor inconvenience to see what the current/last version number is, as git tag lists them alphabetically meaning that v4.5.21 comes before v4.5.4 for example, even though it's a later version. This can lead to people tagging commits wrongly, so to avoid this I wrote some a small set of rake tasks to do the versioning for me.

LEVELS = [:major, :minor, :patch]

def version
  @version ||= begin
    v = `git describe --always --tags`
    {}.tap do |h|
      h[:major], h[:minor], h[:patch], h[:rev], h[:rev_hash] = v[1..-1].split(/[.-]/)

def increment(level)
  v = version.dup
  v[level] = v[level].to_i + 1

  to_zero = LEVELS[LEVELS.index(level)+1..LEVELS.size]
  to_zero.each{ |z| v[z] = 0 }

  Rake::Task["version:set"].invoke(v[:major], v[:minor], v[:patch])

desc "Display version"
task :version do
  puts "Current version: #{`git describe --always --tags`}"

namespace :version do
  LEVELS.each do |l|
    desc "Increment #{l} version"
    task l.to_sym do increment(l.to_sym) end

  desc "Set specific major, minor and patch"
  task :set, [:major, :minor, :patch] do |_, args|
    sh "git tag v#{args[:major]}.#{args[:minor]}.#{args[:patch]} && git push --tags"


They're based on the format I use for tags which is "v<major>.<minor>.<patch>", but as you can see it's fairly simple so you can change it to suit.

You simply invoke the appropriate task from the following:

rake version:major                      # Increment major version
rake version:minor                      # Increment minor version
rake version:patch                      # Increment patch version
rake version:set[major,minor,patch]     # Set specific major, minor and patch

I will probably hook it in to Capistrano so I can set a command line option when I'm deploying which will bump the version number prior to deployment.

Update 4/9/15: I've done that Capistrano hook:

In my config/deploy.rb I've placed:

namespace :deploy do
  before :starting, :version_update do
    if !ENV['version']
      ask :version_update, "none"
      set :version_update, ENV['version']

    case fetch(:version_update)
    when "none"
    when "patch", "minor", "major"
      raise "Please choose either 'none', patch', 'minor', 'major' for version_update."

This checks for

, which you can use like so:

cap production deploy version=patch

If you don't pass anything, it will prompt you at the command line during deploy for either 'patch', 'minor', 'major', or 'none' (none is default).

Because it uses the same tasks defined above, you'll need to import them in your Capfile:

import 'lib/tasks/versioning.rake'