Experience using flatten-maven-plugin for simplifying versioning in Maven projects

About Us

At 1C, we develop not only the platform 1C: Enterprise to C++ and JavaScript, but also applications in Java – specifically a new development environment Enterprise Development Tools based on Eclipse, and the server is deeply integrated with the messenger platform – Interaction Systems.

Introduction

As the build system for Java applications, we most often use Maven, and in this brief article, we would like to discuss one of the problems we encountered during the organization of development and the approach that allowed us to overcome this issue.

Prerequisites and Workflow

Due to the specifics of development in our Maven projects, we use quite a few modules, dependencies, and sub-projects. The number of POM files in a single tree can reach dozens and even hundreds.

Experience using flatten-maven-plugin for simplifying versioning in Maven projects

It would seem: nothing terrible, we created them once and forgot. If we need to change or add something in all files at once, there are plenty of convenient tools in editors and IDEs. What is the most common regular change in pom.xml? We believe it's changing the versions of projects and dependencies. Some may want to argue with this, but that’s how it is for us. The reason lies in the fact that alongside the core, we are simultaneously developing many of our own libraries, and for consistent reproducibility of build and test results, the use of snapshots does not seem like a convenient approach. For this reason, we have to raise the version number in the projects with each build.

Additionally, developers occasionally need to build their branch of a library and verify its functionality across all dependencies, which requires manually changing the version in all of them.

Initial Solution

With such frequent and numerous version changes, we want to simplify and automate the process within CI. Here, a convenient well-known plugin comes to the rescue versions-maven-plugin – we connect it and run

mvn -N versions:set -DnewVersion=2.0.1

and Maven will do everything right: it will traverse the hierarchy from top to bottom, substituting all versions — beautiful! Now we just need to create a pull request, colleagues will review the changes, and we can quickly merge into trunk. Quickly? Not just like that. A couple of hundred pom.xml for review, and that doesn't take into account the code. Moreover, no one is immune to merge conflicts when dealing with such a large number of modified files. It should be noted that during the CI process, version changes occur automatically along with functional updates, rather than separately.

New features

For a while, we settled down and, having accepted it, lived on until the guys from Maven Apache Project included support for so-called 'version placeholders' in Maven starting from version 3.5.0-beta-1. The essence of these placeholders is that pom.xml instead of specifically indicating the project version, variables are used ${revision}, ${sha1} and ${changelist}. The values of these properties are set either in the <properties> element, or they can be defined through the system property

mvn -Drevision=2.0.0 clean package

The values of system properties take precedence over values defined in <properties>.

Parent
<project>
  <modelVersion>4.0.0<\/modelVersion>
  <parent>
    <groupId>org.apache<\/groupId>
    <artifactId>apache<\/artifactId>
    <version>18<\/version>
  <\/parent>
  <groupId>org.apache.maven.ci<\/groupId>
  <artifactId>ci-parent<\/artifactId>
  <name>First CI Friendly<\/name>
  <version>${revision}${sha1}${changelist}<\/version>
  …
  <properties>
    <revision>1.3.1<\/revision>
    <changelist>-SNAPSHOT<\/changelist>
    <sha1\/>
  <\/properties>
<\/project>

Child
<project>
  <modelVersion>4.0.0<\/modelVersion>
  <parent>
    <groupId>org.apache.maven.ci<\/groupId>
    <artifactId>ci-parent<\/artifactId>
    <version>${revision}${sha1}${changelist}<\/version>
  <\/parent>
  <groupId>org.apache.maven.ci<\/groupId>
  <artifactId>ci-child<\/artifactId>
   …
<\/project>

If you want to build version 2.0.0-SNAPSHOT, just use

    mvn -Drevision=2.0.0 clean package

If you want to make a release, simply reset the SNAPSHOT

    mvn -Dchangelist= clean package

*The examples above are taken from article the Maven Apache Project website

The Harsh Reality

Everything is fine and great, it's time to feel satisfaction, but no. It turns out that this method won't work for install and deploy, since the descriptions of the artifacts published in the repository won't be replaced ${revision} with its value and Maven won't understand what it's all about.

<parent>
    <groupId>org.apache<\/groupId>
    <artifactId>apache<\/artifactId>
    <version>${revision}<\/version>
<\/parent>

Light at the End of the Tunnel

We need to find a solution to the problem. The situation could be saved by flatten-maven-pluginThis plugin allows all variables in the pom, but it also removes a lot of other information that is only needed during the build and is not necessary when importing published artifacts into other projects. The plugin also 'flattens' all parent-child dependencies, resulting in flat pom files that include everything needed. The inconvenience was that it cuts out too much 'extra' information, which was not acceptable to us. After studying the information regarding the development of this plugin, it turned out we are not alone in the universe, as in August 2018, a pull request was created in the GitHub repository of the plugin with a request to allow defining how to 'corrupt' pom.xml on our own. The developers listened to the voices of the needy, and already in December, with the release of the new version 1.1.0, a new mode named resolveCiFriendliesOnly was introduced in the flatten-maven-plugin, which was just right for us – it leaves the pom.xml as it is, except for the element <version> and allows ${revision}, ${sha1} and ${changelist}.

Adding the plugin to the project

<plugins>
  <plugin>
    org.codehaus.mojo
    flatten-maven-plugin
    1.1.0
    <configuration>
      true
      <flattenMode>resolveCiFriendliesOnly</flattenMode>
    </configuration>
    <executions>
      <execution>
        flatten
        process-resources
        <goals>
          flatten
        </goals>
      </execution>
      <execution>
        flatten.clean
        clean
        <goals>
          clean
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>

Done!

Happy ending

From now on, to change the version of the entire project and inform all dependencies about it, we only need to edit the <revision> element in just one root pom.xml. A single file with the identical change arrives for review instead of a hundred or so of these files. This also eliminates the need to use versions-maven-plugin.

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster