Fully automate release procedure with release+versions plugins - maven

Would be great if Maven guru community can help me with the following task.
I would like to automate the release process of Maven module in Hudson in a way that release process runs in batch mode (does not need anything to be asked from console). Currently I use common steps release:prepare (with <preparationGoals>versions:update-parent clean verify</preparationGoals> to update parent to latest version before commit) + release:perform. However I would like Maven to do the following:
Somewhen during preparation step:
For all dependencies which match the groupId of the current module and parent, replace -SNAPSHOT with released version (e.g. versions:use-releases -Dincludes=???).
Somewhen after release:
For all dependencies which match the groupId of the current module and parent, replace release version with -SNAPSHOT version (e.g. versions:use-latest-snapshots ...).
Example:
<parent>
<groupId>org.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myproject-api</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
before module is tagged is transformed into:
<parent>
<groupId>org.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.0</version>
</parent>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myproject-api</artifactId>
<version>1.1</version>
</dependency>
and after release is succeeded is transformed into:
<parent>
<groupId>org.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myproject-api</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
I feel like it needs a mixture of
versions:use-releases scm:commit release:prepare release:perform versions:use-latest-snapshots scm:commit
but I am not sure what is the best way of doing this. Especially it would be nice to have as less commits as possible: the difficulty is that reparationGoals are run after -SNAPSHOT version check.
The described project is not a multi-module project in a sense that parent POM is not referring it's children via <modules>. SCM structure is the following:
.
|
+-- myproject-parent
| +-- pom.xml
+-- myproject-api
| +-- pom.xml
+-- myproject-impl
+-- pom.xml
Dependencies are:
myproject-api → myproject-parent
myproject-impl → myproject-parent
myproject-impl → myproject-api
The project's parent POM (myproject-parent) will be released rarely and thus will be released first. Then myproject-api (if necessary) and then myproject-impl.

The simple problem you have is that your parent has a different version number than your childs which is the wrong way for a mulit-module build. A multi-module build is intended to have a number of modules related which have the same release process from which follows to have the same version number. If you follow that guideline you don't need the versions plugin you only do the release via release:prepare and release:perform That's it.
Update:
After the further discussion I would suggest to setup a new set of Hudson jobs which contain the dependencies between the modules (downstream/upstream deps.) and do a release on each hudson job which triggers the next in the string of the jobs and so on. This prerequisites to have separate modules and separate areas in the version control as well. Otherwise this fight will be lost with Maven and complicate the life.

Related

Update pom.xml if parent or certain dependencies have newer versions available, Jenkins pipeline with maven?

Trying to figure out the right approach for updating pom.xml if parent or (certain) dependencies have updates available in nexus repository, and only then build new artifact with Jenkins.
So basically, build new version of 'Testing-app-for-version-update' if there are new releases of parent or dependency apps.
App pom looks like:
<version>1.0.0</version> // <-- Version to update
<name>Testing-app-for-version-update</name>
<packaging>pom</packaging>
<parent>
<groupId>com.test.testing</groupId>
<artifactId>testing-parent</artifactId>
<version>1.0.0</version> // <---- Update pom version if never version
</parent>
<dependencies>
<dependency>
<groupId>com.test.testing</groupId>
<artifactId>app2</artifactId>
<version>1.0</version> // <---- Update pom version if never version
</dependency>
<dependency>
<groupId>com.test.testing</groupId>
<artifactId>app3</artifactId>
<version>1.0</version> // <---- Update pom version if never version
</dependency>
<dependency>
<artifactId>dependency1</artifactId> // <--- No need to update pom version
<version>1.0</version>
</dependency>
<dependencies>
I was wondering about using:mvn versions:display-dependency-updates, but reading the output feels a bit "hackish" approach.
Is there way to use mvn for this?
Comparing the pom versions to released artifacts also feels glumsy? Any other solutions how to create Jenkins pipeline for building new app version, when pom.xml needs to be updated?
Also calling this after app2 or app3 build pipelines are finished, is problematic as the pipeline would be called twice, once the app2 has finished and again app3 has finished. So I would like launch this "update app version" pipeline manually. And I have other applications where version needs to updated as well.

Maven: automatically update only some libraries to their latest version

I have created a parent pom project and some libraries that I manage.
So, for example:
<parent>
<groupId>my.group</groupId>
<artifactId>parent</artifactId>
<version>1.2.3-SNAPSHOT</version>
</parent>
<dependencies>
...a loooot of them
<dependency>
<groupId>my.group</groupId>
<artifactId>lib</artifactId>
<version>1.2.3-SNAPSHOT</version>
</dependency>
..otheeeeers
</dependencies>
Now, I'd like to always use the latest release or snapshot depending I'm on the develop or release branch.
Problem is that the "new" maven 3 approach only has:
mvn versions:use-latest-releases //release
mvn versions:use-latest-versions //snapshot
But this would update every other dependency and I don't want this! I just want to update the ones having groupId my.group.
Is this possible?
edit:
Following khmarbaise advice I'm using:
mvn versions:use-latest-versions "-Dincludes=com.project.my::::"
But it seems that it only works for non-snapshot versions.
ie. If I define 0.0.2 version of my lib it works, while 0.0.2-SNAPSHOT is not seen..is this normal?
Another thing I noticed is that it only works for inline properties, for example this will not work:
<my-lib.version>0.0.1-SNAPSHOT</my-lib.version>
<groupId>com.project.my</groupId>
<artifactId>mylib</artifactId>
<version>${my-lib.version}</version> <--- undetected, I need to put 0.0.1-SNAPSHOT explicitely
Following the advice of khmarbaise, just call something like
mvn versions:use-latest-releases -Dincludes=mygroup:*:*:*:*

