A few days ago I tried to cut my first [JIRA Studio][] release. The process is fairly straight forward, run these two commands and you’re done:

mvn release:prepare
mvn release:perform

During the prepare process, Maven will copy your code into a new tag named after the version number you’ve told it to release. I ran the preparation and it appeared to run fine, so I tried running the perform step. For some reason, Maven was ignoring the version number I had given it, and was trying to deploy artifacts with a SNAPSHOT version instead.

After getting someone to help me, we found that the SCM attributes in our pom.xml were to blame:

scm:svn:https://studio.atlassian.com/svn/JST/branches/studio-streams4-upgrade
scm:svn:https://studio.atlassian.com/svn/JST/branches/studio-streams4-upgrade
https://studio.atlassian.com/svn/JST/branches/studio-streams4-upgrade

We release from trunk but the attributes pointed to a recently merged branch. Woops! Maven uses these attributes to create a tag so it was actually copying a branch to the tag.

Why did the merge overwrite the attributes? Well, this could have happened in a few different ways:

* We didn’t branch by using `mvn release:branch`. Doing this will correctly setup branch tracking so that merging back won’t treat the attribute as a difference.
* We branched from another branch or tag.

I explained the problem on our team’s IRC channel and a few other team members told me that they had been hit by it in the past. Not good. I came up with a small script avoid this in the future.

### Solution

The JIRA Studio team has a “Dependency Checks” build specifically to check that all our dependencies aren’t SNAPSHOT versions. It does nothing other than provide information about our Maven configurations. I thought it would be good to add a check for the SCM attribute.

The SNAPSHOT check uses the [Maven Enforcer Plugin][]. The plugin fails the build when conditions aren’t met. Here is our configuration from the `depcheck` profile:

org.apache.maven.plugins
maven-enforcer-plugin
1.0

enforce-no-snapshots

enforce

No Snapshots Allowed!

false
false

com.atlassian.studio:*

true

The Enforcer Plugin has an easy API that allows [writing custom rules][]. This is the simple Groovy class I came up with:

package com.atlassian.maven.plugins.studio.scm
import org.apache.maven.enforcer.rule.api.EnforcerRule
import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
public class ScmEnforcerRule implements EnforcerRule
{
private String enforceUrl
void execute(EnforcerRuleHelper helper)
{
def scmConnection = helper.evaluate(“${project.scm.connection}”)
def scmDeveloperConnection = helper.evaluate(“${project.scm.developerConnection}”)
def scmUrl = helper.evaluate(“${project.scm.url}”)
[scmConnection, scmDeveloperConnection, scmUrl].every {
if(!it.contains(enforceUrl)) {
throw new EnforcerRuleException(“Please check your paths – ” + it + ” doesn’t contain ” + enforceUrl)
}
}
}
boolean isCacheable()
{
false
}
boolean isResultValid(EnforcerRule enforcerRule)
{
false
}
String getCacheId()
{
enforceUrl
}
}

I’m not a Groovy expert but this should fail the build if an SCM attribute doesn’t contain the `enforceUrl` string. The string gets passed along by our POM:

org.apache.maven.plugins
maven-enforcer-plugin
1.0

com.atlassian.maven.plugins
studio
110

enforce-scm-paths

enforce

${enforce.scm.path}

true

The usage is like so:

mvn -B validate -Pscmcheck -Denforce.scm.path=”https://studio.atlassian.com/svn/JST/trunk”

Easy. We now get feedback from our Bamboo builds about whether our SCM attributes builds point to trunk! This should completely avoid the problem that we had before.

[Maven Enforcer Plugin]: http://maven.apache.org/plugins/maven-enforcer-plugin/
[writing custom rules]: http://maven.apache.org/enforcer/enforcer-api/writing-a-custom-rule.html
[JIRA Studio]: http://www.atlassian.com/hosted/studio/

Fresh ideas, announcements, and inspiration for your team, delivered weekly.

Subscribe now