views:

545

answers:

2

We are in the process of converting our main build process from ant to maven. We use TeamCity for our Continuous Integration server (CI).

We'd like to use the CI server to kick off (nightly) builds whose version contain a build number, as in 1.0.0.build#. These builds would be installed in our local maven repository to be used by other projects. So the CI server would manage the versions, maven would build the project, and the maven repository would make the builds accessible to other projects.

I intended to initiate the build from the CI server using the following command:

mvn -Dversion=1.0.0.25 install

The project's pom would have a bogus version number, and the -D flag would override it, as in:

<version>0.0.0.0</version>

The problem with this method is that the maven install plugin only uses the version in the pom file, not the version passed in on the command line. This is noted in this maven issue.

So since this issue has existed since 08/2006 and has not been fixed, I assume that this is somehow not 'the maven way'. So my question is, how can maven be used in a continuous integration situation to install versioned artifacts in the repository?

+3  A: 

Sounds like you want to build SNAPSHOT versions with unique versions.

So, in your POM declare the version as:

<version>#.#.#-SNAPSHOT</version>

Then, in the distributionManagement section of your POM, enable unique versions for the snapshotRepository via (see Maven's POM reference on this):

<snapshotRepository>
  <uniqueVersion>true</uniqueVersion>
  <id>your-snapshot-repo-id</id>
  <name>Your Snapshots</name>
  <url>http://your-snapshot-repo-url/maven&lt;/url&gt;
</snapshotRepository>

FYI, note that Maven conventions recommend versions be declared as major.minor.revision. So, 1.0.25 instead of 1.0.0.25. If you're able to use this versioning scheme, things will work more smoothly in a Maven world.

shek
+1  A: 

Shek's answer is probably 'the maven way', so I'll accept it as the correct answer. However, we are not ready to change our conventions, so here is the workaround that we are using.

By using a level of indirection you can pass a version number in to the pom at build time and have the install and deploy plugins use them. For example:

<project xmlns="..." xmlns:xsi="..." xsi:schemaLocation="...">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.stackoverflow</groupId>
  <artifactId>stackoverflow</artifactId>
  <version>${ciVersion}</version>
  <packaging>jar</packaging>
  <name>StackOverflow</name>

  <properties>
    <ciVersion>0.0.0.0</ciVersion>
  </properties>

  ...

</project>

We cannot override ${project.version} directly. So instead, we add a second property called 'ciVersion' and give it a default value of '0.0.0.0' in the properties section. Now the CI server can specify a version number by overriding the ciVersion property on the command line. As in:

mvn -DciVersion=1.0.0.25 install

The install and deploy plugins will use the value of the ciVersion property that was passed in whenever ${project.version} is referenced, as expected, and the default value will be used when no version is provided on the command line. This allows us to switch to maven with minimal impact on our process. In addition, this workaround is unobtrusive, allowing for an easy switch to the SNAPSHOT functionality when desired.

Matthew Jaskula