How to version number a project? - maven

I have a maven multi-module project with more than 6 children modules in it. If a team of 3 is working in parallel taking 2 sub-modules each as their task, then how to increase the version number.
whereas I am following Major.minor.patch-meta format for version numbering in release cycles.
Project A
-- sub-module-assembler
pom.xml
-- sub-module-1
-sub-sub-module-1 pom.xml
-sub-sub-module-2 pom.xml
pom.xml
-- sub-module-2
-sub-sub-module-1 pom.xml
-sub-sub-module-2 pom.xml
pom.xml
-- sub-module-3
-sub-sub-module-1 pom.xml
-sub-sub-module-2 pom.xml
pom.xml
-- sub-module-4
-sub-sub-module-1 pom.xml
-sub-sub-module-2 pom.xml
pom.xml
-- sub-module-5
-sub-sub-module-1 pom.xml
-sub-sub-module-2 pom.xml
pom.xml
-- sub-module-6
-sub-sub-module-1 pom.xml
-sub-sub-module-2 pom.xml
pom.xml
--pom.xml
Exact usage of incrementing and decrementing version numbers in parallel programming, Whereas the key thing to be notified in this is some sub-modules in that project totally depends upon some other sub-module, if that is the case then how to version number exactly while the development goes parallel as well in certain order ?
I am not clear about the below but is this right way of version numbering
Should i need to do meta release in case of bug fix e.g alpha, beta , gamma etc.,
Should i need to do a patch release in the case of completion of a feature[sub-sub-module-x] in a sub-module whereas i am using second level+ sub-modules e.g 0.1.1-alpha, 0.1.2-alpha etc.,
Should i need to do a minor release in the case of completion of a sub-module e.g 0.2.0-alpha , 0.2.0-RC etc.,.
So after integrating all the RC's 0.2.0-RC + 0.3.0-RC + 0.4.0-RC etc should i need to do a major release as 1.0.0-RTM etc.,
So understanding the above flow is bit cofusing ..
Is there any way to automate the build numbering in a project so as to maintain clear build release numbers. Please provide a solution.
Thanks

I suspect there will be no answer for all versioning strategies. But let me try some hints that may help you choosing a strategy that is appropriate for your situation.
The project looks rather big. The first grouping I would do is by responsibility. Are there modules that are restricted to a certain development team? Or is the whole thing maintained "all-in-one"? Hopefully you are able to split it up a bit.
Once you know about module(s) responsibilities you need to define some life-cycle. How and how often is a release (or bugfix, patch) created and by whom? If everyone follows the same rhythm you can share one version and release the whole tree. But usually this is not the case in larger projects. It also introduces side effects during development if a lot of people share one version.
If you do not plan to release the complete tree all at once you may split it more consequently. You can still use a common parent pom.xml (but one with a released version).
I would define one version for modules in a parent pom.xml and inherit it. So no individual version in submodules. Furthermore every team that depends on other modules should not use SNAPSHOT dependencies to work of other teams. They may only use a released version (be it BETA or RC1). It is important to keep builds reproducible. E.g.: "no snapshot dependencies to artifacts you are not in charge of (you control what changes and when)"
As for the versioning itself: in doubt the simpler option may be better. All the meta information may only confuse about the actual state?
What may also be of some use is to draw a deployment pipeline: what module comes first, which ones depend on it and so forth. The amount of changes in one module define how the version changes (major, minor, patch change). If those changes do not propagate across modules (the API stays stable, which is your goal) the next module may only do patch releases.
If you have not yet released anything, plan ahead. Every iteration is usually an API change (therefore it actually would be a major release). That would lead to version 18.0.0 to be released (after 18 iterations). So usually the minor version is used to indicate iterations and patch versions indicate some fixes to stabilize that release. So major versions are chosen more from a marketing aspect than from a technical one.
It also depends somewhat on the type of software you build (a product, an in house-solution, some additional service for your landscape). Products have a much clearer versioning, they usually use the META part to indicate iterations and the major.minor.patch numbers to indicate what is going on. That strategy ("indicate what changes to expect") may help for what you are doing as well?
So hopefully this did not raise more questions than you had at the beginning :)

