How can I fail a Jenkins Maven release if it contains SNAPSHOT in the pom.xml - maven

When we do a release we want to fail the release if any of the dependent apps are still in SNAPSHOT version in the pom. For normal builds this should be allowed.
I guess there might be 2 options:
Is there a maven switch for the jenkins maven plugin to specify such and option?
Run a bash script to check for "SNAPSHOT" string in pom.xml, but then how can I detect "if this is a release" inside a jenkins job?
Thanks.

You can use Maven Release Plugin to perform a release, it will fail the release in case of SNAPSHOT dependencies.
You also can specify checking for timestamped SNAPSHOT dependencies, by default it is false.

Related

Jenkins environment variables for Maven pom dependencies

We have several jobs on jenkins that are running on hierarchical dependencies on each other.
Lets say, Job2 has a dependencies on the Job1 for the pom.xml version.
so whenever we have changes at the end of sprint for Job1, we are in need to change the versions of the pom on the dependencies inside the Job2 before releasing the artifacts at the end of sprint, so this might not handy if we have Job3, Job4, Job5 that are depending on the version of Job1. we need to change all the version of Job1 on all the pom.xml of all the Jobs that is dependent on it.
So the question, are there any ways to solve this, probably using jenkins env variables? need a helping hand how to perform it based on the issues above.
Thanks.
You can use jenkins Parameterized Trigger Plugin for passing variables to the downstream projects. Plugin wiki got detailed explanation.
So you have dependencies amongst your internally developed artifacts. During development you want to depend on the latest snapshot of those artifacts, but a release build shall depend on the latest release version of those same artifacts.
This can be achieved with Jenkins and Maven. Set up your release build job like so:
Add a "Pre Step" section of type "Invoke top level Maven targets". In this step you run the targets versions:update-properties scm:checkin to update your internal dependencies to point to the latest release version.
In the main build step do the release: release:prepare release:perform -B. This builds the release version, increments the version number to the next snapshot version, builds that next snapshot version and checks this back into scm.
In a "Post Step" run the targets of the Pre Step again (with allowSnapshots=true) to update your dependencies to reference the latest snapshot version.
Examples:
NOTE: For this to work all jobs have to hit the same Maven repository. Locally on the Jenkins server or your corporate Nexus.
Since you will have the required version at the end of execution of Job1, export it as environment variable or store it in some of the file on build server like
pom_version=1.1
Now when triggering all the downstream jobs, set the parameter of jobs as "pom_version" and either pass this file to pick the required key/value or set the value in pre-defined parameter.
After that, make sure all of your downstream jobs are configured as parameterized with parameter "pom_version"

Remove SNAPSHOT suffix from Jenkins build

I recently upgraded from hudson to jenkins. Since they are practically the same I thought it would be just plug and play. I noticed that when I build my projects my war files are being appended with the SNAPSHOT version instead of just .war. I didn't have this problem in hudson.
Is there a way to globally tell jenkins to use the release war, the one in my target directory, as it's artifact build file or have jenkins, I'm assuming the maven plugin, to not append the SNAPSHOT to the file?
SNAPSHOT is added on purpose. Don't mess with it. Either use bleeding-edge or perform mvn release:prepare release:perform in batch mode from Jenkins.

How to allow any version in Snapshot repo

We're building feature branches into a version 'feature_'. Each feature build will produce the same version. Since these are no releases, I want to deploy the artefacts into the Snapshots repo, but Nexus does not allow versions without 'SNAPSHOT' into the Snapshot repo.
How to configure Nexus to allow any version in a repo?
Solved it by appending '-SNAPSHOT' to the branch version.
It's quite tricky to get Maven in Jenkins to use the right version. The way I solved it now is like this. In the build job configure Git to build the branches origin/feature/*. Then:
In the 'build' section, first thing to do is execute a shell command to construct a file 'env.properties' containing the feature branch version to be used by the Maven build command.
echo BRANCH_VERSION="feature_${GIT_BRANCH##*/}-SNAPSHOT" > env.properties
This uses the GIT_BRANCH environment property of Jenkins. The '##*/' is a Bash Shell Parameter Expansion which strips everything from the parameter value except the part after the last '/' character.
Then use the Environment Injector Plugin to 'inject environment variables' to the build job using the 'env.properties' created in the previous step.
Put 'env.properties' in the 'Properties File Path' field.
Use Maven to build a versioned pom with the correct version using 'Invoke top-level Maven targets':
help:effective-pom -Dbuild.number=${BRANCH_VERSION} -Doutput=versioned-pom.xml. This step is necessary because otherwise the pom in the jar artefact does not contain the correct version causing other problems.
Use another 'Invoke top-level Maven targets' step to do the actual build and deploy using the pom version created in the previous step: -f versioned-pom.xml clean source:jar deploy
That's all folks. If anyone knows a simpler solution, let me know.
This is actually a Maven restriction. You can still use version like feature_x-1.2.3-SNAPSHOT though.
What are you actually trying to achieve though?

Jenkins maven-release-plugin

