Monday, November 3, 2014

Using Maven to assemble and release artifacts to Nexus

An important part of a release process is storing artifacts in an artifact repository. Many customers use custom implementations of artifact repositories (such as file shares in combination with custom scripts) but there are also products which offer many functions of such a repository (and probably many more) out of the box so that custom implementations are not necessary anymore. Nexus is an example of a popular artifact repository. An added benefit of using a popular product to provide repository functionality is that a lot of development tools can easily be integrated with it. Maven can easily be used to compile and assemble code and deploy it to a Nexus repository.

In this blog I will provide an example of how a shell script (as an example artifact) can be packaged and deployed to Nexus by using Maven. I will use the maven-assembly-plugin to package the script, the nexus-staging-maven-plugin to deploy to Nexus and the maven-release-plugin for the version control part of the release process.

 

Implementation

Sample project
My sample project can be downloaded here:

The structure is as follows;

My pom.xml (Maven Project Object Model) looked as follow.


The plugin configuration looks as follows. Instead of the maven-deploy-plugin I use the nexus-staging-maven-plugin. The nexus-staging-maven-plugin provides more Nexus specific functionality then the maven-deploy-plugin has to offer. Instead of the maven-jar-plugin I use the maven-assembly-plugin. This plugin allows more control on how non-Java code can be packaged then the default maven-jar-plugin. Read more on: http://www.baeldung.com/maven-deploy-nexus.


Assembly
In order to put the example shell script in a distributable ZIP which can be put in Nexus, the maven-assembly-plugin is used. In order to configure it, you provide an assembly descriptor. This is an XML file describing how which files should be packaged. In this descriptor you can use filters and different archive formats. Below is an example for the assembly file (src.xml) I've used in this blog.


The assembly file as shown above, creates a ZIP-file when executing mvn package. The output can be viewed here.

As you can see, a lot is done out of the box (some of the actions performed might not be relevant and you could specifically ask for them to be skipped such as executing tests).

In this case /home/maarten/mvntest/myproject/target/testproject-1.2-SNAPSHOT-distribution.zip is created. Distribution is the id in the assembly file. The extension is derived from the specified format. The prefix is derived from the combination ArtifactId and version as specified in the pom.xml file of the project which is being packaged.

Assembly for multi module Maven projects requires some additional actions (see here). You need to add a special distribution module. In this module you need to specify which other modules need to be packaged. Also you need to add a dependency to the last compiled module in the distribution pom file so the distribution project is executed after all binaries are generated.

Nexus
I used a default installation of Nexus. In order to allow usage of Nexus from Maven, I needed to do some configuration in my projects POM file (see in the 'Sample project' part of this blog) and in my local settings.xml file.

The settings.xml file located in my ~/.m2 folder was the following:


It specifies which repository should be used. Nexus can be used to cache artifacts from online repositories so not every developer needs to download every artifact themselves. Inside Nexus, several repositories can be configured. For custom code, by default, the 'Releases' and 'Snapshots' repositories are used.

SCM
The maven-release-plugin requires a version control system such as SVN or GIT. It increases the version number as specified in the pom.xml file, creates a tag for the released version and saves the new trunk in the SCM system. In this example I've used SVN. The following SVN structure worked for the plugin without much additional configuration.

myproject
- tags
- trunk
- branches

Trunk is the 'latest and greatest' while the tags are created by the release process and contain the version number. See here for a blog on how to get an SVN repository working quickly.

Release
In order to execute a release, the following commands need to be given;

mvn release:prepare
mvn release:perform

If all is configured well, the output should look something like my own which can be downloaded here.

The maven-release-plugin does several things. The steps are nicely described on the following blog: http://www.disasterarea.co.uk/blog/maven-release-plugin/. The process can be repeated to create more releases.

Conclusion

Maven should be a tool to make things easier. If using Maven does not make things easier, I recommend not to use it. This of course needs to be evaluated per use-case.

When to use Maven to deploy to Nexus?
If Java is your primary technology (or your technology provides sufficient out of the box support for Maven), the assemblies to be released have a simple structure and the release process looks similar to what the maven-release-plugin provides, you can save yourself a lot of custom code by using the provided functionality of Maven. Packaging, deploying (to Nexus or another repository), executing automated tests, SCM interfacing are all there. Also Maven provides very good dependency management.

When not to use Maven to deploy to Nexus?

If you want to have a single framework to build, package, deploy different technologies and require flexibility in your process, I recommend not to use Maven for this. Using Maven to deviate from the Maven-path, requires effort. If you often have such requirements, you are probably better of with a more flexible framework.

Complex assemblies are hard to create. Multi-module projects are difficult. For the very simple example in this blog (packaging and releasing a single file), I needed to add as much plugin configuration as code to disable existing plugins. I could not get a multi module assembly working quickly enough. Also I needed to create a SVN repository to allow execution of a part of the default release process. The Maven process depends on a settings.xml file. This also needs to be configured just right on every system where the build needs to be executed.

And Nexus?
I have little complaints about Nexus. My first impression is that it is quite suitable for an artifact repository.


No comments:

Post a Comment