In the process of moving some new and existing projects to GitHub and releasing them using Maven under Windows, I discovered a number of issues that can be tricky to get around. This post is for anyone else with the same problems, and for my own future reference.

First off, most of these issues are Windows related and while I would love to move to Linux and be rid of these problems, its impractical at the moment. Also, if you are a non-Windows user you can still get an idea of what is needed to deploy GitHub projects with Maven.

To avoid a disappointing end to the post, the one problem I couldn’t resolve was releasing multi-module projects with maven. I am still getting the StringIndexOutOfBounds error with msysgit. These instructions are still good for single module deployments though. If anyone has a solution to the string index issue, feel free to post in the comments or drop me a line.

My go to page for remembering how to do release a project with Maven is the Sonatype instructions which covers setting up a Sonatype account and tells you what you need to put in your pom.xml file for it to be released automatically.

If you have done maven releases before with subversion, you will know how easy it is. Once the SCM information is in your pom file, Maven will download the source, tag it to the version you select, commit the tag, build it, and deploy it which is really quite nice as well as updating your development code to the new snapshot version.
If you haven’t done a Maven release before, you will need to set up a PGP key on your machine and post it on a key server (see the Sonatype instructions for more info and links that help).

So at this point, lets assume you have a project ready for release in GitHub (or any other Git repository I guess). You have a PGP key set up on your local machine and added to a public key server. Windows users should also have mSysGit set up, which you probably have if you are developing with Git. Your project should also have the release and deployment information set up as defined in the Sonatype document.

I’ve seen a number of different ways of putting the SCM information in the pom file. Here’s what I used that worked for me. Obviously you’ll need to change the account name.

<scm>
   <connection>scm:git:git://github.com/andygibson/${project.artifactId}.git</connection>
   <url>http://github.com/andygibson/${project.artifactId}</url>   <developerConnection>scm:git:git@github.com:andygibson/${project.artifactId}.git</developerConnection>
 </scm>

Interestingly enough, when I was looking to see what other people were using, there are plenty of projects that still have subversion repositories in their scm information. I guess they probably haven’t changed it over yet because they haven’t done a release.

Roadblocks

There are two main problems that you will hit when releasing with Maven under Windows. The first is that when Maven tries to push the changes back to the Git repository it hangs waiting for the pass phrase for your GitHub SSH key. However, since it never displays a prompt for it, you are stuck waiting for it.

The second problem is exposing your pgp keys to your Git Bash shell. The shell expects the keys to be in a particular folder which doesn’t exist by default (/c/.gnugp).

Setting up SSH-Agent

Start up the Git Bash session (or as OSX and Linux users call it, a shell) and go to your project directory.
Windows users, you need to start up an SSH agent to provide your passkey when needed by the release process.

To do this, in your Git Shell type :

eval `ssh-agent`  //pay attention to the back tick quotes here

which should return a piece of text like Agent pid xyz. This command starts the agent and sets up a couple of environment variables relating to the SSH agent. If you type env | grep SSH you will see the environment variables :

$ env | grep SSH
SSH_AGENT_PID=1234
SSH_AUTH_SOCK=/tmp/ssh-abcdef1234/agent.5678

Windows users will need to manually create the directory c:/tmp/ssh-abcdef1234/agent.5678 otherwise you get and error saying could not open a connection to your authentication agent.
Create the new directory and then add your key to the agent using the following syntax which assumes your Github RSA key is in the c:\.ssh\ directory. If it isn’t then just substitute the directory for your key.

$ssh-add "/c/.ssh/id_rsa"
enter passphrase :

Once you enter the pass phrase, it will be stored for that particular key for the rest of the session. When Git requires the phrase as part of the release it will automatically receive it from the agent.

Note that this set up is only good for the current session. If you open another session and want to do a release in that session, you will need to repeat these steps. I also think it would be a bad idea (or at least pointless) to set up the SSH_AGENT_PID or the SSH_AUTH_SOCK environment variables in any global variables.

So now we have that set up, you should be able to run the mvn release:prepare part of the release. This will grab the source code, update the pom version and push the changes back to the repository.

Exposing your PGP keys

For the next step, (mvn release:perform) we need to do the actual release which involves building the artifacts, signing them and uploading them. I’m assuming that you already have a project and environment that is correctly configured for release (including the release servers in settings.xml). If not, again, take a look at the Sonatype instructions for info on this.

The problem we’ll encounter here is that when signing the artifacts, the maven gpg signing plugin can’t find the keys from the Git Shell. It is looking in the /c/..gnupg directory while the windows version of gpg puts it in the users Application Data folder in their profile. There are two ways to solve this problem, and both involve locating the directory containing the Gnugpg keys. This folder is likely to be My Documents\Application Data\ which happens to be a hidden folder for many and varies in location depending on the version of windows. However, in that folder is the gnupg folder that contains your keys. The other piece of the puzzle is the GNUPGHOME environment variable in both Windows and Bash which points to the folder containing the keys.

You can either move the windows folder to where the Bash shell expects it, and set the Windows environment variable to point to it which means that if you fix it now, it will be fixed for every session. Windows GPG will find the folder through the GNUPGHOME environment variable and Bash will find it because that is the default place it looks for it.

Alternatively, you can leave the folder alone and set the environment variable in the Git shell to point to the key folder where it is. The only problem with this is that the environment variable will need to be set up each time. However, it leaves the rest of your environment alone.

I guess the third option is if you don’t have a GPG key already set up and are using the Git shell to generate one, you might have to manually create the /c/.gnupg folder manually.

I wanted to move the folder anyway so I went for option one. The choice is up to you, but if you get a message like :

gpg: no default secret key:secret key not available
pgp: signing failed: secret key not available

Its because Gnupg can’t locate the keys you (should have) already set up.

Once I got that these two problems fixed things went fairly smoothly, well, very smoothly in fact, it just worked. Now, hopefully you won’t have the same problems I had!