Deploy artifacts to Nexus with multiple versions (like Docker images) - maven

With Docker you deploy one image under several more or less volatile tags, e.g.:
hash
v1
v1.1
v1.1.1
latest
Is this possible and conceivable for artifacts in a Nexus repository (at least BUILD123 and latest-SNAPSHOT)?
We are providing services other teams are using. Some consumers of this services want to develop against a latest-and-greats version of this service, some others want to develop against a certain build of this service.
Of course we could change the artifact version in the pom.xmls, create Git-Tags for this and build these tags, but this information has no value in the Git repository.
The idea is Jenkins checking out the development branch, building it and pushing it to the nexus repository with a SNAPSHOT version as well as a distinct build version, so consumer can decide wether or not to develop against a fixed build or not.
Is this possible with only 1 deployment resulting in 1 file in the nexus repository (just like Docker)?

At current time this is not possible. We have some plans for the future with tagging, but nothing concrete as of yet.

You might be able to hack something together on the client side that essentially builds things multiple times and then deploys multiple times with different versions. But imho you are trying to hack around instead of really cutting releases treating them as such and really having a SNAPSHOT dev version.

Related

What are the consequences of always using Maven Snapshots?

I work with a small team that manages a large number of very small applications (~100 Portlets). Each portlet has its own git repository. During some code I was reviewing today, someone made a small edit, and then updated their pom.xml version from 1.88-SNAPSHOT to 1.89-SNAPSHOT. I added a comment asking if this is the best way to do releases, but I don't really know the negative consequences of doing this.
Why not do this? I know snapshots are not supposed to be releases, but why not? What are the consequences of using only snapshots? I know maven will not cache snapshots the same as non-snapshots, and so it may download the artifact every time, but let's pretend the caching doesn't matter. From a release-management perspective, why is using a SNAPSHOT version every time and just bumping the number a bad idea?
UPDATE:
Each of these projects results in a war file that will never be available on a maven repo outside of our team, so there are no downstream users.
The main reason for not wanting to do this is that the whole Maven eco-system relies on a specific definition of what a snapshot version is. And this definition is not the one you're setting in your question: it is only supposed to represent a version currently in active development, and it is not suppose to be a stable version. The consequence is that a lot of the tools built around Maven assumes this definition by default:
The maven-release-plugin will not let you prepare a release with a snapshot version as released version. So you'll need to resort to tagging by hand on your version control, or make your own scripts. This also means that the users of those libraries won't be able to use this plugin with default configuration, they'll need to set allowTimestampedSnapshots.
The versions-maven-plugin which can be used to automatically update to the latest release version won't work properly as well, so your users won't be able to use it without configuration pain.
Repository managers, like Artifactory or Nexus, comes built-in with a clear distinction of repositories hosting snapshot dependencies and release dependencies. For example, if you use shared Nexus company-wide, it could be configured to purge old snapshots so this would break things for you... Imagine someone depends on 1.88-SNAPSHOT and it is completely removed: you'll have to go back in time and redeploy it, until the next removal... Also, certain Artifactory internal repositories can be configured not to accept any snapshots, so you won't be able to deploy it there; the users will be forced, again, to add more repository configuration to point at those that do allow snapshots, which they may not want to do.
Maven is about convention before configuration, meaning that all Maven projects should try to share the same semantics (directory layout, versioning...). New developers that would access your project will be confused and lose time trying to understand why your project is build the way it is.
In the end, doing this will just cause more pain on the users and will not simplify a single thing for you. Probably, you could make it somewhat work, but when something is going to break (because of company policy, or some other future change), don't act surprised...
Tunaki gave a lot of reasonable points why you break Maven best practices, and I fully support that view. But even if you don't care about "conventions of other companies", there are reasons:
If you are not doing CI (and consider every build as potential release), you need to distinguish between versions which should go productive and those who are just for testing. If everything is SNAPSHOT, this is hard to do.
If someone (accidentally) deploys a second 1.88-SNAPSHOT, it will be the new 1.88-SNAPSHOT, hiding the old one (which is available by a concrete timestamp, but this is messy). Release versions cannot be deployed twice.

How to get Jenkins repository server to host only stable builds?

I have Jenkins version 2.7.1 running on a Windows 7 machine. It is successfully pulling code from a subversion repository and running tests. I have the test jobs set up for the development branch of each project only.
We periodically make stable releases of the projects in jar files with version numbers. I would like to have Jenkins be the repository manager for those stable releases. These are made by hand - There is no Jenkins job making or testing stable releases. The projects do use Maven.
Each stable build is tagged in the subversion repository, so it could be made again on demand if needed.
I downloaded the Maven repository server hoping to make this fit the purpose. I read the documentation that's provided, but it's pretty terse. As I understand it and have it configured now, this appears to have a couple of issues:
If I go to jenkins-ip/plugin/repository/project, it has made directories there that expose the names of all of my projects, which seems undesirable. (Here jenkins-ip is the IP where I access Jenkins on my local network.)
On the other hand, there's nothing but empty directories under these projects, so they're currently useless.
These projects all correspond to the continuous testing of the development branch. There's no apparent way to get the stable builds into the hierarchy. (It doesn't seem efficient to create a job for each stable release...)
Is there anyway to get Jenkins (with this plugin or through another method) to be the repository manager just for the stable builds? I know that I can start a different repository manager like archiva, but it would be ideal to use Jenkins since it's already running and it seems to claim capability for this function now.
To use Maven repository server you have to build the project on Jenkins.
Then the plugin will expose all archived artifacts as maven repo.
Note you need to use a "Maven project" type for it to work (freestyle is not supported)
There are several plugins that will help you manage building from multiple tags, however not all of them work with "Maven project" type.
You could also try Jenkins pipeline (previously "Workflow") or the Job-DSL plugin.
A simplest solution would be to have a build parameter specify the tag name (then checkout e.g. ^/tags/projectname/${tagParam}), but you have to figure out how to trigger the job then.

Maven publishing artefacts to remote repository and using $release in the artefact version

