Ivy Settings - Changing the way conflicts are resolved - settings

We setup Ivy in such a way that all projects on trunk or a particular branch have the same version number for our foundation classes jars. For example, trunk is set, so all jars are 5.4, and all projects that use those jars request the 5.4 jars.
We branched off of trunk for a particular feature that will be introduced in release 5.5. Previously, we would simply set the revision on that branch as revision 5.5. We'd go to our Maven repository, and duplicate the 5.4 jars to version 5.5, so projects could build. Jars on this feature branch would be placed in the repo as 5.5 jars.
However, this caused problems. Imagine trunk is set as revision 5.3, and we anticipate that the feature would be complete in revision 5.5. We'd duplicate the 5.3 jars as 5.5 jars, and have developers work on the feature branch.
Now, let's say we place the trunk revision to 5.4. A particular jar is modified in version 5.4, but not necessarily on the feature branch. Now the jar on trunk has changes not found in the feature branch. Later, we move trunk to version 5.5 and merge changes on the branch back to trunk.
Now, a project uses that particular 5.5 jar which is really based upon revision 5.3. The changes in 5.4 aren't there.
To get around this, we're trying a new strategy where feature branches are given non-numeric revisions. This way, when we are ready to merge the branch back to trunk, we duplicate the latest version of the 5.4 jars for 5.5. Then, anything that gets merged back into trunk causes a rebuild.
The problem now is the conflict manager. We have version "fb-foo" on the branch, and "5.4" on trunk. If a particular jar, foo.jar is specified on the branch (revision fb-foo and another jar requested also asks for that particular jar, but version 5.4, we're pulling down the 5.4 version. We'd prefer to pull down the fb-foo version for projects on this branch.
I've tried changing our master ivysettings-public.xml file:
<ivysettings>
<resolvers>
<ibiblio name="public"
m2compatible="true"
checkmodified="true"
root="http://buildl01.tcprod.local/artifactory/libs-release" />
</resolvers>
<latest-strategies>
<latest-revision name="mylatest-revision" usedefaultspecialmeanings="false">
<specialMeaning name="fb-foo" value="99"/>
</latest-revision>
</latest-strategies>
</ivysettings>
However, according to the Ivy report, version 5.4 is still being preferred over version fb-foo.
Is there a way to change this? What if I used 5.4-foo as the version number?

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?

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.

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.

Distinguishing maven releases/snapshots from trunk than the ones from branches when getting latest dependencies

I am working on project to automate maven releases for large set of inter-dependent modules. First the task involves getting the latest versions for internal dependencies. Than order the builds in a way every project is built before it’s needed. Hopefully that combination will get me to my goal of one click bulk release.
However my biggest problem is:
We branch projects from time to time and we do releases/snapshots to Nexus repo manager from that branch. Obviously because the groupId and ArtifactId are the same as the trunk- Snapshots/Releases from trunk and one from branches end up in the same place in nexus.
In a scenario where we have projectA with a trunk version 1.1.x
And projectB → projectA version 1.1.x
So if I use the version-plugin to get the latest dependencies for B, I will get the latest. (perfect)
However if I later branch ProjectA with a version 1.2.0 and add changes that I don’t want projectB to pick up or could potentially break it.
Now next time I run projectB and I use the version plugin to get the latest , The plugin will get the branch version (1.2.0) for ProjectA, as it’s numerically the latest. And there you go, projectB build fails.
I have so far tried adding a classifier to the artifact to distinguish between the two but I later realised the plugin does not act upon the classifier.
This give me so much frustration and will appreciate any hints or advice
Simple use proper/diffrent artifact names for branches. You can automatically create proper artifact names Maven Release plugin
mvn --batch-mode release:branch -DbranchName=my-branch-1.2 -Dproject.rel.org.myCompany:projectA=1.2 -Dproject.dev.org.myCompany:projectA=2.0-SNAPSHOT
The typical approach to solve this problem is to use branch names as version classifiers and that approach works for all scenarios I have seen so far. What problem did you have with this?

Resources