Reputation: 2092
I'm using Jenkins Pipeline to automatically build and deploy my Java apps. I also use maven-release-plugin to perform Maven deploy to Artifactory.
The problem is my Jenkinsfile (or Jenkins Pipeline Configuration) :
You understood that the last step creates an infinite loop, even if there is no useful commit.
Here is the interesting part of my Jenkinsfile :
sshagent([git_credential]) {
sh "${maven_bin} --settings ${maven_settings} -DreleaseVersion=${release_version} -DdevelopmentVersion=${development_version} release:prepare release:perform -B"
}
How can I break the loop (avoid Jenkins to trigger new build when Maven commits on GIT)?
Thanks
Upvotes: 23
Views: 34320
Reputation: 3779
IMHO with the advent of git and pull requests, I don't think using maven-release-plugin or maven-version-plugin with a Jenkins pipeline is a good idea.
Using Multibranch Pipeline with the versioning technique mentioned here is more in line with continuous delivery: https://axelfontaine.com/blog/dead-burried.html
Using the versioning technique above, the pom.xml now looks like this:
<project>
...
<version>${revision}</version>
<properties>
<!-- Sane default when no revision property is passed in from the commandline -->
<revision>0-SNAPSHOT</revision>
</properties>
<scm>
<connection>scm:git:your-git-repo-url</connection>
</scm>
<distributionManagement>
<repository>
<id>artifact-repository</id>
<url>your-artifact-repo-url</url>
</repository>
</distributionManagement>
<build>
<plugins>
<plugin>
<artifactId>maven-scm-plugin</artifactId>
<version>1.9.5</version>
<configuration>
<tag>${project.artifactId}-${project.version}</tag>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
You can now produce releases on your Jenkins server very easily by configuring a Multibranch Pipeline with a Jenkinsfile to build on all branches and deploy only from master branch:
pipeline {
agent any
environment {
REVISION = "0.0.${env.BUILD_ID}"
}
triggers {
pollSCM('')
}
options {
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '30'))
}
tools {
maven '3.5.2'
jdk 'jdk8'
}
stages {
stage ('Initialize') {
steps {
sh '''
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
'''
}
}
stage ('Build') {
steps {
sh 'mvn clean package'
}
}
stage ('Deploy') {
when {
branch 'master'
}
steps {
script {
currentBuild.displayName = "${REVISION}"
}
sh 'mvn deploy scm:tag -Drevision=${REVISION}'
}
}
}
}
See https://jenkins.io/blog/2017/02/07/declarative-maven-project/#set-up on how to configure a Multibranch Pipeline.
With this technique you develop only on non-master branches. Then create a pull request to merge your changes back to master branch. This should then deploy your artifact automatically to your artifact repository.
Addendum
When publishing to a Maven repository using the above method, the pom.xml will not have the proper version. To get Maven to publish the proper version, use the flatten-maven-plugin: http://www.mojohaus.org/flatten-maven-plugin/usage.html.
Also, check out: https://maven.apache.org/maven-ci-friendly.html
Upvotes: 18
Reputation: 438
This is is what we put as a first stage in our pipeline:
stage('Check commit message') {
when { changelog '.*\\[maven-release-plugin\\].*' }
steps {
script {
pom = readMavenPom file: 'pom.xml'
currentBuild.displayName = pom.version
currentBuild.result = 'NOT_BUILT'
}
error('Skipping release build')
}
}
You will need to install https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/ plugin to read maven pom, or just put a fixed description for the skipped build. The build following the release will have grey colour.
Upvotes: 3
Reputation: 185
In case somebody has the same problem with the loop or that subsequent builds get triggered BUT has a Trigger who starts the jenkins pipeline on every push to the repository (Instead of polling).
Here is who I did it: I checked if the last commit contains "[maven-release-plugin]" in the comment.
Code in jenkinsfile:
def lastCommit = sh returnStdout: true, script: 'git log -1 --pretty=%B'
if (lastCommit.contains("[maven-release-plugin]")){
sh "echo Maven release detected" //dont trigger build
} else {
sh "echo Last commit is not from maven release plugin" //do build steps
<..build Job...>
}
Upvotes: 8
Reputation: 161
A solution can be to change the post-receive hook that is calling the notification URL of jenkins:
#!/bin/bash
git_log=$(git log --branches -1)
if ! [[ $git_log =~ .*maven-release-plugin.* ]] ;
then
curl http://buildserver:8080/git/notifyCommit?url=ssh://git@server:22/projects/Name.git;
fi
Upvotes: 0
Reputation: 2092
Thanks to @Daniel Omoto comment, I found out that Jenkins provides option for GIT polling. One is exactly what I needed (and the provided example is for maven-release-plugin!):
Upvotes: 12