Release Java project with Maven in a new way

    All of us have long been accustomed to Maven , to the versioning of their proposed and dependency management. Maven came to life when the daily assembly of the project was the lot of the bravest, when it was considered normal to release at least a couple of times a year, Jenkins was then called Hudson , and the trees were big ...

    The ideas that brought maven into the world of development were extremely in demand and quickly gained popularity: the definition of a standard workflow project, the standard directory model, and a lot more, which has long been taken for granted.

    As one of the innovations, maven introduced the standard versioning system. The version was stored in the project file and changed whenever we released a new release. In a world where making a branch and its merjunti was a feat not available to everyone, this approach was quite common.

    All this greatly simplified the development, start of new projects, introduction to the project of developers, release of version and dependency management.

    But the world does not stand still, and, despite the fact that many ideas implemented by maven still live and move from one project to another, the version of maven has started to deliver more problems than advantages.

    Next, we will try to change the world for the better and simplify our lives.

    I assume that the reader is familiar with Java, Maven, the development lifecycle and setting up the CI / CD, he understands why he needs all this and is generally a ninja .

    In modern realities, it is considered the goal, if not the norm, to release several versions a week or even a day. And, in such conditions, storing a version in a project file leads to very large overheads.

    Each release leads to two commits to the repository, and as a result, with the active development and release of the project, such technical commits become more than useful. The history of the project is littered and becomes difficult to perceive.
    Also, this approach leads to duplication of information: it has become customary to store the version not only in the project file, but also as a repository tag.

    Besides, there was a security issue: when you have one big project, then the build machine only needs access to it. When there are a lot of projects, access is needed to many projects and we either create a super user with access to all projects with write access, or get an additional burden on administering a large number of users with a narrow set of rights, but still having write access to the repository, and often, and the right to commit to a master without a pool of requesting and review.

    When using maven with a release plugin, another interesting feature appears: the reassembly is not performed by the same set of commands as the original version.

    Probably, all these problems will seem to someone far-fetched, but with a more or less large number of projects, managing and tuning the CI / CD turns into an extremely unpleasant and confusing process.

    Now that the problem is visible, let's try to solve it, so as not to greatly change the set of tools, processes, and in general so that it itself, somehow.

    What is needed:

    • the version is stored once, as a repository tag
    • reassembly of any release is possible, the set of steps should be the same as in the case of a new release
    • no rights to write to the repository
    • we still use maven as a project manager

    Suppose that CI / CD will make for us getting the tag and checkout the project.

    Suppose that the tag for us is filled with CI / CD in the environment variable RELEASE_TAG, then in order to release a release, we must execute the following commands:

    mvn -B versions:set -DnewVersion=$RELEASE_TAG (1)
    mvn -B deploy (2)

    1 - updates the versions in the pom-files of the project and its modules
    2 - builds and, if the project is properly configured, loads artifacts into the repository

    Do not forget to set the -B flag , otherwise the execution log turns into a pumpkin.

    Important: in order to avoid confusion and clearly see how and where the assembly is coming from, you need to install the project version into something abstract, for example, DEVELOPMENT-SNAPSHOT. You can use the same command: version: set. The operation is a one-time, because we no longer store the version of the project in the file.

    As a result of the changes, you can remove the configuration of the maven-release-plugin and scm block from the pom file.

    "Of the minuses:
    If you use SNAPSHOT versions anywhere, then confusion may start, now all SNAPSHOT versions look the same. And perhaps this way to release projects is not for you.

    It may be a feeling that an artifact collected from the same commit but with different tags will be the same, but, unfortunately, this is not the case. We, all the same, expose the version in the file, and, as a result, the collected packages will be different.

    "Of the benefits:

    • All requirements are satisfied, and even more!
    • the version is stored only in the project tag
    • building a new one and rebuilding the old version is done by the same set of commands as the original version
    • there is no need to commit to the project
    • the toolbox stayed the same
    • bonus: project configuration simplified

    So, two lines again saved the world.
    That's all, thank you for your attention!

    Also popular now: