Manage dependency version centralized - maven

I've got multiple projects using a certain Dependency of Version XX, if I release a new version, I have to touch every project to change it to version XX.Y.
I've came across an approach to edit my m2 settings <version>${my.version}</version>, to add a parameter and bind it into my POM.xml, but this implicit means, everyuser has to manage their m2 settings when I do a new release.
Is there a way to central (user independant) manage the versions as in SVN, so none has to change anything and it always uses the up2date version, if I release a new version?

In general, the maintainer of every project should decide for themselves if they update the version or not. Updating the version might break things, so they may choose to stay on the older version. Particularly, it is important that the maintainers notice that something has changed, so that tests are run.
For development, though, there are Snapshot versions. A Snapshot dependency always references the newest version, but the -SNAPSHOT indicates this to the maintainer of the project. Snapshot versions should not go to production - the builds are not reproducible.
If artifacts are so tightly coupled that they are build together, think about using multi module projects.

You can use a pattern called "Bill of Material".
I think your question is somehow similar to this question (but not exactly a duplicate), and my answer applies here aswell:
You create a new maven project (the bill of material) that only consists of a pom with dependency management block. Here you declare all your dependencies and their versions. The packaging should be set to pom.
This bill of material (bom) project is now used as parent of all other projects. When using a dependency, only group id and artifact id is specified, the version tag is ommited. In that way, the version will be taken from the bom and you have one central place to manage the versions of the dependencies.
More details with examples are here (in the lower part of the page) or here.

Related

Best practice to change version of dependencies in nexus

Consider a project that is used in other projects, and this project has version 1.0 and is present in the Nexus.
After that, some changes are done in this project.
Now there are two solutions:
Increment the version of the project to 2.0, and delete the version 1.0 from Nexus. When the developers try to get the dependencies from the Nexus with version 1.0 they will get an error that this version does not exist and need to change the version to 2.0.
Change the functionalities of this project and inform the crew that some changes are done, but this is not the practice at all.
Is there any functionality in Maven and Nexus to simplify this task and make this all happen in the backend so the developers can't do anything, or is this not possible?
If you have an old version of an artifact that must not be used anymore because it has some dangerous bug, or it does not work with the new database structure or something like this, it may be advisable to move it to some non-public Nexus repository (and also delete it from the local repository of the build server), so that nobody can use it for release builds (people can use it for local builds, but this is usually not dangerous).
If you want to manage standard versions throughout your company, it is a good idea to have a parent pom or some boms which collect versions in a <dependenyManagment> section and can be included by the developers. This way, you only need to inform them to change one version number (namely the one of the parent pom or bom) instead of many.
Still, you are left with the problem that people do not read company newsletters. I know the problem that many developers of jars compile and test their source code against very old versions of their dependencies while the war/ear (that includes the jar) uses new versions.

Promoting semantically versioned artifacts when an upstream dependency has changed

I am in the midst of an initiative to convert our build.gradle files to use semantic versions. In addition to using Gradle, we also use Git and are following the Gitflow Workflow. Jenkins is used to build the projects.
Versions for released artifacts follow a MAJOR.MINOR.PATCH format. When declaring dependencies in the build.gradle file, we use dynamic versions, such as 10.0.+ (i.e. take the latest 10.0.PATCH version).
We promote our artifacts from a Release Candidates repository to a Releases repository in Nexus. The repository has its policy set to "Releases". Because of the complexity of the product (200+ projects, with many upstream and downstream dependencies), a lot of the promotion plugins available for Jenkins appear to fall short. We were thinking of having Jenkins build the master branch as a way to rename artifacts (10.0.0-rc.1-abcdefg becomes 10.0.0) and upload them to the correct Nexus repository.
I am unsure of how to handle a situation where an upstream dependency has a patch version incremented. The downstream project - a WAR - is re-built by Jenkins and bundles the new JAR, but the version of the downstream project doesn't change. When an attempt is made to upload to Nexus, it fails because only one artifact can have the same version.
Here is an example:
The Releases Nexus repository has upstream-api versioned at 10.0.0, and downstream-project versioned at 10.0.0
downstream-project depends on 10.0.+ of upstream-api
upstream-api.jar is bundled into the downstream-project.war file
The two artifacts are deployed as part of Release X of the product
When a hotfix branch has been merged into master, the upstream-api version has changed to 10.0.1
The fix means that when deployed, the product is now Release X'
downstream-project stays at 10.0.0, but is re-built because of the change in the upstream dependency
Jenkins fails to upload downstream-project-10.0.0.war to Nexus because it already exists
I could have the old artifact replaced with the new artifact, but then that means that Release X can no longer be deployed from artifacts in Nexus (eg. in the case of a rollback, or needing to replicate an issue on an older release).
How is this typically handled?
How is this typically handled?
I don’t have a universal answer here. I would assume that these are the most “common” possibilities:
Don’t distribute your dependencies with the release and continue to use dependency version declarations such as 10.0.+. The assumption is then that the software will indeed work with any 10.0.x version – at least as far as your users will tolerate it. That usually happens for free software which is distributed in source or in a package system of a Linux distribution. The dependency version declaration is only updated when there is a required improvement in the dependency, i.e., when the change is so important that your users won’t tolerate any earlier version.
Distribute your dependencies with the release and either:
Use a build number in addition to the main/semantic version number of the original code – for example 1.3.4-b3. If I’m not mistaken, then this is often being done for proprietary Windows software.
Increment the main/semantic version number when a dependency changes and make the dependency requirement explicit.
Some more General Thoughts on the Issue
I think the core issue is the dynamic dependency declaration – the 10.0.+ version declaration. What you state with this declaration is that your release will work equally well with any 10.0.x version.
If that is really the case, i.e., the bugs that are fixed by a patch in the dependency are guaranteed to never affect the release, then your release should probably simply not be rebuilt, since its functionality wouldn’t change anyway. The version of the dependency wouldn’t matter, your release could stay with the older dependency version.
More likely, though, the upstream bugfixes will also make a difference in your downstream project, i.e., they will affect the functionality of the release. In that case you should make the “new” dependency explicit in your build.gradle. Since that’s a change to your release artifact, a new release version is due.

Maven aggregate pom skip released modules

This is probably supported, so I apologize if the answer is trivial, but I can't find an answer.
I have a multimodule (aggregate) pom containing a number of modules with interdependencies. Let's say something like:
infrastructure
framework
business-module1
business-module2
At a certain moment, infrastructure is stable, so I can release it. The version is updated to 1.0 and all dependencies to it are updated to that version as well.
When doing a local install, the module is still build. I know want to avoid building the 1.0 version locally, since it is released and costs build time. The question could be rephrased to, never build a released module.
I have quite a lot of modules in a multimodule setup, and only want to build snapshots. I know that I can skip modules using command line options, but don't want to repeat all these modules. Besides, from the version declarations, it should be clear to maven which modules to build.

Managing Versions of dependencies

What is best way of managing versions of dependencies?.
Generally I would create a super POM (Not Parent POM) and I would declare all my dependencies in the super POM. So that all my projects can refer that POM for the dependencies. The advantage is that all my dependencies are controlled from a central POM.
But if we are developing some products selling to different clients year after year and also dependencies versions get updated year after year. How will I keep track of my dependency versions of products I released to each client?.. I don't want to keep updating my POM every time a dependency version needs to be updated.
So I was thinking of keeping the version of dependencies in my settings xml as properties and settings can be updated or version-ed per release.
I am experienced in Maven but not an expert. Any good suggestions?...
Thanks In Advance
Joseph
Put all your version in the dependencyManagement of the parent pom. (as you do now, that's why dependencyManagement exists)
To keep track of old release : use a tag in SCM.
settings.xml in not part of the project! it is there to contains properties and data about the build environment (i.e. not the project).
don't mix dependencies of different projects. It seems a very bad idea (it means that if you uddate a widely used dependency (like hibernate for instance) for one particular customer: it will be updated for all your projects. And so you will have to re-validate all your projects against the new version of hibernate)
And just a little question, what difference do you make between versioning your settings.xml and versioning your parent pom ?

Update dependencies in Project B when Project A is released

I have two multi module projects. One is the main project tree. The other project tree pulls in the artifacts (WARs, JARs, etc) from the first project. They each have their own separate parent pom.
I would like to keep their version numbers identical. Project 2 has a dependency management section that has the artifacts from project 1 in it. The problem with this is that I can't release the project due to snapshots.
For example. The version number (for both projects) is 3.4-SNAPSHOT. I can release a version 3.4 of project 1 and all the pom versions will be set from 3.4-SNAPSHOT to 3.5. When I go into project 2, I want to do the same exact thing. The hitch is that dependencies of project 1 are at 3.4-SNAPSHOT and I can't figure out how to automatically get them to be 3.5. It's like I want the dependencies to be updated to the release version, before actually releasing.
I understand that if I make both trees extend from the same parent pom, the maven release plugin would detect the dependencies as submodules and update them automatically.
I read a little bit about the versions plugin but I didn't like the use-latest-versions part of it (it seems way to dangerous). The Update-properties seemed promising but it upon a second cursory look, it looked like the use-latest-versions plugin packaged slightly different.
Also, I tried just using ${project.version} but that's basically the same as putting 3.4-SNAPSHOT in as the dependency - it'll error saying it can't release due to snapshots since the version actually hasn't been updated yet.
The way you have the projects configured they are totally independent. You might as well be asking for the version of your log4j dependency to be the same as your current project B version.
While it won't be automatic, you should replace the versions of all references to Project A within Project B to use a property that is defined in the parent pom for Project B. Then, when you release Project A, you only have to change one pom so the project.a.version property is now the released version instead of SNAPSHOT. After the release of B you could then change it back to ${project.version} to keep them in sync.
As you admit, the right answer here is to re-arrange your project to have a common parent. Anything else is just a workaround.
However, it looks to me like versions:use-releases might achieve your goal. You can specify an includes list to ensure only project 1 dependencies are updated.
If you wanted this to be automatic, you could consider binding this goal to one of the lifecycle phases prior to compile.
Edit: sadly this looks like its not possible. At least, that's how I understand by the "Executes by direct invocation only" mentioned at the top of the page.

Resources