Related

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.

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.

One (multi-module) maven project per svn trunk or not

My usual practice is to have a single maven project (can be multi-module) per svn trunk like this:
trunk/ (style 1)
/pom.xml
/submod-1
/submod-2
Basically, the entire trunk is treated as a single release package. I find this easier to manage. There's an aggregation/parent pom to manage all modules within this trunk.
However, i noticed some of my peers organize like this:
trunk/ (style 2)
/project-1
/pom.xml
/project-2
/pom.xml
Basically, within the single svn trunk...project-1 and project-2 needs to be managed separately. i.e. I cannot checkout the trunk and work with its contents as a single multi-module maven project -something i appreciate.
Q1: When would style 2 be a good idea, if at all?
Q2: Can someone tell/point me to best practices on how to manage maven projects with subversion?
I have seen instances of both.
In my opinion, it depends on how independent the projects/modules are. If they have their own release plans, then it makes sense for them to have their own trunk, branches and tags. However, if the projects/modules are always released together, it may make sense for them to be part of a single trunk.
From a maven perspective, if the modules of a multi-module project inherit their <version> from the parent, then it should follow style 1 above.
I pretty much agree with #Raghuram's answer, but would like to add the following:
If you want to release projects together with the same life cycle and the same version number, you need the Style 1, with the parent POM in the root of the trunk. This parent POM then usually includes the sub projects as modules to be built from the root.
Style 2 makes sense if you have a set of independent projects (e.g. utilities), where you want a single SVN location (for easier administration), but have different release cycles. In this case, you don't need a root aggregator POM that includes the single project as modules. It might still make sense to have a common parent POM for the utility projects that centralizes things like compiler settings and plugin management. The difference to Style 1 is that you would never release all of the projects together. You would release a stable version of just the parent POM and then release the single utility projects as needed.
We have used both styles with great success - the main difference really is in the way and frequency you use for releasing.
With Style 2 (and the utility project example) I don't see an issue if these projects share the same SVN tags and trunk. A developer can still decide whether he wants to check out the whole utility trunk or just a single project.
Just look at this question and at least its most-up answer. It actually summarizes the case and says pretty everything about it.
Just think to continuos integration:
This thought make first approche more flexible to use with CI servers like jinkins, bitbucket or bamboo ...

Automating Maven artifact releasing

For a project with a large number of Maven artifacts (both internally generated as well as external ones), how does one go about automating the releasing of the internally controlled artifacts as part of an overall product release.
Things to be aware of about this question, we use Jenkins and the Maven release plugin. So the operation of releasing a single artifact is automated (albeit the operation to kick-start the process is manual). However the process of releasing all the changed artefacts over the course of a release is not automated (i.e. one has to manually kick-start the release of each artifact). Part of the problem is that almost nothing is released until the end of the release, prior to that everything remains in SHAPSHOT. We have a huge number of components as well as numerous applications/services (over 30) which rely on the plethora of components. So it is not just the case of picking a component and releasing, there are release dependency hierarchies that must be followed (i.e. start at the bottom releasing components that do not use other components and then work your way up until all the applications/services are released).
It is also worth noting that we use two common parent poms which, for the most part, control the versions of the external artifact dependencies and the internal component dependencies. Some pom files for components and applications may override this, but this is (or should be) an exception and should be for a good, but temporary, reason. So when an internal artifact is released, the version in the corresponding parent dependency pom should also be updated.
The product has a release number (of course), however the various pom files technically do not share this version number. While this is not strictly true, the idea as that when parts of the software are set to end-of-life, they will not be updated in the future, thus while a limited number of artifact versions match the product's version at present, this will eventually not be the case.
Any thoughts on ways to get this process automated would be greatly appreciated. Also if you feel what I have described seems to be a crazy way to manage the software, then please provide a comment. Thank you.
You might be able to make use of the Maven Versions plugin which can help formalise versions for projects.
For example, the use-next-releases goal may allow you to release the lowest level of project and then more rapidly bring those released versions into their dependencies.
There may also be scope to use the use-next-versions goal if you fancy releasing components as necessary and simply bring your projects to the "latest" version thats been formally released.