Wondering how people manage their project artefacts through an environment lifecycle of say DEV - AQA - CQA - RELEASE and if there's some best practices to follow.
I use a Jenkins build server to build my projects (code checkout then maven build). My artefacts all have version 1.0.0-SNAPSHOT and are published to a local .m2 repo on the build server. There are also Jenkins jobs that rebuild the DEV system (on the same server) using those artefacts. The project build is automated whenever someone checks in code. The DEV build is automated on a nightly basis.
At some point, my lead developer determines that our project is fit to go to AQA (the first level of testing environment on a different server).
For this I need to mark the artefacts as version 1.0.0-1 and publish to a remote AQA repository (it's actually a Nexus repo).
The Maven deploy plugin sounds like the right approach, but how do I change the version number to be effectively 1.0.0-$release (where $release is just an incrementing number starting from 1)? Would Maven/Nexus be able to manage the value of $release, or would I need a simple properties file in my project to store/update the last used $release.
Furthermore, someone tests AQA and determines its fit to move on to CQA (second testing env). This is 'promote to AQA'. So my requirement is to copy the artefact from the AQA Nexus repo and publish to the CQA Nexus repo.
Likewise, after CQA, there'd be a 'promote to RELEASE' job too.
I think the version value remains unchanged during the 'promote' phases. I'd expect the AQA repo to see all versions 1-50, but CQA only 25 and 50, then RELEASE only 50, for example.
I can find loads of info about Maven plugins/goals/phases, but very little about a prescriptive method on how or where to use outside of the immediate development environment.
Any suggestions gratefully received.
Staging/promoting is out of scope for Maven. Once deployed/uploaded to a remote repository, that system is responsible for the completion of the release cycle. Read this chapter about staging: http://books.sonatype.com/nexus-book/reference/staging.html if you use Nexus.
Build numbers are just that build numbers. They are not promotion / staging numbers.
You should come up with another means of tracking your promotions, because otherwise one might get confused in "knowing" that build 10.1.4-2 is the same as 10.1.4-6. Certainly, all of the Maven related software will see those two builds as different builds.
In addition, if a person "grabs" the wrong copy of the build, the way you are managing staging within your build number will increase confusion. As if you don't kill all of the 10.1.4-2 builds, then someone might get a copy of that not realizing that the build has been promoted to 10.1.4-6. This means that for the "last" staging number to be the most likely one to be grabbed, you must do two things (which are impossible in combination)
Remove all the old staging numbers, updating them to the new ones.
Ensure that no copy of an old staging number escaped the update.
Since people generally can copy files without being tracked, or said files might not be reachable at time up "update", or timing between reaching all the files cannot be simultaneous, such a system is doomed to fail.
Instead, I recommend (if you must track by file), placing the same file in different "staging directories". This defines release gateways by whether the file exists in a certain directory, and makes it clear that it is the same file that is going through the entire process. In addition, it becomes easy to have various stages of verification poll their respective directories (and you can write Jenkins tasks to promote from one directory to another, if you really wish).

multiple maven projects release against a common timestamp

We have several projects undergoing, and there are dependencies relationships among them. All projects makes up a final software.
We set up a DEV build environment to do snapshots build by using LASTEST dependencies. Any change will trigger a snapshot build (jekins job) and all dependent's snapshot build will be triggered too, and so if any changes break some project, that project's own build will notify the owner.
The question is about the release. The DEV build is continuous, and we want to release EVERY project against certain timestamp when it was a GREEN dev build across all projects.
How to get such release process setup?
thanks.
jenkins provides some Post-Build-Actions. You can use them to publish/archive every successfully built artifact to whereever you want.
Your Release-Job can take all the artifacts and deploy them. So you're sure all artifacts are from GREEN builds and is also independent from all the continuous jobs.
If you want to be really cool, do some smoke tests (e.g. is database connection working, external APIs working, etc) in the Release-Job as well.
best,
marco

How are snapshot and release repositories used differently?

I understand that during development build artifacts are placed in the snapshot repository.
When a product needs to go to QA for testing, do teams pull from the snapshot repository? Or do they do a full build, deploy to the release repository, and then give it to QA from there?
Also, if my snapshots repository holds all the build artifacts from each build, how is this commonly cleaned up? I could see keeping the last 5 builds from the build server, but not every one. I'm using Artifactory if it helps.
Opinions differ, here'e my approach:
Snapshots are for Dev
Typically used for "throwaway" builds. I publish them from my CI server, triggered by changes committed to the source code. The purpose of the snapshot build is to share the latest tested artifact from a particular team. This is important as teams might be sharing jars between each other.
This approach is much more stable than our previous approach of sharing the source code (Constant fire-fighting problems, when another team commits something that fails their build.... and by extension everyone elses).
Cleaning up snapshots
I use Nexus to manage my repository, it has a scheduled task that can be configured to periodically purge the snapshot repository. I'd imagine Artifactory has similar functionality.
Release candidates are for QA
I treat QA like a full-blown release to the customer. That's why I prefer the term "Release Candidate".
The key difference between a release candidate build and a snapshot is that the source code is "tagged" or "labelled" (dependent on your SCM system's terminology). What you're doing is drawing a line in the sand from which you can conveniently re-create the binary on demand.
Nexus professional has a staging suite, which enables development to cut a new release and hold it on a temporary "staging repository". Obviously some releases will fail testing in which case they're dropped. others are either promoted to the next group in the chain, or released to the public area.
There are several methods of implementing this "promotional model" of release management.
How release revisions are managed
I use the following numbering convention for my releases.
<major number>.<minor number>.<patch number>.<build number>
Example:
1.0.0.24
(For smaller/simpler projects I might alter the convention and drop the patch number).
Ivy has a wonderfully useful buildnumber task to manage the incrementing build number, based on what has already been published to your repository.
<property name="release.candidate" value="1.0.0"/>
..
<ivy:buildnumber organisation="${ivy.organisation}" module="${ivy.module}" revision="${release.candidate}"/>
..
<echo message="Release revision: ${ivy.new.revision}"/>
The release.candidate property is typically stored in a properties file, under version control. What I really like about this solution is that it enables parallel branch management (See answer to this question).

Resources