Jenkins fails to build multi-module Maven project

I have a multi-module Maven project where I have multiple micro services as modules so I have modules listed in my parent pom.xml like below:
<modules>
<module>core</module>
<module>model-base</module>
<module>module1</module>
<module>module2</module>
...
<module>module5</module>
<module>module7</module>
<module>module6</module>
</modules>
Here the module7 is dependent on module5, 6 so I have dependencies listed like below in my module7 pom.xml:
<parent>
<artifactId>pojectA</artifactId>
<groupId>com.domain</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>module7</artifactId>
<dependencies>
<dependency>
<groupId>com.domain</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.domain</groupId>
<artifactId>module5</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.domain</groupId>
<artifactId>module6</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
When I run mvn clean package in my local the module5, 6 called before the module7 as expected but in Jenkins it is trying to build module 5 then module7 making build fail saying:
[ERROR] Failed to execute goal on project module7: Could not resolve dependencies for project module7:jar:1.0-SNAPSHOT: Could not find artifact module6:jar:1.0-SNAPSHOT -> [Help 1]
Do I need to run any other jobs or re-order the modules in my pom.xml, how is it differ from local to Jenkins? Appreciate any help on this.
The order of modules is not relevant. Maven recognizes which project depends on which other project(s) and sets the build order in the reactor accordingly. See POM Reference, Aggregation (or Multi-Module):
You do not need to consider the inter-module dependencies yourself when listing the modules, i.e. the ordering of the modules given by the POM is not important. Maven will topologically sort the modules such that dependencies are always build before dependent modules.
Add Pre-Step as per below attached screenshot. This will compile all your top modules.
Then we can execute which ever module we want.
As is probably quite well understood, the issue is that the dependencies between the child modules fail because they aren't installed in the local repository yet (because they are yet to be built). The goal that causes this (for me anyway) is mvn test, which is invoked by mvn package. Your local build probably works because at some point you've done a mvn install and this has bootstrapped your system.
In Jenkins the only way I've found to make these builds work is to use the Pre-build step invoking a Maven target of install, and then build the main step as usual.

How do I default sub-module versions in a Maven multi-module project using snapshots?

I looked at previous questions on the topic and it seems people were a step ahead of where am I at the moment.
I am currently trying to use the maven release plugin to my multi module project. I start from scratch (more exactly, I retrieved some old projects to put in a new multi module project).
I have a POM parent that I defines as:
<groupId>com.somestuff</groupId>
<artifactId>stuff</artifactId>
<version>10.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name> stuff </name>
My child modules inherits the parent using:
<parent>
<groupId>com.somestuff</groupId>
<artifactId>stuff</artifactId>
<version>10.0.0-SNAPSHOT</version>
</parent>
So since it’s a new project, I specify the dependencies between modules as snapshots. For example, if module A depends on module B, I will add to A’s POM the part:
<dependencies>
<dependency>
<groupId>com.somestuff</groupId>
<artifactId>divarmiclient</artifactId>
<version>10.0.0-SNAPSHOT </version>
</dependency>
</dependencies>
The result is when I try to do a “mvn release:prepare”, Maven will yell that there is snapshot dependencies. But since it’s a whole new project, and that versions prior to 10 don’t exist, I have no idea how to default the version values of the modules.
My question is, how shall I default the module values ? How do I do in order to make my multi-module project acceptable from a snapshot perspective ?
For clarification, you're saying your structure is:
theparent
pom.xml
A/
pom.xml
B/
pom.xml
And the following assumptions all hold true:
theparent, A, and B are currently on same version
releases will always be kicked off from 'theparent' level so they remain on same version
A depends on B, always same version
Then the solution is as follows:
<dependency>
<groupId>com.somestuff</groupId>
<artifactId>B</artifactId>
<version>${project.version}</version>
</dependency>

how to handle versions in maven?

I have all these version numbers throughout parent pom and children poms including the parent reference like so
<parent>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-core</artifactId>
<version>${parent.version}</version>
</parent>
and dependency references to other child projects like so
<dependency>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-shared</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
and finally the declaration of the version of the thing we are building
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>artifcat</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ifp-shared</name>
<url>http://maven.apache.org</url>
EDIT based on some answers which solved half the question...
We want to have all the versions be ${project.version} since it is really just one project with one release number.
I can seem to do ${project.version} in the dependency but this does not work in the parent xml code above. Is there another way? (man, I should really just switch to gradle).
thanks,
Dean
<parent>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-core</artifactId>
<version>1.2.3-SNAPSHOT</version> <!-- real version-->
</parent>
<artifactId>blah</artifactId>
<!-- No version here, will be inherited -->
<dependency>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-shared</artifactId>
<version>${project.version}</version>
</dependency>
project.version is what you want. Not parent.version.
You need to use dependencyManagement tag to centerilize the versions in the parent pom for the dependencies.
See this question and answers
differences between dependencymanagement and dependencies in maven
For you your own modules, some of the properties are inherited from the parent pom. You will need to declare the parent version in each child but you don't need to declare a groupId/version in your child poms if you want them to be same as their parent's.
We switched to gradle which works fabulously now. Every automated build a new version is released as 1.2.x where x is the next build number. Downstream, projects depend on 1.2.+. This allows every release to be official so QA can test it, reject it or go, yup, build 1.2.568 is the release we will release to the world. Projects can depend on 1.2. but then they don't get bug fixes. This seems to work much better than all that snapshot nonsense as you give QA a snapshot and they approve and you have to change and do another build. We want every build to look official so they can release the one that happens to pass all QA tests.

Resources