Monday, January 15, 2007

Integrating Subversion with your Issue Tracking System

This article will explore a technique for integrating Subversion development with your issue tracking system. This technique was cooperatively developed by the TortoiseSVN and Subclipse development teams, and both products support the features that will be described.

Background
Many popular issue tracking systems have developed procedures for integrating with version control tools like CVS and Subversion. A common approach that is used is for the issue tracker to provide one or more Subversion hook scripts that interrogate the message provided in the commit process, looking for references to issues in the message text. Depending on the tool being used, there will often be some meta data stored within the issue tracker to record the files that were modified for that issue. Some tools support features that change the state of the issue, others might perform some kind of validation and possibly reject the commit transaction. This part is really up to the issue tracker and the hook script(s) they provide.

The problem with this approach is that it only works as well as the ability of the issue tracker's hook script to correctly identify the references to issues in the commit message text. With no help being provided by the version control tool to help the user consistently format their message, this can be a difficult task to perform accurately. Also, even when everything works correctly, the integration is only in one place, the issue tracker. In other words, you can view an issue in the issue tracker and see what files were modified (or some other reference to the version control tool), but when looking at history in the version control tool, you do not have easy access to the related issues that were addressed by the commit.

With all this in mind, these were the goals of the issue tracking specification that we developed:
  1. Provide a place in the UI of the commit dialog for the user to supply issue ID's. These issues are then inserted into the commit message in a consistent manner.



  2. Provide for the possibility of some simple validations in the UI. Such as verifying that the issue is a number, or warning if no issue is entered.


  3. When showing Subversion history in the UI, convert any references to issues in the commit message into clickable hyperlinks to the issue tracker.

You can view the full specification in the TortoiseSVN Subversion repository here. (username = guest with no password)

These features combine to give the user a better experience in terms of referencing their issue tracker from their Subversion client and also makes it much easier to write server side hook scripts that can accurately parse the commit messages. A nice aspect of this feature is that since the integration between Subversion and your issue tracker is still ultimately based on the text of the commit message, even users that are using a client that does not specifically support this feature can still participate in the integration by entering their commit messages in a format consistent with what this feature would have done for them.

Details
With all this in mind, how do you turn on this feature and/or configure it? The way that we settled on was to use Subversion properties to hold the configuration information. This allows one person to set it all up, and the configuration can then be pushed out to other users via the update and/or checkout process. In addition, the configuration just needs to be set on the top-level folder in the working copy. At runtime, the client will walk the working copy back to the root looking for the configuration. This means if you just set it on the root folder, that is enough. Keep in mind, that the client is walking the "working copy" not the "repository". If you have an environment where someone might conceivably check out at any folder level in the repository, then you might need to store this configuration as properties on every folder. Subclipse users are working in Eclipse, and Eclipse has a fairly rigid project structure. So for Eclipse users, it is pretty easy to configure as you just need to put the configuration on the project folder and you can be fairly confident that is what your users are checking out.

Once that is decided, there are then several properties all prefixed with "bugtraq" which determines the configuration of the feature. We chose bugtraq with the slightly odd spelling just to avoid any potential current or future namespace conflicts. Here are the properties and an explanation of each, this is actually copied from the spec verbatim:

NOTE: The specification has evolved a bit since it was first written and now breaks the feature down by a "basic" and "advanced" configuration where the latter is based on the use of regular expressions. Subclipse currently only supports the basic configuration options, and that is also all that this article covers.

Bugtraq Properties:

name : bugtraq:url
value : (string)

This value is the URL pointing to the bug tracking tool. The URL string should contain the substring "%BUGID%" which the client replaces with the issue number. That way the resulting URL will point directly to the correct issue.

NOTE: The URL must be properly URI encoded by the user. This URL can be used by clients to create a link to the bug tracking tool when showing the log message of a revision.

name : bugtraq:warnifnoissue
value : "true"/"yes" or "false"/"no"
If set to "true", then the clients will warn the user if the issue text box is left empty. But it must not block the commit, only give the user a chance to enter an issue number in case (s)he forgot it.

name : bugtraq:label
value : (string)
This can be used by a client as a GUI label describing the text box where the user has to enter the issue number. If this is not set, then a default value should be used, e.g. "Bug-ID / Issue-Number :". Keep in mind though that most GUI clients don't resize their windows according to the size of GUI elements. So keep the size of the label string below 20-25 chars.

name : bugtraq:message
value : (string)
If this property is set, then the client should show a text box in the commit window where the user can enter an issue number. The value string of this property is used by the client to create an additional line added to the log message. The string must contain the substring "%BUGID%"
which is replaced with the issue number the user entered before applied to the log message. The client will add the resulting string as a new line to the end of the log message the user entered:
logmessage + "\n" + resultstring

