Monthly Archives: November 2006

Integrating Mantis and Subversion #

Do you want to know how to integrate Mantis and SVN? I did, but could never manage the right Google query to return a page written for someone unfamiliar with customizing Mantis. (I’m still learning SVN too.) This is the documentation I wish I’d had. This process is easier if you know Bash or some other scripting language. This was accomplished using Mantis 1.0.0rc2. An older version may not work with these instructions.

Introducing Subversion (SVN) Hooks

Subversion allows for custom scripts to be called when it performs certain actions on a repository. Browse to your repository. The server-side one, not your working copy. In /path/to/svn/repository_name/hooks you will see a list of sample scripts for the five actions subversion recognizes.

start-commit
Run before the commit transaction is created. May be used to stop the transaction and return error messages to clients.
pre-commit
Run when the transaction is complete, but before it is committed. It can be used to require comments to include a bug tracker ticket number, or enforce fine-grained access to parts of the repository. It can cause the transaction to rollback and return error messages to clients.
post-commit
Run after the transaction is committed, and a new revision is created. Often used to send notification emails or trigger repository backups. Errors from this hook are ignored Subversion comes with some scripts for common actions. Read the manual for more details.
pre-revprop-change
Revision properties such as log messages aren’t versioned. If you were to go back and change a log message, for example, the old one would be lost. This hook, and its post- counterpart, offer a chance to reject or log the change.
post-revprop-change
Run after revision properties are changed. There are some security restrictions built in, be sure to read the manual.

Well, that sounds simple. All we have to do is write a script that will log into our bug tracking system and insert a comment on the appropriate ticket. That sounds easy enough, but let’s not make things too complicated. With a few minor customizations, Mantis will do most of the work for us.

Customizing Mantis

The manual for Mantis has two relevant pages. One, titled “Source Control Integration”, provides a list of customizable settings, but offers no directions on where these settings are most appropriately accessed. The other, “CVS integration”, is not terribly helpful either, but it does provide another piece of our puzzle—it tells us there is a command line PHP script included with Mantis that accepts a version control (e.g. SVN, CVS) log message via stdin, and adds comments to any tickets as appropriate.

First things first. Create a new user in Mantis. This is the account the script will use. I called mine “svn”. Make sure the user has permission to add comments and resolve tickets. Don’t forget to add it to your project(s).

Open up /path/to/mantis/config_inc.php. If it doesn’t exist, create it. (If it doesn’t exist, you didn’t follow the installation directions.) This file is used to override default settings. It’s not distributed as part of Mantis, so when you upgrade, it won’t be overwritten. This is where you should have your database connection information, and where you would override the default colors, status/severity options, or any number of configurable settings.

Add the following lines to /path/to/mantis/config_inc.php:

$g_source_control_account = 'svn';
$g_source_control_regexp = '/\b(?:bug|issue)\s*[#]{0,1}(\d+)\b/i';

What does it all mean? (Some credit is due Digitalpeer for helping me through this. I found it just as I was getting the integration working. It would have saved some time.)

$g_source_control_account
This is the user we created in Mantis.
$g_source_control_regexp
This is the regular expression Mantis will match against the log message. This is an optional setting; the default is /\bissue [#]{0,1}(\d+)\b/i.

Using a custom RegExp

You’ll notice I defined a regular expression different from the default. I wanted to not only match the string “issue #1337”, but to be a bit more liberal, matching the phrase “bug #1337” too. For those of you savy enough to craft your own expressions, the first capturable group must be the bug number, or the script won’t work. (This is hard-coded into Mantis.) Hence the non-capturing group (?:bug|issue).

Automatically closing tickets

These custom settings lay the groundwork for Mantis to automatically add comments to tickets based on SVN log messages. There are additional settings we can use to get Mantis to resolve tickets automatically too, based on a different regular expression. To enable this behavior, add the following lines to /path/to/mantis/config_inc.php:

$g_source_control_set_status_to = RESOLVED;
$g_source_control_set_resolution_to = FIXED;
$g_source_control_fixed_regexp = '/\bfix(?:ed|es)\s+(?:bug|issue)?\s*[#]{0,1}(\d+)\b/i';

$g_source_control_set_status_to
The status to set the ticket to. Use CLOSED if you prefer.
$g_source_control_set_resolution_to
The resolution attached to the ticket. There are constants defined for each built-in resolution. You may use a different one, but FIXED makes the most sense.
$g_source_control_fixed_regexp
This is an undocumented setting. The default is to be equal to $g_source_control_regexp, but I only wanted certain tickets to be automatically closed, so I used a different regular expression. My expression matches “fixes issue #1337”, “fix bug #1337”, or simply “fixed #1337”. (Plus several iterations on those words.) The ticket number must be the first captured group. Altering the expression to also accept the words “solved” and “solves” is left as an exercise for the reader.

Testing Mantis

Before we go further, let’s make sure we implemented the Mantis settings properly. Run the following from the command line (alter the paths, of course)
%> /path/to/php /path/to/mantis/core/checkin.php <<< "My web monkey fixed issue #1337 by accident."

If you’ve configured Mantis correctly, there should be a new comment on ticket #1337.

Connecting the pieces

Now that we have Mantis set to accept log messages from our version control system, we need to connect Subversion to it. Remember the hooks from the beginning of this article? We’re going to write one. I used Bash script. (Be nice, I’m still learning Bash.)

Save the following file to /path/to/svn/hooks/post-commit (no file extension):

#!/bin/bash
 
REPOS="$1"
REV="$2"
 
log=$(svnlook log -r $REV $REPOS)
 
/usr/bin/php -q /var/bugtracker/core/checkin.php <<< "$log"

What is svnlook?

The program svnlook is distributed as part of Subversion. Given a revision and repository path as parameters, it will return various properties of the revision, such as the author or which files were changed. In this case we’re asking only for the log message.

Permissions

Give the file permission to executable by your repository. This will be slightly different for each setup, but something similar to the following should do the trick:

%> cd /path/to/svn/hooks
%> chmod 770 post-commit
%> chgrp svn post-commit

More on post-commit

The post-commit hook takes two parameters: the repository path and the revision number. If you needed to run post-commit manually (testing your script!), it would look something like this for revision 746:

%> /path/to/svn/hooks/post-commit /path/to/svn/repository_name 746

SVN and Mantis in perfect harmony

There you have it. That’s how you integrate Subversion with Mantis. If you have questions, feel free to leave a comment.

Special thanks to the guys who spent time writing Version Control with Subversion (For Subversion 1.1): Ben Collins-Sussman, Brian W. Fitzpatrick, and C. Michael Pilato. The world would be a better place if every piece of open source software was documented this well. (By contrast, the Mantis documentation is terribly out of date and rather disorganized.)

A more advanced script

I wasn’t content with having just a log message added to my Mantis tickets. I wanted to know who did it, and what files were changed. Thus, my actual script is a bit more complicated. (Remember, I’m still learning Bash, so be nice.)
#!/bin/bash
 
REPOS="$1"
REV="$2"
 
auth=$(svnlook author -r $REV $REPOS)
dt=$(svnlook date -r $REV $REPOS)
changed=$(svnlook changed -r $REV $REPOS)
log=$(svnlook log -r $REV $REPOS)
n=$'\n'
/usr/bin/php -q /var/bugtracker/core/checkin.php <<< "Changeset [${REV}] by $auth, $dt$n$log$n$changed"

One Response
Hire Tom! Hire Tom!