Maven and snapshots? - maven

I'm working on a rapid project, of which, I'm directly working on a module that is continuously changing. Others have a direct dependency on the module, and as such, I stubbed out the public interface and deployed it to our local Nexus repository as 0.0-SNAPSHOT for use.
Now that I've almost completed my first iteration of the module, I've attempted to redeploy the updated artifact. Reading about snapshots, others claim that a snapshot should represent the current head trunk. Is this true?
Maven automatically increments my snapshot version upon redeploy - so, going from 0.0-SNAPSHOT, I'm still at 0.0-SNAPSHOT, only, it's iteration 3 or 4 of the same snapshot. When should I roll over to 0.1-SNAPSHOT? Is there a plugin I can use to automate the version change, instead of manually editing my pom?
After integration testing and the deployment of our first system release, 1.0-RELEASE, how should my module progress? Should I move my module to 1.0-SNAPSHOT and continue thereon? Is there a methodology one should follow, or is it left to the discretion of the developer?

The X.Y.Z-SNAPSHOT notation identifies temporary versions leading up to release X.Y.Z, so you usually do not move from X.Y.Z-SNAPSHOT to X.Y.Z+1-SNAPSHOT unless you release X.Y.Z. If you adhere to this convention the maven-release-plugin may help you with the full release process.
Note that the most common Maven convention uses 3-number release identifiers without any suffix (i.e. no -RELEASE). Suffixes are usually used to distinguish variants of the same release.
Maven is all about conventions, so there's little chance you'll go very far without reading about it: This book is a good starting point.