In case bugtraq:append is set to "false", then the log message is defined as resultstring + "\n" + logmessage

The client should make sure that the string doesn't have multiple lines. If more than one issue number is entered by the user (separated by commas), the client must make sure that there's no whitespace chars before and after the comma. And also the whole issue number string must be trimmed.

name : bugtraq:number
value : "true" or "false"

If this property is set to "false", then the client allows any character entered in the issue text box. Any other value or if the property is missing then only numbers are allowed as the issue number. One exception is the ',' char, which is used to separate multiple issues. The client must never complain if the text box is left empty, i.e. if no issue number is given. Not all commits are assigned to an issue!

name : bugtraq:append
value : "true" or "false"
If set to "false", then the bugtraq:message part is inserted at the top of the log message, if "yes" or not set, then it's appended to the log message at the bottom.

Since these are all Subversion properties, you need to use the svn propset command to set them on a folder within your working copy (there is no way to do it directly against the repository).
svn propset bugtraq:append false .
property 'bugtraq:append' set on '.'
You then need to commit those changes so that other users can get them. Keep in mind that in order to commit property changes to a folder, the revision of the folder in your working copy has to be the same as the HEAD revision of the folder in the repository.

Here is an example of the properties set on one of the Subclipse projects as an example:


If you refer to the previous screen shots, you can get an idea how these properties manifested in the UI of the commit dialog and the text that was inserted into the commit message.

Conclusion
This is a feature in Subclipse and TortoiseSVN that our users lobbied hard for and seem to love. I personally enjoy the easy access to issues that is created by the hyperlinks in commit messages when viewing history. Often reading the history contained within an issue is the best way to understand the context of why a particular change was made.

I do not know the complete list of Subversion clients that have added support for these properties, but I know that it goes beyond Subclipse and TortoiseSVN and includes several of the web-based repository browsers.

The Subclipse integration with Mylar includes partial support for this feature as well. When browsing history within Subclipse, the Mylar "Open Corresponding Task" option will be present and will determine the issue based on these properties and the content of the commit message. I assume this would mean if you were using Bugzilla or another issue tracker with a rich editor in Mylar that the rich editor would be opened in place of the web browser. Unfortunately the Mylar Change Set integration in Subclipse does not currently have a way to plug your issue number into the right part of the commit dialog. It does stick the URL of the issue in the commit message text, so all is not lost. Perhaps in the future it will be possible to enhance this so that the issue ID itself is populated.

10 comments:

Nik said...

What happens if you don't have a working copy to use? I'm specifically thinking of SVN::Web, which has similar functionality, enabled by the SVN::Web administrator configuring a pipeline of filters they want to run the log message through prior to display.

One of the things those filters can do is parse out bug id refs and turn them in to links. See http://jc.ngo.org.uk/svnweb/jc/revision/?rev=1292 for an example.

Is the approach just to walk back up the path, querying the remote repo for the property at each point? If so, is there an expectation that the client can cache this information for a reasonable period of time?

Mark Phippard said...

No, you are correct that there has to be a working copy. Meaning, if you are viewing history from context of the repository browser (as opposed to your working copy) in either Subclipse or TortoiseSVN, then this feature is not enabled.

The TortoiseSVN developer was against adding this because of the performance hit of walking the remote repository to discover the properties. I can't say that I disagree, especially for people using servers like tigris and SourceForge that can get slow sometimes.

Nik said...

I do not know the complete list of Subversion clients that have added support for these properties, but I know that it goes beyond Subclipse and TortoiseSVN and includes several of the web-based repository browsers.

Do you know which web-based repo browsers have adopted this? I can go and look over their code / talk to them and see what they did.

Mark Phippard said...

WebSVN definitely supports them. I think Trac does too.

Colonel Nikolai said...

so, does it work? I looked all over your blog for a download button :D.

I guess I don't understand: eclipse+subclipse+svn+somerandomhookscript? I see client support, but what about the corresponding server-side hook?

Mark Phippard said...

If you want to do something within your issue tracker you would have to write the script or get it from the issue tracker vendor.

You only need a hook if you want to store info about the commit in the issue tracker.

Chris said...

I also found that the "scmbug" tool works really well in this setup to get your commit information into Bugzilla.

Check out my posting on how I accomplished that: http://blog.platinumsolutions.com/node/102

annerose said...

These comments have been invaluable to me as is this whole site. I thank you for your comment.

free ps3 said...

Thanks for the nice post!

Rafael Sanches said...

Hey! I love the SVN integration with bugzilla. I also made a perl script that make it possible to merge into the stable branch only commits that has a bug id. That's alwesome and is the same thing as creating a separate branch just for that bug id.

http://mufumbo.wordpress.com/2008/05/10/simple-script-to-merge-commits-from-a-bugzilla-id/