Search code examples
mavenmaven-release-pluginmaven-versions-plugin

How to update/fix a single child module's parent version


Structure

I know this project structure is not "the Maven way" and this is why I struggle in the first place. Unfortunately I cannot change the project structure.

I try to simplify it as much as possible:

/module-a
/module-b
/module-c
/parent              <- <parent>master</parent>, <modules>module-a, module-b, module-c</modules>
/parent/aggregator-d <- <parent>parent</parent>, <modules>module-a, module-b</modules>
/parent/aggregator-t <- <parent>parent</parent>, <modules>module-a</modules>

Use Case

The version of all modules should be changed to a given version. Apart from the parent module, no module explicitly defines its version, so only the parent version has to be changed. But since the parent version is referenced in all other modules, they have to be updated accordingly.

This works fine (using release:update-versions -DautoVersionSubmodules on the parent) for all modules that are listed in a <modules> section in the parent POM (or activated profile). However, the remaining modules aggregator-d and aggregator-t are not updated.

Failed attempts

So I thought I'd update the remaining modules separately, using mvn --non-recursive, but with no luck so far.

With the release plugin, I only managed to update their own version, using release:update-versions, however this does not update the referenced parent version, so it results in a module version different than the parent version (the explicit module version declaration has been added by the release plugin):

<parent>
  [...]
  <version>1.0.0-SNAPSHOT</version>
</parent>
<version>1.0.0-changed-SNAPSHOT</version> <- added by release plugin

Using the versions plugin, versions:set fails because the module version is defined by its parent, versions:update-parent does not work because I cannot specify the new parent version (instead the newest version found in the remote repository will be set) and versions:update-child-modules tells me that all child modules are up to date (because the idea is to run it on an aggregator which references the module I want to have updated).

Other ideas

The Maven commands are executed within a Jenkins declarative pipeline, so maybe I could try the (deprecated) writeMavenPom.

Apart from that and using something like sed or maven-antrun-plugin for regex replacement, I've run out of ideas.


Solution

  • Reading more documentation on the versions Maven plugin I noticed that for the parameter newVersion of versions:update-property it says:

    If you like to define the version to be used exactly you have to use it like this: -DnewVersion=[19.0] otherwise a newer existing version will be used.

    So I applied this information to the parameter parentVersion of versions:update-parent, together with -DallowSnapshots. I then got this warning (while the build still succeeded):

    [WARNING] Not updating version: could not resolve any versions

    Luckily I found out that the desired version is not required to exist in the remote repository, it's OK if it exists in the local repository. So what I did to finally make everything work is just mvn --non-recursive install the parent POM before using versions:update-parent.

    All in all I do this now (-N is --non-recursive, ${v} resolves to e.g. 1.0.0-changed-SNAPSHOT):

    mvn -f parent release:update-versions -DautoVersionSubmodules -DdevelopmentVersion=${v}
    mvn -f parent -N install
    mvn -f parent/aggregator-d -N versions:update-parent -DallowSnapshots -DparentVersion=[${v}]
    mvn -f parent/aggregator-t -N versions:update-parent -DallowSnapshots -DparentVersion=[${v}]
    

    This solution is not very pretty but i favor it over using regex or deprecated Jenkins API.