• Home
  • Blog
  • Git commit hook to bugzilla using git-notifier

Git commit hook to bugzilla using git-notifier

Vincent Danen

September 21, 2012

I'm a big fan of the git-notifier script, which acts as a hook in git to send you nice emails about things that have changed in your git repos. I'm also a bugzilla user, so I wanted to be able to put git commit notifications, automatically, in bugzilla if "bug #X" is in the commit log. Initially I was intending to use gitzilla for this, but I didn't feel like attempting to make it work with the latest release of pybugz (says it is tested with version 0.8.0 but the current version is 0.10.1. In retrospect, that might have actually been easier. =)

Anyways, I decided to use git-notifier to send an email to bugzilla (while gitzilla uses XMLRPC, which would have been preferable, I also have incoming email support enabled in bugzilla). It took some trial and error, but I got it working (although I suspect there are easier ways to do it).

The first thing I had to do was patch git-notifier to accept a bug id, because bugzilla needs to know what bug to route the incoming email to. This was very easy to do (I'll be sending this upstream to see if they want to include it, but I may also change it to pull more info from the git config so that the post-receive hook doesn't have to be so obscene:

--- git-notifier.orig   2012-09-21 10:04:21.283442085 -0600
+++ git-notifier    2012-09-21 10:25:04.811307023 -0600
@@ -37,6 +37,7 @@
     ("link", True, None, "Link to insert into mail, %s will be replaced with revision"),
     ("updateonly", False, False, "update state file only, no mails"),
     ("users", True, None, "location of a user-to-email mapping file"),
+    ("bug_id", True, False, "bug ID (for sending email to bugzilla)"),
     ]

 class State:
@@ -250,6 +251,11 @@

     repo = Config.repouri

+    if Config.bug_id:
+        bzid = "@bug_id = %s\n\n" % Config.bug_id
+    else:
+        bzid = ""
+
     if not repo:

         if gitolite:
@@ -269,10 +275,10 @@
 X-Git-Repository: %s
 X-Mailer: %s %s

-%s
+%s%s

 """ % (Config.sender, Config.mailinglist, Config.emailprefix, subject, repo,
-       Name, Version, mailTag("Repository", repo)),
+       Name, Version, bzid, mailTag("Repository", repo)),

     return (out, fname)

This works, and works well, but the post-receive hook is messy. What used to just be:

#!/bin/sh
/srv/git/hooks/git-notifier [email protected] --link="http://[url];a=commitdiff;h=%s" \
  --emailprefix="[git: [repo]]"

Has now turned into this monstrosity:

#!/bin/sh
while read oldrev newrev refname
do
    commit=$(git rev-parse $newrev)
done

bzemail="[email protected]"

/srv/git/hooks/git-notifier [email protected] --link="http://[url];a=commitdiff;h=%s" \
  --emailprefix="[git: [repo]]"

for BUG in $(git log ${commit} -n 1 | sed 's/bug #/bug#/g' | \
  egrep -i -o 'bug#[0-9]*'); do
    BUGID=$(echo "${BUG}" | sed 's/bug#//i')
    EMAIL=$(git log ${commit} -n 1 --pretty=format:"%ae")
    test=$(echo "$BUGID" | sed 's/[0-9]*//g')
    if [ "${test}x" = "x" ]; then
    # make sure it is a digit
        /srv/git/hooks/git-notifier [email protected] --link="http://[url];a=commitdiff;h=%s" \
  --emailprefix="[git: [repo]]" --bug_id=${BUGID} --mailinglist=${bzemail} \
  --sender=${EMAIL} --manual=${commit}
    fi
done

(lines wrapped for readability)

So while it's fugly, there's quite a bit of magic to it. Seems that when you call git-notifier again, it won't send an email because it knows it's already been sent, which is why we need the commit hash, and feed it to it with the --manual option. The --mailinglist option is used to point to bugzilla (again, the git-notifier config is pointing to another email address to receive the commits already, so we need to override it). The --sender option takes the committer's email address as the value (the $EMAIL variable), which also overrides the default git-notifier sender (which is the local user on the system unless you're using gitolite (which I'm not)). The --bug_id is a digit to reference the bug in the commit (this should also send multiple mails if more than one bug is referenced in the commit, but I've not tested that yet). The end result is you get a copy of the git commit directly into bugzilla, in the same format that you would get it via email.

I may spend some time later on trying to make gitzilla play nicely with the newer version of pybugz, but for now this scratches my itch. Like I said, not the prettiest solution, but it works as a quick-n-dirty hack. The inspiration for using email to send this to bugzilla was from Gentoo's Bugzilla Email wiki entry (the subversion integration part in particular).

Note that since the email is being sent as the committer, the committer needs to have an account with that email address in your bugzilla. If not, bugzilla's email_in.pl will bounce it back. So you may want to have a bugzilla "commits" account as a dummy account from which you can email these things if not all of your committers have bugzilla access or use the same email address in bugzilla that they do in git.

If anyone has any suggestions on a better way to do this (particularly via XMLRPC which I think would be a nicer way to go), I'm all ears. (Short of writing my own -- I could do this, having worked with bugzilla and lately with XMLRPC access, quite a bit -- I'm too lazy to write something from scratch)

Leave a Comment

Comments use MarkDown. Need help? MarkDown Cheatsheet