Introduction
Subversion’s hook scripts provide a powerful and flexible way to associate actions with repository events. For example, the pre-commit hook allows you to check and possibly abort a transaction before it actually gets committed. This article describes how to write such a hook in VBScript® and test whether the committer has supplied a commit message and that the message contains a valid issue ID. The issue tracking system used for integration is JIRA®.
Creating the Hook Script
When you install Subversion, it also installs sample hook scripts. These sample scripts are located in the REPOS_PATH\hooks directory. For example, the pre-commit template is in PATH_TO_REPOS/hooks/pre-commit.tmpl. These templates contain instructions on what the hook script does and what parameters it can expect.
Tip:
The hook file must be an executable. Windows uses file extensions to determine whether or not a program is an executable, so you would need to supply a program whose base name is the name of the hook, and whose extension is one of the special extensions recognized by Windows for executable programs, such as .exe or .com for programs, and .bat for batch files.
|
The Pre-commit Hook
The pre-commit hook gives you an opportunity to catch the transaction just before it becomes a revision. Typically, this hook is used to protect against commits that are disallowed due to content or location (for example, your organisation might require that all commits to a certain branch include a ticket number from the bug tracker, or that the incoming log message is non-empty). Subversion passes this hook two parameters:
- The path to the root of the repository
- The transaction identifier
The pre-commit can fail the transaction by printing an informative message to standard error and returning a non-zero value. A return code of zero allows the transaction to complete successfully.
The Hook Script
The hook script enforces the following rules:
- Non empty commit message.
- Commit message must begin with an Issue ID followed by a space and hyphen.
- The Issue ID specified must be a valid issue in the Issue System (JIRA).
- The Issue must have been assigned to the committer.
JIRA Integration
The integration with JIRA is done via a Web Service using SOAP messages. This of course requires that the XMLRPC plug-in be enabled on the JIRA server. The script makes use of the MSXML.HTTP
object to invoke the JIRA Web Service. The commit log message and the committer are found using the svnlook.exe program which comes with the Subversion software. The Web Service invocation is done by a class named WebService
which is actually an adaptation of the code published at CDYNE Wiki. (The code found on this site is good enough to make a POST request, but fails to invoke a SOAP enabled Web Service.) The code calls the following methods in the JIRA Web Service:
login
- This method must be called to ensure that we get an authentication token. The token returned by this method is required in subsequent calls. This method takes the following two parameters, and upon successful logon, returns the authentication token:
in0
- The user name
in1
- The plain text user password
getIssue
- This method is used to retrieve the issue details given its id. This method takes the following two parameters, and returns the issue details if the requesting user has view permissions and the issue with the supplied ID exists:
in0
- The authentication token
in1
- The issue ID
logout
- This method is used to logout the user. This method takes only one parameter, namely the authentication token.
The actual error is conveyed back to the user by writing the error text on StdErr
. This allows the committer to see why his/her commit is denied.
pre-commit.bat
As mentioned earlier, the Subversion server is capable of calling the executable scripts only. Since the pre-commit hook is written in VBScript, we need a driving script. Here is the driving script:
@ECHO OFF
SETLOCAL
SET PATH=C:\Windows;C:\Windows\system32;D:\SCC\SVN146\bin;
cscript.exe //NoLogo H:\SVNRepo\docman\hooks\pre-commit.wsf %1 %2
IF ERRORLEVEL 1 GOTO fail
:success
EXIT 0
:fail
EXIT 1
History
- 4/11/2008 - The first version released on my blog.