Gitlab + Custom Hooks

With Gitlab (also with Github) it is straight forward to add post-receive web-hooks so actions can be taken after a push event. At the difference of Github, Gitlab is normally self-hosted, which could technically lead to interesting possibilities with custom post-receive (or any other) hooks. Unfortunately it is not possible to add custom-hooks directly from the web interface, it needs to be done under the hood.

Gitlab relies on Gitolite for it’s authorization process, we will make it relies on Gitolite also for git hooks’ management. We will stick to the Gitolite way of decuplating hooks based on the doc, in the section hook chaining

How to make Gitlab custom hooks aware ?

Remember during Gitlab’s installation the following step – copying Gitlab custom post-receive hook to Gitolite hooks directory :

cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive

In order to make Gitlab custom post-receive hook aware, you need to edit the /home/git/.gitolite/hooks/common/post-receive file so it looks like this :

#!/usr/bin/env bash

# This file was placed here by GitLab. It makes sure that your pushed commits
# will be processed properly.

while read oldrev newrev ref
do
  path_to_hook='/home/git/.gitolite/hooks/common/post-receive.secondary.d/'
  pwd=`pwd`
  reponame=`basename "$pwd" | sed s/\.git$//`
  env -i redis-cli rpush "resque:gitlab:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$reponame\",\"$oldrev\",\"$newrev\",\"$ref\",\"$GL_USER\"]}" > /dev/null 2>&1
  if [ -x "$path_to_hook/$reponame" ];then
    "$path_to_hook/$reponame" "$reponame" "$oldrev" "$newrev" "$ref" "$GL_USER"
  fi
done

How does it work ?

Explanation of the file difference with previous version

  • Line 8 : indicates the directory where the post-receive hooks will be stored
  • Line 12-14 : if a post-receive hook exists for this project execute it

In practice

In practice there will be one post-receive hook per project and the hook should be named after the project. (Do not forget to make it executable)

And that’s about it, from now on every time you will be pushing your project in Gitlab, it will execute the post-receive script located in $path_to_hook and named after the project itself.

Tests

Project name : customhooks
Post-Receive Hook: location is /home/git/.gitolite/hooks/common/post-receive.secondary.d/customhooks

#!/bin/sh

GIT_WORK_TREE=/var/www/blog git checkout -f

Note : the post-receive scripts can be written in any script-able language be it Shell, Ruby, Python, Perl, etc…

After pushing the customhooks project, I will have a copy of my actual project in the directory /var/www/blog . It’s up to you now to have hooks as sophisticated as your needs requires it.

Conclusion

This post shows how to do it specifically for the post-receive hook, but the same logic can be applied to the other available hooks. Remember, Gitolite manages them not Gitlab directly.
Even if genuinely Gitlab does not give you the possibility to add custom hooks, it is an easy feature to add. QED