GitLab Pipeline with release steps

The Maven Release Plugin can be used to release a Maven project. There are two important goals:

  • release:prepare that changes the version in all POMs to the supplied release version, commits those changes to SCM, creates a tag, changes the version in all POMs to the supplied next development version and commits those changes as well.
  • release:perform pushes the released and packaged Maven project to a remote repository.

My project uses Semantic Versioning, i.e. Major.Minor.Patch[-SNAPSHOT]. While there is a SemVer Policy for the Maven Release Plugin, it only increases the minor element for the next development version. My goal was to automate the execution of this plugin and the release process for all three version components within my GitLab pipeline. There should be three jobs in a Release stage that can be triggered manually:

  • release-major: releases the next major version, e.g. for a current version 2.3.1-SNAPSHOT:
    • Release version should be 3.0.0
    • Development version should be 3.0.1-SNAPSHOT
  • release-minor: releases the next minor version, e.g. for a current version 2.3.1-SNAPSHOT:
    • Release version should be 2.4.0
    • Development version should be 2.4.1-SNAPSHOT
  • release-patch: releases the current patch version, e.g. for a current version 2.3.1-SNAPSHOT:
    • Release version should be 2.3.1
    • Development version should be 2.3.2-SNAPSHOT

For this process we need to extract what the current and next major, minor and patch components are. Maven Build Helper Plugin offers the build-helper:parse-version goal that does just that. Our full Maven command to release the patch version looks like this:

mvn build-helper:parse-version release:prepare release:perform \
    --batch-mode \
    -DreleaseVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion} \
    -DdevelopmentVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion}-SNAPSHOT \
    -Dusername=$USER \
    -Dpassword=$PASSWORD \
    -Darguments=-Dmaven.test.skip \

For our GitLab pipeline we need to tell the runner to checkout the exact commit. By default the GitLab runner would checkout the detached HEAD of our branch which is just a pointer without the ability to commit. It is also necessary to set git user.name and user-email as the runner will commit to our branch. Our three jobs in .gitlab-ci.yml are defined as follows:

.release-setup:
  script:
    - git checkout -B "$CI_COMMIT_REF_NAME"
    - git config user.name "..."
    - git config user.email "..."

release-patch:
  stage: release
  when: manual
  script:
      - !reference [.release-setup, script]
      - >
       mvn build-helper:parse-version release:prepare release:perform 
        --batch-mode 
        -DreleaseVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion}
        -DdevelopmentVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion}-SNAPSHOT
        -Dusername=$USER
        -Dpassword=$PASSWORD
        -Darguments=-Dmaven.test.skip

release-minor:
  stage: release
  when: manual
  script:
      - !reference [.release-setup, script]
      - >
       mvn build-helper:parse-version release:prepare release:perform 
        --batch-mode 
        -DreleaseVersion=\${parsedVersion.majorVersion}.\${parsedVersion.nextMinorVersion}.0
        -DdevelopmentVersion=\${parsedVersion.majorVersion}.\${parsedVersion.nextMinorVersion}.1-SNAPSHOT
        -Dusername=$USER
        -Dpassword=$PASSWORD
        -Darguments=-Dmaven.test.skip

release-major:
  stage: release
  when: manual
  script:
      - !reference [.release-setup, script]
      - >
       mvn build-helper:parse-version release:prepare release:perform 
        --batch-mode 
        -DreleaseVersion=\${parsedVersion.nextMajorVersion}.0.0
        -DdevelopmentVersion=\${parsedVersion.nextMajorVersion}.0.1-SNAPSHOT
        -Dusername=$USER
        -Dpassword=$PASSWORD
        -Darguments=-Dmaven.test.skip

This GitLab pipeline setup is very convenient and helps to automize the versioning and release process in your CI/CD process.