high wisdom



Sat Mar 8 19:47:35 IST 2008

Git-Bugzilla integration

UPDATE: See my blog post about GitZilla - git-bugzilla integration done right. The stuff below is bitrotten and outdated now.

There's always SCMBug, but you can cook your own Git-Bugzilla integration very easily. SCMBug's fine, but it's a lot of code if all you want is simple cross-linking between Git, Bugzilla and Trac (btw - GitPlugin for Trac would throw up an error unless you have at least *two* commits in your repository - talk about undocumented easter bugs!).

Anyhoo - here's what I want :
1. Git should disallow any commit where the commit message does not have a bug number.
2. Git should add a comment to the corresponding bug on a commit, mentioning the author, the Trac changeset link, the commit message and the list of files which changed.

And here's the code to do it. First, the post-receive hook :

#!/usr/bin/perl -w
use strict;

# A hook script which integrates with bugzilla. It looks for bug IDs in
# commit messages and adds the commit message as well as a link to the
# changeset as a comment on the bug.

# This program is released under the terms of the GNU General Public License
# version 2. A copy of the license may be obtained by emailing the author,
# or at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#
# The absolute lack of warranty and other disclaimers as per the license
# apply.
#
# Copyright 2008, Devendra Gera. All rights reserved.
#
# Author : Devendra Gera 

### user configurable section

# The bugzilla has contains the server, username and password for the targeted
# bugzilla installation. There's NO 'http://' in the server line.
my $bugzilla = {
	server		=> "10.147.251.90/bugzilla",
	user		=> "demonuser",
	password	=> "daemonuserspassword",
};

# __PATH__ and __REVISION__ are replaced in $browser->{changeset} and
# $browser->{revision} to get the changeset and revision URLs respectively. 
my $browser = {
	changeset	=>
	"http://10.147.251.90/projname/changeset/__REVISION__",
	revision	=>
	"http://10.147.251.90/projname/browser/__PATH__?rev=__REVISION__",
};

# The bug_regex should extract the bug id from the commit message and place
# it in $1
my $bug_regex = 'bug #(\d+)';


##### End user configurable section

use WWW::Bugzilla;

my $input = <>;
chomp $input;

my ($oldrev, $newrev, $refname) = split /\s+/, $input;
my $commit_msg = `git-whatchanged $oldrev..$newrev`;

# prepare the changeset URL
my $changeset_url = $browser->{ changeset };
$changeset_url =~ s/__REVISION__/$newrev/g;

# author
my ($author) = ( $commit_msg =~ /^Author:\s+(.*)$/m );

# files
my @filelist = grep ( /^:/, split( /\n/, $commit_msg ) );

# prepare comment
$commit_msg =~ s/^.*?Date://s;	# eat everything till the Date: heder
$commit_msg =~ s/^.*?\n//m;	# eat the date line completely
$commit_msg =~ s/^:.*?$//mg;	# eat the file list from the msg.
chomp $commit_msg;
my ($bug_number) = ( $commit_msg =~ /$bug_regex/ );

my $comment = <<END_COMMENT;

------------------------------------
changeset $newrev [ $changeset_url ]
    by $author :

$commit_msg
------------------------------------

Files changed :
END_COMMENT

$comment .= join("", @filelist) . "\n";

my $bz = WWW::Bugzilla->new(
	server		=> $bugzilla->{ server },
	email		=> $bugzilla->{ user },
	password	=> $bugzilla->{ password },
	bug_number	=> $bug_number
);

die "cannot connect to bugzilla" unless defined $bz;

$bz->additional_comments( $comment );

$bz->commit;

And here's the update hook :

#!/usr/bin/perl -w
use strict;

my $refname = shift;
my $oldrev = shift;
my $newrev = shift;

my $commit_msg = `git-whatchanged $oldrev..$newrev`;

# check if the commit message contains a bug number
if($commit_msg !~ /bug #\d+/) {
	exit -1;
}

exit 0;

The TODO :
1. Push every configurable thing to git's config file and access it via git-config.
2. Code cleanups. One definition of the bug regex (which is hardcoded in the update for now).

edit : the here doc in the code was causing a problem with formatting, eating up some of the code. Fixed now.


Posted by gera | Permanent link | File under: tricks, perl, code, hacks | [ 7 ]