Maven : Multimodule projects and versioning

What are the best practices for software versioning and multimodules projects with Maven?
I mean, when I create a multimodules project with Maven, what is the best approach for the versioning? To use a single version for all the modules (defined in the top project)? To use a version for each module (defined in the POM of each module)? Is there another approach that I'm missing? What are the pros and cons of each approach?
In general, are the different modules released together (possibly sharing the same version number)?
Thanks
Honestly it depends on what you would like to do. Multimodule projects are created for multiple reasons, one of them being you only need to deploy what has changed instead of all modules.
Think about it this way: if you had a non-multi-module project and you only had to change one line in the services layer, you have to rebuild the entire project and deploy all of the code again...even though only your services layer will change.
With multi-module projects, you can regenerate your project and deploy only what changed...your services. This reduces risk and you're assured that only your services module changed.
You also have a multitude of benefits to using multi-module projects that I'm not listing here but there is certainly a huge benefit to NOT keeping your version numbers of your modules in sync.
When you build your project, consider deploying it to a repository that will hold all compatible jars together for builds (each build creates a new folder with the parent-most pom version number). That way, you don't need to keep documentation about which jars are compatible...they're all just deployed together with a build number.
I was looking for a solution for this exact problem myself and versions-maven-plugin was exactly what I needed. I don't like the release plugin communicating with the SCM system. The versions plugin does just what we need: it sets a new version number in all poms of the project:
mvn versions:set -DnewVersion=2.0.0
Then I can proceed with commits, tags and an official build server build...
EDIT:
The versions plugin depends on how a maven multi-module project has been organised: as a result, it often does not update all POM files in a complex multi-module project.
I've found that sed and find do the job much more reliably:
sed -i 's/1.0.0-SNAPSHOT/1.0.0-RC1/g' `find . -name 'pom.xml'`
Typically you create a multi-module project because you have deemed that the various modules are parts of a single whole. Maybe the client-piece, the controller-piece and the services-piece. Or maybe the UI with services.
In any case, it makes sense to have the version numbers for the various modules to move in lock-step. However Maven does not enforce that as a rule.
As to your question
are the different modules released together (possibly sharing the same
version number)
I would think so. That is one of the reasons for having it a multi-module project. Otherwise you could have the modules as independent projects.
Of course this is the kind of stuff that is rife with edge cases and exceptions ;-)
I had the same problem with a project I`m working on. I also decided to use separate versions and even the dependency to the parent pom only has to be updated if some of the managed dependencies change. (so mostly as #vinnybad describes it)
Two additions
exists-maven-plugin
With the usage of the "org.honton.chas.exists-maven-plugin" only the modules will be deployed to the repository that have actually changed, which is really great, because also the according docker-images will only be published if something has changed on one of the service. This avoids "polluting" the image repository with different but unchanged versions.
versioning
One main downside of the "separated versions" approach are the questions regarding versioning:
What's the current version of my project?
Which module versions work with each other? (even thought they don't directly depend on each other, one does rely on what another does, e.g. they share the database schema)
To solve that I put all module versions into the dependency management part of the parent pom, even if no other module depends on them. A "integration-test" module could solve that by depending on all of the modules - and of course testing them together.
This way I would be "forced" to update the parent pom with every change, since it's referring the released module versions. This way the parent pom would have the "leading" version and at the dependency-management block state the versions of all modules that are compatible with each other (which will be ensured by the integration test).

Resources