How to manage maven dependant artifacts after creating release versions - maven

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.

Related

Keeping jar version numbers in sync between JitPack and other repositories

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?

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.

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.

Maven and snapshots?

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

Resources