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/