For updating your POM version without manually updating, you may take a look at Maven Release plugin (Although I wrote myself a little script to do the POM update as I find Release plugin don't fit that good in my work flow)
It then come to your version number issue. It is more a release procedure issue. Normally a planned release is denoted by increment of Major or Minor version in the version number. SNAPSHOT version denote that certain release is in progress. For example, I will prefer doing something like this for your case:
Assume I am planning to release first iteration as 0.1, then I will make my head trunk in SCM (e.g. trunk in SVN) with 0.1-SNAPSHOT as version. Which denotes that all development is in fact contributing to release of version 0.1. Upon finish, I'll update the POM version from 0.1-SNAPSHOT to 0.1, perform an actual release of version 0.1 (including release branching, tagging, deploying the artifact), and then change the POM version to SNAPSHOT of next planned release (for example, 0.2-SNAPSHOT).
Similarly, after releasing 1.0 (or 1.0-RELEASE in your example), POM version in head trunk should then be updated to snapshot of your next release version, for example, 1.1-SNAPSHOT.
Just bear in mind that there should no longer be SNAPSHOTs of certain version, if that version is actually released.

Understand the way maven interprets SNAPSHOTS is to clear any doubt you can have.
Extract from http://books.sonatype.com/mvnref-book/reference/pom-relationships-sect-pom-syntax.html
For example, if your project has a version of “1.0-SNAPSHOT” and you deploy this project’s artifacts to a Maven repository, Maven would expand this version to “1.0-20080207-230803-1” if you were to deploy a release at 11:08 PM on February 7th, 2008 UTC
First, Let me suggest to stick on maven conventions and change your version to 0.1 as maven archetype:generate propose.
So SNAPSHOT helps others to stay up-to-date easily with your active project. On every compilation, their projects will check new releases of SNAPSHOTS dependencies (based on that pseudo-datetime-version they have on its .m2 directory).
When you finish work on 0.1-SNAPSHOT you deploy an 0.1 and start a 0.2-SNAPSHOT or 1.0-SNAPSHOT

Related

How to manage maven dependant artifacts after creating release versions

We are using release plugin to convert snapshots to releases, but snapshots were already added as dependencies in other projects. Do we need to update every project pom, to use the new releases.
Eg: ArtifactA is included in ArtifactB,
ArtifactA is included in ArtifactC
ArtifactB and ArtifactC is included in Artifact D
Is there an alternate way to push dependent releases in place of snapshots
[We use Jenkins to build and push to Nexus]
Our build server runs versions:use-releases followed by a commit to the SVN before the build. This replaces all SNAPSHOT versions by their respective release versions if they exist.
A less cumbersome way of dealing with releases - keep using snapshots. Technically there's nothing wrong with snapshots and there's no need to change them to release versions. Just don't use versions with SNAPSHOT suffix - use resolved snapshots (with timestamp and build number).
As for the dependencies - usually there's no big need to change the version immediately after the release. It's only when clients need the updates - then they should change to newer versions manually.
If we're talking about remote API and its client lib as a dependency - such remote API needs to keep backward compatibility to give some time for others to upgrade.

Release Candidate behaving like SNAPSHOT in Maven repository

In development, I can reference the latest version of an artifact as 1.2.3-SNAPSHOT. Now I need the same behaviour for release candidates, i.e. I would like to be able to depend on the latest release candidate (there should also be a procedure for the developer to declare development versions as release candidates).
I am not sure how to implement this behaviour properly. Should I use an additional repository for release candidates and move development versions to this repository if the developer requests it? Or can I somehow define a "second snapshot list", like 1.2.3-RC?
You can get there be re-configure a few things:
use a version range for the dependency
change the updatePolicy for the repository you store the release candidates. see https://maven.apache.org/settings.html (updatePolicy). If you store the artifacts in a maven proxy usually you need to allow to overwrite releases.
Remember in a multi module build that they might upload modules before detecting a failed build (due to mvn deploy being a phase not a goal). You need to verify the complete build is ok before starting to upload artifacts in the maven repository. Or stage them somehow.
Remember this will most certainly prevent your builds being reproducible. Since an RC dependency might change between builds. You would need to change the version range - which is not always an issue. Ranges may work for you.
I've better experience to let developers stay on snapshots but have the CI server set an explicit version (for example using the versions plugin) prior to deployment / releasing for the dependency the artifact uses.

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.

How to manage Tycho / EAP versioning correctly

I have an Eclipse 4 project that is built using Tycho (0.19.0) and Maven (3.0-5)
During development of a version, say 1.0.0, the artifacts are configured with version 1.0.0-SNAPSHOT, and 1.0.0.qualifier depending on the files. When I want to release the version, I use the tycho-versions:set-version goal to change from 1.0.0-SNAPSHOT to 1.0.0.
I then build and copy the product to a remote share that publishes an update site so that older versions can be upgraded automatically at launch time.
Since I have some beta testers, I use more that one update site. One contains the stable versions, and my beta testers have one more update site to check at startup. The other one is actually an update site for snapshots that I have published, so those are not released versions of the product.
What I am experiencing seems strange: When the 1.0.0 application starts, it finds the previous snapshot (versioned 1.0.0.201312191455), thinks that those artifacts are more recent and updates itself back to an older version.
I'm guessing that Eclipse's version conventions state that x.y.z is older than x.y.z.u. Is that correct?
If so, then why does the tycho versions plugin remove the qualifier when a versions changes from snapshot to "release"? Doing so seems to make the artifacts look older than any of the snapshots. What's the correct way to handle this situation?
The answer was given in the tycho mailing list some time ago:
http://dev.eclipse.org/mhonarc/lists/tycho-user/msg01001.html
The details:
OSGi does not have a notion of "snapshot" versions, all versions are
treated the same and 1.0.0.qualifier is indeed considered to be newer
than 1.0.0.
There are two versioning schemes that result is reasonable behaviour
both for OSGi and Maven.
Use the same four part version (eg., 1.0.0.20111112-0735) for both Maven
and OSGi. This results in slightly odd version jump when going from
snapshots to releases on the maven side, i.e. 1.0.0-SNAPSHOT goes to
1.0.0.20111112-0735, but everything works otherwise.
Use even/odd convention to version snapshots and releases, i.e.
1.0.1-SNAPSHOT/1.0.1.qualifier is released as 1.0.2/1.0.2.
I think it is also possible to decouple maven and osgi versions of
released artifacts, i.e. use 1.0.0 for maven and 1.0.0.20111112-0735 for
OSGi, but personally I find this confusing and would not recommend. And
I am not sure if Tycho will allow this in the future.
--
Regards,
Igor

Maven branch update projects version automating release workflow

I have a difficult case to solve regarding the Maven automated projects versioning, I hope I'll find a proper solution based on your experience and advices.
The problem is like that:
We have a huge mavenized java product which comprise of ~200 very interdependent different projects.
We agreed that each project should be developed independently, so that each of them should have it's own lifecycle.
It's all working fine in the development stage, there is no problem. The problem comes when we are preparing the release for these projects: Because the are so many projects the manual changes are a pain so we decided to find an automated solution to solve the release process.
The prequisites are these:
We all agreed that the release policy from SVN perspective should be like that:
- all development should be performed on SVN trunk, releases should be created and maintained on branches. Each performed release should automatically create a tag.
The policy from MAVEN perspective is like that:
- before releasing a project, we first copy the trunk to a branch in order to have control over projects maintainance on the branched code. The versioning system we choose is: Major.Minor.BuildNumber-SNAPSHOT (e.g. 1.0.0-SNAPSHOT). When branching the code, we want to change the project version number by incrementing the MinorVersion (e.g trunk-1.0.0-SNAPSHOT will become 1.1.0-SNAPSHOT, and 1.0.0-SNAPSHOT will be copied and released on the new created branch)
- when we decide that the project is mature enough in order to be released we are releasing it by using maven-release-plugin (mvn release:clean release:prepare release:perform) so that our project version will be transformed from Major.Minor.BuildVersion-SNAPSHOT (e.g. 1.0.0-SNAPSHOT) to Major.Minor.BuildVersion (e.g. 1.0.0), then will be prepared for the next development iteration like: Major.Minor.BuildVersion+1-SNAPSHOT (e.g. 1.0.1-SNAPSHOT)
The problems we are facing are related to projects versioning.
So, during the development phase on the trunk, all the projects are using the latest SNAPSHOT versions of their dependencies (mvn versions:use-latest-versions -DallowSnapshots=true -DupdateDependencies=true), but when we consider it's time to start the release procedure and prepare to branch the code, there problems start:
we are start branching
parent-pom
(mvn -B release:clean release:branch -DbranchName=${project.artifactId}_${project.version} -Dusername=${username} -Dpassword=${passwd} -Dproject.rel.${groupId}:${projectId}=1.0.0-SNAPSHOT
-Dproject.dev.${groupId}:${projectId}=1.1.0-SNAPSHOT)
copy project from trunk to new created branch, transform pom version on trunk from 1.0.0-SNAPSHOT to 1.1.0-SNAPSHOT
non-dependent projects
(mvn -B release:clean release:branch -DbranchName=${project.artifactId}_${project.version} -Dusername=${username} -Dpassword=${passwd} -Dproject.rel.${groupId}:${projectId}=1.0.0-SNAPSHOT
-Dproject.dev.${groupId}:${projectId}=1.1.0-SNAPSHOT versions:update-parent
-DallowSnapshots=true)
copy project from trunk to new created branch,
transform the trunk pom version 1.0.0-SNAPSHOT become 1.0.1-SNAPSHOT
update parent-pom.version: 1.0.0-SNAPSHOT become 1.1.0-SNAPSHOT
dependent projects:
(mvn -B release:clean release:branch -DbranchName=${project.artifactId}_${project.version} -Dusername=${username} -Dpassword=${passwd} -Dproject.rel.${groupId}:${projectId}=1.0.0-SNAPSHOT
-Dproject.dev.${groupId}:${projectId}=1.1.0-SNAPSHOT versions:update-parent
-DallowSnapshots=true versions:use-latest-versions -DallowSnapshots=true
-DupdateDependencies=true)
copy project from trunk to new created branch
transform pom version on trunk from 1.0.0-SNAPSHOT to 1.1.0-SNAPSHOT
update parent-pom on trunk from 1.0.0-SNAPSHOT to 1.1.0-SNAPSHOT
update the already branched dependency projects from 1.0.0-SNAPSHOT to 1.1.0-SNAPSHOT
The first problem here is that there is no way yet to have an argument to increase the MinorVersion when branch the project, the maven-release-plugin 2.2.2 does not increment the pom MinorVersion on trunk when branching, so that's why we need to use -Dproject.rel.${groupId}:${projectId}=1.0.0-SNAPSHOT
-Dproject.dev.${groupId}:${projectId}=1.1.0-SNAPSHOT arguments and change them manually for every project, so 200 times every time when we preapare for a new release.
I'm wondering if it's not a way to make all described procedure somehow in an automated fashion and to not need to perform all these changes manually all the time.
We've taking account even to modularize this product so that to colapse those 200 project in 100 probably, but this is not acceptable since the idea is to have a fine grained projects versioning and have all the projects with it's own lifecycle, so an aggregator (I mean a classic one) is out of discussion here.
We are using SVN as VCS, Maven as build tool (probably you already figured out about that :) ), and Bamboo as a CI server (actually, instead of "Maven Dependency Processor" feature, Bamboo is not helping me to much regarding the versioning problem).
Do you guys have any idea in order to find a proper solution for this problem, maybe another plugin which would help (versions-maven-plugin does not change versions automatically when branch), maybe another point of view for this, I don't know..., any help or sugestion are welcome.
Thanks!
I try to avoid keeping internal projects versions in the <properties> section of the parent-pom, since every time when I release a project, the <version>${project.version}</version> variable will be switched with the explicit version of the project like:
<properties>
<project_A.version>1.0.0-SNAPSHOT</projectA.version>
</properties>
stored in parent pom, translated in the projects pom like: ${project.version}, will become 1.0.1-SNAPSHOT when release that project, and will overwrite the <project_A.version> version from parent-pom <properties>. So this trick of keeping the projects versions as properties in a centralized location like the parent-pom, is valid as long as you don't release the projects.
This is the question strictly related to the branching question.
Now, if you want I can tell you more about releasing the projects using this <properties> substitution:
Lets's say you want to release your project_A, what will you do with the <projectA.version> stored in the parent pom <properties> which is a -SNAPSHOT version when you start to release the parent pom, right? I mean, in order to release a project, you'll release all its dependencies and its related parent-pom first right? otherwise your project release will fail since is pointing to a -SNAPSHOT version of the parent pom.
Now, you are releasing the parent-pom keeping the -SNAPSHOT version of project_A inside of it's <properties>, next when you'll release the project_A, your project will refer to the new created release version of your parent pom, which parent pom released version is refering to the -SNAPSHOT version of your project_A, still not a problem since your parent pom is keeping the true version of your project_A, until your projectA released version (lets say 1.0.0) will refer to the same parent pom released version which is containing 1.0.0-SNAPSHOT version of your project_A, and now you have a problem already because your parent pom <properties> is keeping a wrong info.
Ofcourse you can hack the parent pom when release it and store the release version of project_A, but this against the rules and I would not agree with that at all, plus that are other scenarios when this "hack" will cause more problems than help.
I'm sorry if this sounds pretty complicated and detailed but I just want to explain as much as possible the real life situation not just theoretical, plus that I also need to keep in mind that I have 200+ projects I need to keep somehow aligned.

Resources