Google code issue tracker integration with version control using git commit template

I’m using google code for one of my open source project. And I think it is definitively a good code site.

All open source community code site have its pros and cons (I’ve tried a lot of them sourceforge, github, jboss.org, google code etc), and every one have some beautiful unique feature. But one of my most loved feature is definitively google code’s integration of issue tracker and version control. In a nutshell it permit to create, update and close issues just adding some keyword on your commit.

It’s great in general, but it’s really amazing if you are using a distributed Version Control. And I’m using git for local repository and git-svn to synchronize it with central subversion repository.
Imagine this situation: you are working with your laptop off-line (i.e into an air plane where also GSM connection isn’t available) and you find a bug or you have an idea for an enhancement. What do you do in this case? Of course take care of the bugged code, fix it, write a test for that and then commit it into your git local repository. What is the missing step in this work flow? Of course create an issue into your issue tracker system to keep community up to date, and don’t forget it if you can’t completely finish it now. At this point come very useful the google code feature permitting you to create, update, or fix an issue when you are committing a change.

There is only one problem with this integration: remember the structure the commit message have to fit and all (or at least the most useful) values you can assign to various fields. I’ve solved this problem creating 3 template for the commit messages and I use them with git. Using template during a git commit is very easy: just make a commit like this

git commit -a -t tempalteFile

Git will Use the contents of the given file as the initial version of the commit message. The editor is invoked and you can make subsequent changes. If a message is specified using the -m or -F options, this option has no effect.

Here you have my 3 template file:

NewIssue.tmpl

#commit comment here

#next line doesn't need any number. ssue number will be automaticaly assigned after commit
New issue
#A summary is always needed. Please complete next line
Summary:
#Uncomment the rigt Status
#Status: Accepted
#Status: Fixed
#Status: New
#Uncommet right Labels and/or add labels to the list (comma or space separate)
#Labels: Type-Defect Priority-Medium
#Labels: Type-Defect Priority-High
#Labels: Type-Defect Priority-Critical
#Labels: Type-Enhancement Priority-Medium
#Labels: Type-Enhancement Priority-Low
#Labels: Type-Enhancement Priority-High

#Comment text for the issue tracker goes here

UpdateIssue.tmpl

#commit comment here

#Complete next line with issue number
Update issue
#summary is rarely updated. If you need that uncomment and complete next line
#Summary:
#Uncomment the new Status you would get your issue. No uncomment status will keep the previous status
#Status: Accepted
#Status: Fixed
#Status: New
#Uncommet Labels and/or add labels to the list (comma or space separate) if you want update/add Labels
#Labels: Type-Defect Priority-Medium
#Labels: Type-Defect Priority-High
#Labels: Type-Defect Priority-Critical
#Labels: Type-Enhancement Priority-Medium
#Labels: Type-Enhancement Priority-Low
#Labels: Type-Enhancement Priority-High

#Comment text for the issue tracker goes here

FixIssue.tmpl

#commit comment here

#Complete next line with issue number
Fixes issue

#Comment text for the issue tracker goes here

The same thing should be possible also with svn and other SCM.

Hoping it could help some other people enjoying this google code feature developing open source code during their trips :)

Have fun!

Writing an irc bot for svn commit notification

Recently I’ve started working with a new team. Since we are based in 2 different site a bit far each other we are using extensively an IRC channel to communicate.

We are using subversion as SCM and we need to keep all members of the team up to date about svn commits. The solution I’ve put in place during an insomniac night in an hotel is a post-commit hook invoking an irc bot script written in perl connecting to the server and shotting a message there. Quite simple, and it is taking its goal.

In $SVN_REPOSITORY/hooks edit and make executable the file post-commit

#!/bin/sh

REPOS="$1"
TXN="$2"
SVNLOOK=/usr/bin/svnlook

# get last commit message
COMMIT=`$SVNLOOK log "$REPOS"`
USER=`whoami`

# call bot with arguments reposname, revison and commit message in one string
/usr/bin/perl /usr/local/bin/svn_irc_bot.pl "$USER $REPOS r$TXN: $COMMIT"

# all checks passed, so allow the commit
exit 0

then edit and make executable the file /usr/local/bin/svn_irc_bot.pl

#!/usr/bin/perl -w
#svn_irc_bot.pl

