Hookie

Hookie is a pluggable framework for creating git hooks using Ruby. It was originally designed for writing hooks for gitolite, but should work for any hooks, including local ones.

Build Status

Background

After we had setup HipChat at our organisation I wanted to get notifications from gitolite pushes pushed to HipChat. I found the gitolite-hipchat-notification project, and forked it and cleaned it up a bit for my purposes. However this script wasn't very flexible in that you needed to add it individually to each repo (or suffer with a single config). Then I wanted to add Jenkins build notifications as well, so had to enhance the script to support running multiple tasks. Eventually it was all getting too crufty and so Hookie was born!

Hookie is designed so that you can have multiple actions take place as a result of a git hook (usually post-receive), these actions are built as plugins, and configured via git - the beauty of this is that for gitolite you define the hook globally and then configure which plugins run where via git config keys, which can be defined in your gitolite-admin repository. So once Hookie is setup you don't need to make changes on the server.

Hookie includes those aforementioned plugins for HipChat and Jenkins in the base build.

In addition there is now a FishEye plugin (as of v1.0.1)

Acknowledgements

Hookie is built on the base of @peplin's gitolite-hipchat-notification project, which was originally forked from gitolite-campfire-notification - the magic of Open Source!

Hookie uses grit for accessing information in git repositories.

Installation

Install the gem on your git server

gem install hookie

You then need to create a post-receive script in your repository's hooks directory, there are a couple of ways to do this, see below for some options. The post-receive hook will look like this:

#!/usr/bin/env ruby
require 'hookie'

# Add your plugins here
# require 'my_plugin'

Hookie::Framework.hook "post_receive"

NOTE the above doesn't work if your gitolite user is using RVM as the gitolite shell won't have loaded RVM. The alternative hook script looks like this:

#!/bin/bash
source ~/.rvm/scripts/rvm
ruby -rhookie -e 'Hookie::Framework.hook "post_receive"'

If you need to add your own custom plugins then add them with additional -r arguments (require)

Installing hooks with gitolite

The idea is that you install hookie as a post_receive hook for all your repositories, but configuration determines when the hook is actually run. To install for all repositories you create the post-receive script in the .gitolite/hooks/common/ directory. Make sure the script is exectuable.

Installing hooks manually

You can also install Hookie hooks manually, by adding them to the hooks directory within your repository. Note that the same configuration still applies. You should also be able to install Hookie for local repository hooks, but I haven't tried this yet! Currently Hookie assumes it will be receiving changeset information on STDIN in the format gitolite provides it, I'm not sure if other git servers and/or local hooks also receive information the same way?

Configuration

NOTE for gitolite you will need to make the following change to .gitolite.rc or your config keys won't work!

GIT_CONFIG_KEYS             =>  'hookie\..*',

Hookie was written such that it can be configured using Gitolite's ability to set git config keys via the gitolite-admin repository.

You can set "global" config keys using the special repository @all in gitolite, and override or set project specific keys within the repository itself. This makes it easy to, for example, set your HipChat API key for all repos, but then set the room that gets notified in each repo separately - and this can all be done via the gitolite-admin repository, without requiring access to the git server.

An example conf/gitolite.conf:

repo gitolite-admin
    RW+     =   marcin

repo testing
    RW+     =   @all
    config hookie.core.allowedplugins = hipchat,jenkins,fisheye
    config hookie.hipchat.room = 123456
    config hookie.jenkins.url = http://jenkins.example.com/job/Test%20Job/build?token=test
    config hookie.jenkins.branches=develop
    config hookie.jenkins.auth=jenkins:TOKEN

repo @all
    config hookie.hipchat.apikey = APIKEY
    config hookie.hipchat.from = "Git Test"
    config hookie.core.web.commit = https://fisheye.example.com/changelog/%REPO%?cs=%COMMIT%
    config hookie.core.web.browse = https://fisheye.example.com/browse/%REPO%
    config hookie.fisheye.apikey = APIKEY
    config hookie.fisheye.url = https://fisheye.example.com/rest-service-fecru/admin/repositories-v1/%REPO%/scan

The following core keys are used by the framework:

  • hookie.core.allowedplugins - comma separated list of plugins that are run for this repo - by default NO plugins get run.
  • hookie.core.repo.name - set the name of the repository used when generating URLs or for display purposes. Normally it can be determined from the path and the key isn't required
  • hookie.core.web.browse - URL to a web based repo browser. The special variable %REPO% will be replaced with the repo name.
  • hookie.core.web.commit - URL to a web based view of a single commit. The special variables %REPO% and %COMMIT% will be replaced with the repo name and commit id respectively.
  • hookie.core.web.proxy - optional proxy to use when making HTTP calls in plugins (example syntax: "proxy.example.com:8080")

Plugins

The following plugins are shipped with Hookie:

  • HipChat - posts a notification to a HipChat room in response to a commit
  • Jenkins - triggers a Jenkins build in reponse to a commit
  • FishEye - triggers a scan of a FishEye repository in response to a commit

HipChat

The following config keys apply to the HipChat plugin:

  • hookie.hipchat.apikey - your HipChat API key
  • hookie.hipchat.room - the HipChat room to post your message to - you can get a list of rooms using the following API call: http://api.hipchat.com/v1/rooms/list?auth_token=YOUR_TOKEN
  • hookie.hipchat.from - who the notification appears from (default: git)
  • hookie.hipchat.notify - set to 1 to trigger a notification (default: 0)

Jenkins

The following config keys apply to the Jenkins plugin:

  • hookie.jenkins.url - the trigger URL to be called for this repostiory (you should set this per-repository)
  • hookie.jenkins.branches - only trigger a build if the change set includes commits to the branches in this list. Comma separated. Default is to build for any commit.
  • hookie.jenkins.auth - the username:token combo to use to authenticate with Jenkins

FishEye

The following config keys apply to the Fisheye plugin:

  • hookie.fisheye.url - the FishEye REST API URL (see the FishEye docs for where to find this URL). You should use the placeholder %REPO% which will be replaced with the repo name
  • hookie.fisheye.apikey - the FishEye REST API Key (see the FishEye docs for where to obtain this token)

Writing Plugins

Hookie was designed to be extensible by writing your own plugins.

A minimal plugin is:

require 'hookie/plugins/base_plugin'

module Hookie
  module Plugin
    class EmptyPlugin < BasePlugin
      def post_receive
        log "Empty Plugin - post_receive"
      end
    end
  end
end

BasePlugin provides useful instance variables such as config and framework.config is a symbol keyed hash of your plugins config. By convention your config key is the lowercased first part of your plugin name (eg. EmptyPlugin -> empty), so config keys are, for example, hookie.empty.blah

Your plugin will be called if it has a method matching the name of the hook being run (eg. "post_receive" above). See the HipChat and Jenkins plugins for vaguely more complex examples.