How to manage Tycho / EAP versioning correctly - maven

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

Related

Why Maven default-bindings.xml is not updated?

The versions of Maven plugins specified in default-bindings.xml is not latest.
For example, maven-resources-plugin is 2.6, but latest is 3.1.0,
maven-jar-plugin is 2.4, but latest is 3.1.0.
https://github.com/apache/maven/blob/master/maven-core/src/main/resources/META-INF/plexus/default-bindings.xml
I think it's not necessary to update default-bindings.xml at every minor version update of plugins.
However, the above is major update.
I know I can change the versions myself if I want.
My Question is why default versions that affect most of the maven users are clearly old.
The thing is you should always pin all your plugin (and I mean all plugins) inside your build which means define the version of all plugins via <pluginManagement>..</pluginManagmenet> this is best practice and you should never rely on those in Maven Core.
Furthermore there is work done in the background to decouple the artifact handlers (plugin binding) from Maven Core and move it to the plugins1, 2 and 3 and so on (which is done in very small steps and will take a long time).

Manage dependency version centralized

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.

Does every dependency have a "latest" version in sbt/maven?

For example can I always use a "latest" version for every library as follows?
"com.kaala.re" %% "brain-builder-client" % "latest"
You can use LATEST for maven for any dependency, but it's DEPRECATED feature in maven 3.
When you depend on a plugin or a dependency, you can use the version
value of LATEST or RELEASE. LATEST refers to the latest released or
snapshot version of a particular artifact, the most recently deployed
artifact in a particular repository. RELEASE refers to the last
non-snapshot release in the repository. In general, it is not a best
practice to design software which depends on a non-specific version of
an artifact. If you are developing software, you might want to use
RELEASE or LATEST as a convenience so that you don't have to update
version numbers when a new release of a third-party library is
released. When you release software, you should always make sure that
your project depends on specific versions to reduce the chances of
your build or your project being affected by a software release not
under your control. Use LATEST and RELEASE with caution, if at all.

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.

Is there a way to tell maven to always use the latest _stable_ version of a dependency?

How can I tell maven to always use the latest stable version of a dependency?
I know that I can depend on latest release version or just the latest version whatever that is from this question. I also know I can use the dependency plugin (also from that link).
However, I use google's guava library which seems to get an update every week. I find myself updating the version all the time. It's the google versioning system where it is more an incremental update than a big bang update and thus it is very unlikely that it will break anything especially given the nature of this library.
So I Would like to not have to keep changing the version identifier of my maven dependency.
So I could do this:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>[12.0.1,)</version>
</dependency>
Which would give me version 12.0.1 and later... and since I don't depend on any repos that are going to supply any snap shot versions of this dependency this will ensure I always have the latest release version.
However, it will also give me the "rc" versions as well (13.0-rc1 and 13.0-rc2). This is what I want to avoid.
Is it possible to make maven only depend on the stable release? i.e. that don't have any "rc" or "beta" or "alhpa" in their name and are just plain "13.0".
You can use RELEASE value in version element for your dependency to make Maven use the latest released version. However this is not the best practice, because it can break build reproduceability.
Also, Maven don't make logical differences between versions like 12.0.1 and 13.0-rc1. From Maven's point of view both of them are released versions and basically what you're trying to do is breaking Maven releases ideology in several ways.
So, instead of versioning artifacts like 13.0-rc1, you should do a regular releases and use special repositories and artifact promotion process as par of your release. So, you could have a release-candidates repository that can be used during testing and once test pass you'll promote those artifacts to a final release repository. But if you need to make changes, you'll just update released version, so 13.0, 13.0.1, etc...
mvn versions:use-latest-releases -Dexcludes="*:*:*:*:*-M*,*:*:*:*:*RC*,*:*:*:*:*rc*,*:*:*:*:*-alpha*,*:*:*:*:*-beta*,*:*:*:*:20030203.000550,*:*:*:*:*Beta*"

Resources