nonblocking / nonsnapshot-maven-plugin

Non-Snapshot Maven Plugin
10 stars 9 forks source link

Nonsnapshot Maven Plugin

A Maven plugin to get rid of SNAPSHOT versions and automatically update artifact versions with each build if anything changes. Such a change can be a scm commit since the last build or a newly available upstream dependency version within a configured range.

Motivation

When working on a huge project with hundreds of Maven artifacts depending on each other, dealing with SNAPSHOT versions really becomes unhandy. The main reasons are:

  1. The developers need to have all projects in the workspace to make sure the dependency resolution of the IDE works
  2. Manually versioning 100+ projects means a lot of effort
  3. It is not possible to reproduce the exact state of a project to any given time, when you depend on SNAPSHOT versions
  4. It makes a fully automatized deployment complicated, since you need a manual versioning step instead of just pushing the latest build onto your servers

How this plugin works

The algorithm works as follows:

  1. Collect all modules recursively.
  2. Check all modules for changes (commits) since the last version update. If commits exist mark the module as dirty.
  3. Resolve the latest upstream dependencies versions. If any newer version are available update the version accordingly and mark the module as dirty.
  4. Mark all modules as dirty which have dirty dependencies.
  5. Bump the version of all dirty modules.
  6. Rewrite the pom.xml of all modules with a new version.
  7. Optional: Generate a script and/or property file for an incremental build of all dirty modules (Maven > 3.2.1 required).
  8. Commit all changed pom.xml files to SCM. This step can be deferred and done by a second goal.

The generated artifact versions consist of a "base version", which can be configured, and the build timestamp or revision id (SVN only) as a qualifier. Examples:

Configuration

The plugin can be added to a separate (POM-) project or your main aggregator project. Like this:

<build>
    <plugins>
        <plugin>
            <groupId>at.nonblocking</groupId>
            <artifactId>nonsnapshot-maven-plugin</artifactId>
            <version>4.0.1</version>
            <configuration>
                <baseVersion>1.2.3</baseVersion>
                <scmType>SVN</scmType>
                <!-- <scmType>GIT</scmType> -->
                <scmUser>${scmUser}</scmUser>
                <scmPassword>${scmPassword}</scmPassword>
                <useSvnRevisionQualifier>true</useSvnRevisionQualifier>
                <deferPomCommit>true</deferPomCommit>
                <generateIncrementalBuildScripts>true</generateIncrementalBuildScripts>
                <generateChangedProjectsPropertyFile>true</generateChangedProjectsPropertyFile>
                <dontFailOnCommit>false</dontFailOnCommit>
                <dontFailOnUpstreamVersionResolution>false</dontFailOnUpstreamVersionResolution>
                <upstreamDependencies>
                    <upstreamDependency>at.nonblocking:*:LATEST</upstreamDependency>
                    <!-- Examples -->
                    <!-- <upstreamDependency>at.nonblocking:*:2.10</upstreamDependency> -->
                    <!-- <upstreamDependency>at.nonblocking:test-test2:2.10.3</upstreamDependency>-->
                    <!-- <upstreamDependency>at.nonblocking:test-*:LATEST</upstreamDependency>-->
                </upstreamDependencies>
            </configuration>
        </plugin>
    </plugins>
</build>

Notes

Usage

Goals

The following goals are available:

Using it on a CI Server

A fully automatized auto-release is of course only possible if you use this plugin within a CI server (e.g. Jenkins).

First add the following optional configuration parameter:

<deferPomCommit>true</deferPomCommit>

Then configure the job on your CI server like this:

  1. Revert and update the workspace
  2. Execute the goal nonsnapshot:updateVersions
  3. Build the whole project
    • Option 1: mvn install
    • Option 2: Incremental build with mvn install --projects ${nonsnapshot.changed.projects}. To get the property nonsnapshot.changed.projects you have to enable the option generateChangedProjectsPropertyFile and inject properties from the generated file ./nonsnapshotChangedProjects.properties. On Jenkins you can use the EnvInject Plugin for that.
  4. Deploy all generated artifacts to your remote Maven repository (e.g. Artifactory)
  5. Execute the goal nonsnapshot:commitVersions

On Jenkins you can use pre-build and post-build steps for #2 and #5.

This configuration guarantees that the module versions in the dependencies section of a POM file are always available from the remote Maven repository. (And so the developers no longer need all the Java projects in their workspace.)

Continuous Deployment

For Continuous Deployment just create a new release (POM-) module which includes all your deployment modules in the dependencies section.

For example:

<dependencies>
        <dependency>
            <groupId>my.domain</groupId>
            <artifactId>webapp1</artifactId>
            <version>1.0.12-4567</version>
            <type>war</type>
        </dependency>
        <dependency>
            <groupId>my.domain</groupId>
            <artifactId>webapp2</artifactId>
            <version>1.0.12-4555</version>
            <type>war</type>
        </dependency>
</dependencies>

Since the dependency versions are rewritten with each plugin execution, they will always point to the latest version. You can now use the maven-dependency-plugin or the maven-assembly-plugin together with ant to copy all your deployment artifact to the server.

Licence

Licensed under the Apache License, Version 2.0.