Keeping jar version numbers in sync between JitPack and other repositories - maven

I maintain a few Java library projects on GitLab, which I currently build with a GitLab CI workflow and deploy to a GitLab Maven repository. Now I would like to make them available via JitPack while keeping the GitLab Maven repo for a while.
GitLab’s Maven repo, like most of the others out there, uses the contents of the <version> tag in pom.xml for versioning. JitPack, on the other hand, needs a Git ref to work with (a branch name, a tag or a plain hash). I am looking for a way to use the same versioning regardless of the repo, so that version FOO will fetch a jar based on the same code, regardless of whether it is taken from GitLab or JitPack.
For a released, stable version that could be solved by tagging each release with its version number. That is, when I release version 3.7.0, I would ensure the <version> tag in my pom.xml reads 3.7.0, and tag the commit with 3.7.0 as well. I would need to enforce a match between the two (e.g. by teaching CI to bar{k|f} upon detecting a discrepancy), but with some homework, both repos would carry the same version of my code under the same version number.
Things get tricky when it comes to unstable versions. If I am working on the upcoming 3.7.2 release and would already like to make it available for testing, I understand common practice is to set the version tag to 3.7.2-SNAPSHOT, telling everyone that this is not a stable version. The GitLab Maven repo would serve the jar under that version.
For JitPack, versions ending in -SNAPSHOT indicate that the code could have changed since the last build and the jar should be rebuilt from source. A version named 3.7.2-SNAPSHOT would cause JitPack to look for a ref named 3.7.2 (tag or branch) and build it from scratch.
So I would have to ensure that the version name of the upcoming version resolves to the latest commit for the upcoming version. I could do that by developing the upcoming version in a branch named like the version, but that would presumably result in a naming conflict as I release it, as I would then introduce a tag with the same identifier.
Is there a general recommendation for addressing this, i.e. serving unstable versions of a jar via JitPack and a conventional Maven repo under the same version number?

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.

Is it possible to use revapi maven plugin to do check against a SNAPSHOT version?

I'm currently setting up revapi-maven-plugin for a project, using latest version (0.7.0), and we want to check on our jenkins that no regression appears in our API during development.
Then for my process I don't want to check the regression between a snapshot and a release but between two snapshots.
Unfortunately (?) we use a different repository for our snapshots and our releases, and apparently revapi-maven-plugin seems not able to get the latest snapshot version from the snapshot repo.
Or is it and I did not understand how to do that?
I already put those value in my configuration but it does not change anything:
<alwaysCheckForReleaseVersion>false</alwaysCheckForReleaseVersion>
<oldVersion>LATEST</oldVersion>
This is supported since the version 0.8.0 of the revapi-maven-plugin.
The documentation of the oldVersion property reads (https://revapi.org/modules/revapi-maven-plugin/check-mojo.html#oldVersion):
If you don't want to compare a different artifact than the one being built, specifying just the old version is simpler way of specifying the old artifact. The default value is "RELEASE" meaning that the old version is the last released version of the artifact being built (either remote or found locally (to account for artifacts installed into the local repo that are not available in some public remote repository)). The version of the compared artifact will be strictly older than the version of the new artifact. If you specify "LATEST", the old version will be resolved to the newest version available remotely, including snapshots (if found in one of the repositories active in the build). The version of the compared artifact will be either older or equal to the version of the new artifact in this case to account for comparing a locally built snapshot against the latest published snapshot.

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

How to use maven version plugin in branch

I use maven version range for the dependencies in my parent pom.It works fine when I do a build on snapshot or a release.
But how should I need to proceed when I want to use the specific version of dependencies in a branch ?
For example: when I use version range such as (1.2.0,) it will always fetch the latest jar from the nexus repository. The latest would be like 1.2.5 as of when I do a release, since the dependencies are getting changed over and over.Now the latest version of my dependencies is 1.2.8-SNAPSHOT
In branch when I want 1.2.5 version for my dependencies, it is always looking for the latest one which is 1.2.5+
How to resolve this, while searching for similar questions I found that it could be resolved using maven-version-plugin. That requires a changes in the pom to add the plugin. But is there a solution without changing the pom and getting exact version for a dependency?
Any suggestions?
There is no solution without changing the pom at this point, if I understand the scenario correctly: In the release of a prior version of your product, the version of one (or more) of its dependencies was not fixated to the version available at the time. Now, in support of that previous release, the build has a different result than at the time of release.
There is no suggestion except to change the branch's pom to use the 'back' version available at the time of the release. Consider it a short term fix to a bug in the release process.

Resources