Freitag, 27. September 2013

Lightweight release builds with Apache Maven

This article is a follow-up of http://diplingfh.blogspot.ch/2013/02/how-has-our-release-process-matured.html as I have enhancements to the version.override feature I presented in this article the first time.

For quick readers here a short howto:
  • Download maven-core-extensions-0.3.2.jar and store it under $M2_HOME/lib/ext
  • Configure your root pom.xml according to [1]
  • execute mvn clean install -Dversion.override
See https://github.com/rotscher/emerging for more information.

Some more explanation


It's not the main purpose to replace the maven-release-plugin. But still, for doing continuous delivery during development phase it's not convenient:

We need a build with a unique version
And I don't mean unique SNAPSHOTs as this generated version might be different for each module inside a multimodule project. And there is no 100% safety that I really reference the latest SNAPSHOT! And this timestamp-buildId construct is ok for machines but not for humans (my tester answers my "which-version-is-deployed-question" with 2.2.3-201309261313-1).

When the build- and deployment process is started a unique version is generated and used throughout the toolchain (E.g. as build parameter in Jenkins, or input parameter to a deployment tool, or mentioned in a status report).

We don't want the pom version updated and committed daily
The developers don't like that all pom files are updated and they have to build from scratch to get new SNAPSHOT artifacts into the local maven repository.

we don't need a tag daily
The unique version mentioned above (and the revision from version control, too) is stored where ever it makes sense:
  • display-name of web.xml (this is visible in Tomcat manager)
  • somewhere in the (web) application and then visible for all users
  • in a database table
  • in all MANIFEST.MF
With all that information it's easy to track down problems during the development (when done in short cycles ;-). And it's even possible to reproduce a build if necessary at all.

The build must fail fast
How many times did your release process failed because you still had configuration errors? And how good do you feel about your release when you finally fixed all that errors? I mean, you just released something different than what you tested.
This is mainly the problems of SNAPSHOT versions. With the version.override feature you detect such configuration errors very fast!

The release plugin is not handy
In the last phase of a development iteration it should be possible to deliver as fast as possible. The release plugin builds three times and commits twice: this takes time and the chance of failures is high.
How many times did you fixed the scm connection configuration in your root pom?
And ever tried to execute the release plugin in an automated way? E.g. automatically triggered at 9pm?

Final thoughts
To me, SNAPSHOT versions are ok on local developer machines but it's subobtimal when SNAPSHOTs are in a remote repository, or even on a Jenkins with shared local repository (but having private repositories is not always possible due to infrastructure limitations).
This approach here is as easy as executing normal SNAPSHOT builds (also on local developer machines!), is not changing anything in the version control (and no risk of failures with the version control), but is behaving like release:perform. And it still leaves the choice to use all options in the development process:

mvn clean install (after each commit during the day)
mvn clean install -Dversion.override (once per day)
mvn release:prepare release:perform (when day x arrives  ;-)


[1] version.override custom install plugin configuration
<profiles>
    <profile>
        <id>version.override</id>
        <activation>
            <property>
                <name>version.override</name>
            </property>
        </activation>
        <build>
            <pluginManagement>
                <plugins>
                    <!-- deactivate the default install plugin -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-install-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>default-install</id>
                                <phase>none</phase>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </pluginManagement>
            <plugins>
                <!-- configure the custom install plugin for lightweight release builds -->
                <plugin>
                    <groupId>ch.rotscher.maven.plugins</groupId>
                    <artifactId>install-custom-version-plugin</artifactId>
                    <version>0.3.1</version>
                    <executions>
                        <execution>
                            <id>custom-install</id>
                            <phase>install</phase>
                            <goals>
                                <goal>install</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Kommentare:

  1. Is it still necessary to put the profile configuration into the pom.xml? Looking at the extension source, it seems that it's doing that automatically for you?

    AntwortenLöschen
    Antworten
    1. Yes, it's still necessary for integrating the custom-install-plugin (with or without profile depending on how you want to use the version.override feature).

      I once tried to integrate the plugin in the lifecycle but I fear I have to little knowledge of plexus and therefore my integration solution was too complicated. So I never finished this and recommend to configure everything in the pom.

      Löschen