my $server = ""; #put here your address
my $port = 6667;
my $nick = "svn_bot";
my $ident = "svn_bot";
my $realname = "svn_bot";
my $chan = "#YourChannel";#put here your channel name
my $pass = "svn_bot";
my $svn_commit = $ARGV[0];
use IO::Socket;

my $irc=IO::Socket::INET->new(
PeerAddr=>$server,
PeerPort=>$port,
Proto=>'tcp') or die "DEAD!";

#print $irc "USER $ident $ident $ident $ident :$realname\n";
print $irc "NICK $nick\r\n";
#print $irc "PRIVMSG nickserv/@/services.dal.net :identify $pass\n";
print $irc "USER $ident 8 * :P erl IRC Hacks Robot\r\n";

print $irc "join $chan\n";

while(my $in = <$irc>)
{
if($in=~/004/)
{
print $irc "PRIVMSG $chan :$svn_commit \n";
last;
}

if($in=~/^PING(.*)$/i)
{
print $irc "PONG :$1\n";
}
}
close($irc);
#EOF

If user named “fooUser” make a commit on “fooRepository” for release 409 with a comment like “this is a fooComment” on irc channel you will get something like:

<svn_bot> fooUser fooRepository r409: this is a fooComment

I took the base of code here. Then I’ve modified it a little to get result I like.

Subversion branching in my experience

In my working life I have lead teams developing some big projects and products. In all these development we had to control versions, releases, some QA dedicated version and so on.

Of course we used SCM for these stuffs, and I focused ,as usual for me, on open source solutions. So I started to use cvs a lot of year ago, and more recently (exactly since Jan 2004) subversion. As in all big projects I needed to track code for different development line and product releases, and use of branches have been quite natural (especially in svn world) achieving these goals.

In my career I have been lucky working with great developers, but we have needed to find an agreement about the use of branches (and tags) in our SCM, because they can easily become a nightmare if leaved out of control and convention. Moreover, it’s a matter of fact that SCM is easy to understand and use, but a correct use of branches and tags may be something which most developers don’t understand and use them without worries.

Some months ago I wrote 2 documents to cover 2 different needs: the first is an introduction to branching and tagging in general and in our environment for new hired people, the second is a checklist of operation needed in branching a project, respecting our “svn pattern”. Both documents was in italian language, but they need a review with minor adaptation of our newest best practice in these days, and so I decided to translate and generalize it to make it public. Originally our document describe svn pattern strictly coupled to jira, fisheye and hudson practice we are using, I tried to decouple them, to make this post easy to read for atlassian/hudson non-believer. If someone is interested I can describe in another post how we are using these tools in our environment. Just let me know by comments or by email.

Ok, stop describing background and go with documents: The first is this post itself, the second is attached here as pdf and txt, since I think it’s more useful in that format used as checklist.

Let’s start describing what is a branch and a tag in svn: branches and tags in subversion just a copy of sources. Branches is for convention a copy where teams do parallel development, tags is for convention a read only copy (and only for convention in svn), to store a copy of code in a particular stage of development (they are for convention not modifiable). How do you create a branch or a tag? Of course, being them just copies, with copy (or move) command. Let’s see the command (here and in the rest of post, I make an example of the most common use, at least for us, of the command…take a look to the “svn help <command>” and the good svn online manual for more detail

svn copy SRC DEST

Our normal convention used in svn is to create 2 directories on repository called branches and tags where you have to copy them. So for example, we can create a branch called “Experiment1″ with this command:

svn copy $REPO_PATH/trunk $REPO_PATH/branches/Experiment1

But how are we using branches? Well we are using 2 different kind of branching, with totally different goals: STABLE branches, used for stable product release maintenance, and personal branches, used for experimental code and/or for agile parallel development.

In this figure I sketched our repository layout. As you can see we have a current development line on trunk and we branch starting from there for e different reasons:

1) starting a new parallel personal development (red), which will be described in detail later in this post.

2) Create a branch for a stable release (green), which need maintenance. When the version reach the end of supported life we migrate the branch on a tag to keep “legacy” code with it’s story somewhere. This approach permit us to always have clean code for any version maintained, where investigate for bugs and stack trace reported by customers.

But where have we to fix a bug? In all branches having the same code? Of course here subversion merging help us a lot.

When we find a bug we correct it on trunk whenever it is possible and then merge the correction (backport in our slang) on all active branches. When the bugs can’t be corrected on trunk (i.e because the buggy code don’t exist in trunk anymore) we fix it on the newest branch available and then backport it on older code.

