Update pom.xml if parent or certain dependencies have newer versions available, Jenkins pipeline with maven? - 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.

Related

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:*:*:*:*

Versions Maven Plugin : do not update to last release available

Let's consider I have a dependency in my pom.xml like this :
<dependency>
<groupId>mygroupid</groupId>
<artifactId>myartifactid</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
For each build, I'd like the version of this dependency to be updated if the release exists.
Thus, I expect the version to be updated from 1.0-SNAPSHOT to 1.0, even if version 2.0 has been released.
It's possible with Versions Maven Plugin, executing mvn versions:use-releases. Fine.
Now, the version is set in a property. The pom.xml looks like this :
<dependency>
<groupId>mygroupid</groupId>
<artifactId>myartifactid</artifactId>
<version>${my.version}</version>
</dependency>
<properties>
<my.version>1.0-SNAPSHOT</my.version>
</properties>
Same as before, I'd like like the version of this dependency to be updated if the release exists.
It looked possible with the same Versions Maven Plugin, executing mvn versions:update-properties. But, with this goal, the version is updated to the last release available (e.g. 2.0 in our case) instead of 1.0.
Any idea of how to get the same behavior as use-release goal with update-properties goal ?

Maven copy parents declared in the POMs

My final goal is to create a Maven repository in a certain directory containing only a certain set of artifacts and all their dependencies.
For this I use the following command:
mvn.bat dependency:copy-dependencies -f dependencies.pom
-DoutputDirectory=localRepoDir -Dmdep.useRepositoryLayout=true
-Dmdep.copyPom=true -Dmdep.addParentPoms=true
dependencies.pom being:
<project>
<modelVersion>4.0.0</modelVersion>
<description>Dependencies</description>
<groupId>com.dummy</groupId>
<artifactId>dummy</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.dependency1</groupId>
<artifactId>dep1</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.dependency2</groupId>
<artifactId>dep2</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
When doing this, I notice that parents declared in the dependencies' poms are not copied from the .m2 Local maven repository to the destination directory.
Perhaps I'm missing something and there's a better way to do this, since it's kind of a hack to use a pom file to declare the artifacts I want to copy (together with their dependencies).
Turns out that maven was using version 2.8 as default for the dependency plugin. When explicitly indicating it to use the latest version (2.10), it worked just fine.
The addParentPoms parameter was already introduced on 2.8 for copy-dependencies, so I guess it must be a bug in the 2.8 release.
mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:copy-dependencies

Adding A Group of Files to a Local Maven Repository

I have an existing java project. It is a maven project. I want to add it to my local maven repository for reuse in other projects.
MyUtilityClass.jar
MyUtilityClassSources.jar
MyUtilityClassDocs.jar
Dependent on
slf4j-1.7.2.jar
junit-4.11.jar
This SO Question/Answer gives instructions for adding a single file to a local maven repository using mvn install:install-file
This SO Question/Answer gives instructions for adding a group of jars - sources, javadoc, etc. using mvn deploy-file.
This SO Question/Answer alludes to specifying dependencies via a pom.xml file, but doesn't provide details.
I have two tasks in front of me that I'd like to accomplish:
add the project for MyUtilityClass to my local repository, with sources, docs, and dependencies automatically added when I pull them in.
I'd like to create a maven task for the MyUtilityClass project that adds the latest and greatest bundle to my local repository.
I am using eclipse as an IDE and maven version 3.0.4. The POM for this project looks like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.local.mine</groupId>
<artifactId>MyUtilityClass</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyUtilityClass</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>com.local.mine</groupId>
<artifactId>slf4j</artifactId><!--from local repo -->
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.local.mine</groupId>
<!--from local repo and shouldn't be automatically added -->
<!-- to projects that reuse the resulting bundle -->
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
The easiest way to do this is to think of each project as their own release cycles. They should be independant of each other.
As you have discovered, you can
use install to install the artifact to your local repository
use install-file to install secondary artifacts to your local repository
use deploy to so the same steps as install(-file), but to remote repositories
What also does this is the release plugin. When you perform the pair goals of release:prepare and release:perform, you end up with
version values update in the pom files
version control tags created
the artifact installed & deployed
any source and/or javadoc artifacts deployed
What you want to use is the release plugin.
The simple solution is to use
mvn install
in the project you would like to reuse. This will install the artifacts of your project into your location repository.

Fully automate release procedure with release+versions plugins

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.

Resources