Happy Wednesday, everyone! I don't have very much time this week, so I'll keep this short and sweet: While we've historically used Subversion at PRX, we have recently been migrating to Git to take advantage of some awesome tools and to better interact with the community.

We're also most comfortable with Ruby, so when I was asked to look into setting up a build server for our iOS apps, there wasn't much question as to how I would do it.

I set up a bare git repository running on a spare MacBook Pro with XCode and found the commands that were necessary to run when a new build was ready to be deployed. The next step was to set up the appropriate hook for that Git repository so that the builds could be triggered by a push.

In the SVN world, this would be a post-commit hook, but because Git works differently (one push can contain many commits), the hook we are interested in is the post-receive hook. You can take a look in your .git/hooks directory for some samples, most of which are written in sh. We wanted something in ruby, and here's what we came up with:

[ruby]
#!/usr/bin/env ruby

require 'rubygems'
require 'grit'

repo = Grit::Repo.new(File.join(File.dirname(__FILE__), '..','..'))
while msg = gets
old_sha, new_sha, ref = msg.split(' ', 3)

commit = repo.commit(new_sha)

case ref
when %r{^refs/heads/(.*)$}
branch = $~[1]
if old_sha.to_i(16) == 0

# A new branch was pushed

else

# A branch was updated

end

when %r{^refs/tags/}
tag_object = Grit::GitRuby::Repository.new(repo.path).get_object_by_sha1(new_sha)
tag = tag_object.tag
tag_message = tag_object.message
if old_sha.to_i(16) == 0

# A tag was created

else

# A tag was moved

end
end
end
[/ruby]

Simply save this in your .git/hooks/post-receive file and make it executable. Then, every time you push to this remote, the script will execute. You can make whatever modifications are necessary for your specific application.

I hope this helps everyone working with Git hooks and Ruby!