What we are doing here is in fact a single commit management and merging. It give us an high level of confidence on what we are doing on stable releases, especially used together with Jira, unit tests and hudson.

We always have a person or a team responsible of maintenance of a version, and it’s up to her (or them) to decide what bugs need backporst and it’s up to her (or them) to manage this merge:

cd branch_workingCopy_dirsvn merge –dry-run -r N-1:N $REPO/branches/$BRANCH_NAMEsvn merge -r N-1:N $REPO/branches/$BRANCH_NAME
svn commit -m”JARA-YYY: back porting of commit N, fixing JIRA-XXX”

We use svn also to make parallel development on the same project. Similar approach is described in detail in a lot of article of agile development (1,2). I don’t know, and I don’t care, if we are totally agile compliant, but we use the same idea to create personal branches, and commit on them all works around big Jira tasks.

Our idea is that our trunk have to be clean, buildable and with all test passing (and hudson verify this condition at every commit). Ideally trunk would be releasable at any moment, or at least can receive patch to be backported. But, of course, there are some bug issues and development to be done that can’t be developed in few hours by a single developer on her laptop (buildable, tests passing, feature complete and stable). But of course we needs to have new code somewhere making possible to an heterogeneous team to work on and to be available to all team members at any time. So the solution is to have parallel “personal” branches.

Personal branches is totally different from release ones described above, since they don’t die at some stage, but they have to be merged on trunk, applying to trunk all changes developed and tested in branch. But sometimes this development phase may take some time (in particular for experimental code development), and trunk may change a lot during this time. For this reason merging back a branch on a trunk which have changed a lot could easily become pain, with a lot of difficult to resolve conflict.

Our solution have been to keep personal branches updated, merging frequently from trunk and resolving day by day conflicts, and a final “publish” action reporting all changed code in branch into trunk. Few conflict at a time, and on a well known code base is much more easy to understand and to resolve.
But isn’t difficult to keep track of which revision is already merged on branch? (IOW a lot of merge, means keeping track of merge operations?).
It was true (even not impossible, we always kept track of them with a text file) before subversion 1.4, which includes a command “svnmerge to keep track of merges (it’s in fact a contribution, downloadable also for early versions as svnmerge.py)

What does it for you? It keep track of merges from trunk to branch (using properties on branch) and make much more easy merging in this direction. Theoretically it would also help you also merging back in other direction, but we don’t use it for this operation, since “traditional” merge does a good job in this final “pubblication” operation. There are commands we use to make these operations, refer to previous figure to better uinderstand what we are doing:

CREATE A PERSONAL BRANCH

svn copy $REPO/trunk $REPO/branches/$BRANCH_NAME -m”created branch”
svn co $REPO/branches/$BRANCH_NAME branch_workingCopy_dir
cd branch_workingCopy_dir
svnmerge init
svn commit -m”svnmerge initialized”

MERGING FROM TRUNK TO PERSONAL BRANCH (FREQUENTELLY)

cd branch_workingCopy_dir
svnmerge merge
svn commit -m”merged trunk to branch”

MERGING INTO TRUNK FROM PERSONAL BRANCH

cd branch_workingCopy_dir
svnmerge merge
svn commit -m”last merge of trunk to branch”
remove property used to track merges
svnmerge uninit
svn commit -m”svnmerge uninit”
cd trunk_workingCopy_dir
svn update

(get the revison number….suppose 346)
svn merge –dry-run $REPO/trunk@346 $REPO/branches/$BRANCH_NAME@346
svn merge $REPO/trunk@346 $REPO/branches/$BRANCH_NAME@346
svn commit -m”reported changes from $BRANCH_NAME trunk”
svn delete $REPO/branches/$BRANCH_NAME@346

That’s all. Just one more advice………

Last, but not least, merging works on difference, so don’t forget to ensure that difference are real changes on code, and not simple formatting!!!

Use of some tools to format code automatically at some time is more than useful: eclipse at save file defining a code style formatter profile, jalopy used in ant or in maven or what else you can figure out, but please don’t leave it to developers, use an automatic tool! Of course it’s just my humble opinion, but to many times I have been in pain merging code (and mainly understanding difference on fisheye) with stupid formatting problems!

Hoping they would be useful for use here you have our checklist document in txt and pdf formats.

Have fun!