edubkendo
5/12/2013 - 8:14 PM

README.md

#!/usr/bin/env ruby

require 'erb'
require 'yaml'
require 'pp'

lines = %x{git diff-index --cached --name-only HEAD}.split(/[\r\n]+/)

ENV['RAILS_ENV'] = 'test'

lines.each do |file|
  if File.exists?(file) and file =~ /\.(rb|rake|god)$/
    print "[SYNTAX] #{file} - "
    ret = system("ruby -c '#{file}'")
    exit 1 unless ret

    if file =~ /_test\.rb$/
      print "[UNIT  ] #{file} - "
      unitcmd = "ruby -Ilib:test #{file}"
      unitcmd = "bundle exec #{unitcmd}" if File.exists?('Gemfile')
      ret = system(unitcmd)
      exit 1 unless ret
    end

    if file =~ /_spec\.rb$/
      print "[SPEC  ] #{file} - "
      rspeccmd = "rspec #{file}"
      rspeccmd = "bundle exec #{rspeccmd}" if File.exists?('Gemfile')
      ret = system(rspeccmd)
      exit 1 unless ret
    end
  end

  if File.exists?(file) and File.basename(file) =~ /^(Capfile|Gemfile|Guardfile|Rakefile|config.ru)$/
    print "[SYNTAX] #{file} - "
    ret = system("ruby -c '#{file}'")
    exit 1 unless ret
  end

  if File.exists?(file) and file =~ /\.feature$/
    print "[ (::) ] #{file} - "
    ENV['CUCUMBER_FORMAT'] = 'progress'
    cuccmd = "cucumber #{file}"
    cuccmd = "bundle exec #{cuccmd}" if File.exists?('Gemfile')
    ret = system(cuccmd)
    exit 1 unless ret
  end

  if File.exists?(file) and file =~ /\.(yml|yaml)$/
    print "[SYNTAX] #{file} - "
    begin
      # Load with erb to avoid problems with cucumber's yml
      erb = ERB.new(IO.read(file)).result(binding)
      yaml = YAML.load(erb)
      puts "Syntax OK"
    rescue SyntaxError => ex
      puts ex.message
      exit 1
    rescue ArgumentError => ex
      puts ex.message
      exit 1
    end
  end
end

Git pre-commit hook for Ruby on Rails

This pre-commit hook is checks the files being committed to fits two rules:

  • No syntax error (both for Ruby and YAML files)
  • If this is an TestUnit, Cucumber, or RSpec test, it should pass

TODO

  • Add checks for XML files
  • Add checks for deep checks for .rb files
  • Make it configurable from project's code