→ Git post-commit for profit

13 January 2008

Unless you’re on Ruby 1.8.6 (which has trouble reporting exit codes properly), you can get cheap-as-hell continuous integration with the following pre-commit script:

$ chmod 744 .git/hooks/pre-commit
$ cat .git/hooks/pre-commit 
#!/bin/sh
rake test

Cool, huh? Our buddy Git lets you decide whether a commit gets applied using the pre-commit hook. Reject a commit using an exit code of 1, accept a commit with an exit code of 0.

In Ruby:

$ cat .git/hooks/pre-commit
#!/usr/bin/env ruby
if `whoami`.strip != 'deploy'
  puts "You need to be `deploy`!"
  exit 1
else
  exit 0
end

Here’s another trick, inspired by Gitosis: have your Git post-commit scripts execute or build something for you.

For instance, let’s say you’re generating your Nginx config file from YAML. First thing’s first, you should keep that config file in a local Git repo:

$ git init
Initialized empty Git repository in .git/

Now we’ve got a cheap, versioned config file. But we can do more. Let’s actually build the nginx.conf file whenever we make a commit – that’ll force us to keep our changes in Git and offloads the building task.

$ cat .git/hooks/post-commit
#!/bin/sh
# run this from the same directory as your config.yml!
generate_nginx_config config.yml nginx.conf -y
sudo cp nginx.conf /etc/nginx.conf
sudo /etc/init.d/nginx restart
rm nginx.conf

Finally:

$ chmod 744 .git/hooks/post-commit

Making the file executable tells Git you want it to actually be run.

Of course, this isn’t limited to just config files. This here blog is just a collection of textile files and rake tasks. When I’m ready, I hit rake publish and everything is compiled ‘n’ pushed to my server. Naturally, I keep the blog under version control using Git.

I can (and did) get rid of the rake publish step by having my post-commit publish for me:

$ cat .git/hooks/post-commit 
#!/bin/sh
rake publish

It’s run as me, so there’s no issue. Okay, blog post done. Time to commit…