Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can maven be used in a continuous integration situation to install versioned artifacts in the repository?

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?

like image 908
Matthew Jaskula Avatar asked Dec 02 '08 23:12

Matthew Jaskula


2 Answers

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</url>
</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.

like image 167
shek Avatar answered Sep 20 '22 17:09

shek


Matthew's answer provides a solution where the artifacts get uploaded into the local and remote repository having the desired version number, i.e. the paths inside the repository are contain the correct version numbers, however, Maven installs and deploys always the source POM file that would still contain the ${ciVersion} in the version element.

If you have a multi-module with a common parent like this:

<project xmlns="..." xmlns:xsi="..." xsi:schemaLocation="...">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>myParent</artifactId>
    <groupId>com.stackoverflow</groupId>
    <version>${ciVersion}</version>
  </parent>
  <artifactId>myChild</artifactId>
  ...
</project>

you won't be able to reference a dedicated version of the myChild module, as the dependency resolution will exist with an error that it cannot find the myParent module with version ${ciVersion}.

However, you could use the resolve-pom-maven-plugin that uploads a POM into the local and remote repository where all variables inside the POM get substituted by their actual values. In order to do this, you have to add the following snippet into your (parent) POM:

...
<build>
  <plugins>
    <plugin>
      <groupId>com.sap.prd.mobile.ios.maven.plugins</groupId>
      <artifactId>resolve-pom-maven-plugin</artifactId>
      <version>1.0</version>
      <executions>
        <execution>
          <id>resolve-pom-props</id>
          <goals>
            <goal>resolve-pom-props</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
...
like image 36
Joern Avatar answered Sep 19 '22 17:09

Joern