In Jenkins (latest), Maven 3.0.x, I have a project (Java source code).
I'm using M2 release plugin, which provides a nice "Perform Maven Release" button on the Jenkins job (left hand side pane on the Jenkins job's dashboard). Behind the scene / in Jenkins job's configuration, it calls: release:prepare release:perform goals.
When I'm click on "Perform Maven Release", it does it's job successfully (builds from 1.0.0-SNAPSHOT, run tests && if successful, make changes to pom.xml and put version as 1.0.0 as version ID, perform some more verification and make changes to pom.xml (what maven-release-plugin checks are etc), commit this change in version control, tag it with 1.0.0 as a "TAG" in version control, change pom.xml again to use 1.0.1-SNAPSHOT and commit it, then checkout from that tagged 1.0.0 release version tag which we just created, checkout it under /target/checkout folder, build relase 1.0.0 artifacts (jar/war/pom etc) and finally deploys it to the repository which you'd have mentioned inside ..... ... section.
<distributionManagement>
<repository>
<id>dev-artifactory</id>
<url>http://1.2.3.15:8081/artifactory/libs-release-local/</url>
</repository>
<snapshotRepository>
<id>dev-artifactory</id>
<url>http://1.2.3.15:8081/artifactory/libs-snapshot-local/</url>
</snapshotRepository>
</distributionManagement>
What I need is:
1) How can I make "Perform Maven Release" process to call a deployment to a server once x.x.x release artifacts are generated by the process above and run some Integration tests. This should happen before deployment of artifacts to a binary repository (Artifactory/Nexus) is performed by maven-release-plugin process. i.e. if you are putting artifacts in a release repository, then non-unit tests are also successful (not that artifacts are in libs-release-local repository in Artifactory and Integration tests are yet to be launched.
OR do I need to change ... to use libs-snapshot-local (Artifactory repository) and then run IT tests and finally if those tests are successful, move 1.0.0 release artifacts from libs-stage-local repository to libs-release-local repository.
I know I can put maven-release-plugin related settings in Maven's user's .m2/settings.xml (user global) or at M2_HOME/.m2/settings.xml (global) but at this point, that's not the question.
We have a Jenkins deployment for each environment (dev, qa, prod). We move the same artifacts across all environments using Promoted Builds, Copy Artifact, and Parameterized Trigger plugins. To see how they work together, read this post (How to promote a specific build number from another job in Jenkins?)
As per the release process, instead of Maven Release plugin, use Maven Promote plugin (http://java.jiderhamn.se/2016/05/04/announcing-maven-promote-plugin/) to release the artifact that is already built and tested (there are a lot of articles on maven release plugin's drawbacks). You can still use Jenkins M2 Release Plugin, but in it's configuration, Release goals and options, call mvn release:clean promote:prepare release:prepare instead. For more details: https://github.com/mjiderhamn/promote-maven-plugin/issues/2
Maybe you should consider taking a look at this article here: https://pragmaticintegrator.wordpress.com/2014/05/12/running-the-maven-release-plugin-with-jenkins/
With Jenkins Release plugin you could customize your release workflow to add specific steps once your M2 release is done.

Can Maven release:prepare update snapshot version to the release version in batch mode

mvn release:prepare
It constantly asks me to resolve snapshot dependencies.
Is there a way to do this in batch mode so that maven automatically uses the associated release. i.e. if a dependency is 1.0.0-SNAPSHOT it will automatically update this dependency to the 1.0.0 release?
[INFO] Checking dependencies and plugins for snapshots ...
There are still some remaining snapshot dependencies.: Do you want to resolve them now? (yes/no) no: : yes
Dependency type to resolve,: specify the selection number ( 0:All 1:Project Dependencies 2:Plugins 3:Reports 4:Extensions ): (0/1/2/3) 1: : 1
Resolve Project Dependency Snapshots.: 'com.my.project' set to release? (yes/no) yes: : yes
What is the next development version? (0.0.2-SNAPSHOT) 0.0.2-SNAPSHOT: : 0.0.2-SNAPSHOT
Note that you can configure Maven ignore SNAPSHOT dependencies checking by using allowTimestampedSnapshots, according to maven-release-plugin documentation:
allowTimestampedSnapshots:
Whether to allow timestamped SNAPSHOT dependencies. Default is to fail when finding any SNAPSHOT.
Type: boolean
Since: 2.0-beta-7
Required: No
Expression: ${ignoreSnapshots}
Default: false
Or simply run the command below:
mvn release:prepare -DignoreSnapshots=true
However, it is still recommended to resolve all SNAPSHOT dependencies before doing the final release, as it is the convention used by most people. You should always consider to do it manually at developing phase rather than automatically batching at release phase, as change/upgrade project's dependencies (either your own or third party jar) may sometimes introduce bug or incompatibility and break your project, which usually need developer's attention and fix them before doing final release.
In another word, dependency resolution is not a task which should be done at release phase, moreover, it is not a task which should be done automatically without developer's attention.
You can do update of the SNAPSHOT's via the versions-maven-plugin before the release.
If your dependency is a program of you own and its lifecycle is closely linked to the one you try to release, you may think about using a multimodule project : http://maven.apache.org/guides/mini/guide-multiple-modules.html. Maven release plugin would update version for all of you dependencies modules.
If not, you are probably doing something you should not.
Just changing 1.0.0-SNAPSHOT to 1.0.0 does not ensure you app will continue to work. So does not consider that Maven should !
Further considerations
Maven release plugin checks if you are using a snapshot dependency, because Snapshot, by definition, are unstable vesions. It may change along the time. That means what was working today may not work tomorrow.
Releasing means that your version is stable, and the build can be reproduce anytime without any change. Using Snapshot version, this assertion become false.
So,

Resources