When working with jenkins 2 (declarative) pipelines and maven I always have a problem with how to organize things within the pipeline to make it resusable and flexible.
On the one side I would like to seperate the pipepline into logical stages like:
pipeline
{
stages
{
stage('Clean') {}
stage('Build') {}
stage('Test') {}
stage('Sanity check') {}
stage('Documentation') {}
stage('Deploy - Test') {}
stage('Selenium tests') {}
stage('Deploy - Production') {}
stage('Deliver') {}
}
}
On the other hand I have maven which runs with
mvn clean deploy site
Simply I could split up maven to
mvn clean
mvn deploy
mvn site
But the 'deploy' includes all lifecycle phases from
So I saw a lot of pipline examples which do things like
sh 'mvn clean compile'
and
sh 'mvn test'
which results in repeating the validate and compile step a second time and waste "time/resources" in this way. This could be resolved with doing a
sh 'mvn surefire:test'
instead of running the whole lifecycle again.
So my question is - which is the best way to get a good balance between the jenkins pipline stages and the maven lifecycle? For me I see two ways:
Or did I missunderstand something in the CI/CD practice?
Of all Jenkins best practices, it's best to use Thin Plugin in conjunction with either creating a pipeline by configuring a job. Else, if you have your server deployed over cloud point 'E' (above) is the recommended approach.
There are three built-in build lifecycles: default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project's web site.
Pipelines are made up of multiple steps that allow you to build, test and deploy applications. Jenkins Pipeline allows you to compose multiple steps in an easy way that can help you model any sort of automation process. Think of a "step" like a single command which performs a single action.
Two month later I think I have a well balanced Jenkins pipeline script that is not complete, but works stable on windows and linux. It avoids pitfalls of other examples I have seen.
Jenkinsfile
pipeline
{
agent any
tools
{
maven 'Maven3'
jdk 'JDK8'
}
options
{
buildDiscarder(logRotator(numToKeepStr: '4'))
skipStagesAfterUnstable()
disableConcurrentBuilds()
}
triggers
{
// MINUTE HOUR DOM MONTH DOW
pollSCM('H 6-18/4 * * 1-5')
}
stages
{
stage('Clean')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode clean'
}
else
{
bat 'mvn --batch-mode clean'
}
}
}
}
stage('Build')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode compile'
}
else
{
bat 'mvn --batch-mode compile'
}
}
}
}
stage('UnitTests')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode resources:testResources compiler:testCompile surefire:test'
}
else
{
bat 'mvn --batch-mode resources:testResources compiler:testCompile surefire:test'
}
}
}
post
{
always
{
junit testResults: 'target/surefire-reports/*.xml'
}
}
}
stage('Sanity check')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode checkstyle:checkstyle pmd:pmd pmd:cpd com.github.spotbugs:spotbugs-maven-plugin:spotbugs'
}
else
{
bat 'mvn --batch-mode checkstyle:checkstyle pmd:pmd pmd:cpd com.github.spotbugs:spotbugs-maven-plugin:spotbugs'
}
}
}
}
stage('Packaging')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode jar:jar'
}
else
{
bat 'mvn --batch-mode jar:jar'
}
}
}
}
stage('install local')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode jar:jar source:jar install:install'
}
else
{
bat 'mvn --batch-mode jar:jar source:jar install:install' // maven-jar-plugin falseCreation default is false, so no doubled jar construction here, but required for maven-install-plugin internal data
}
}
}
}
stage('Documentation')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode site'
}
else
{
bat 'mvn --batch-mode site'
}
}
}
post
{
always
{
publishHTML(target: [reportName: 'Site', reportDir: 'target/site', reportFiles: 'index.html', keepAll: false])
}
}
}
stage('Deploy test')
{
steps
{
script
{
if (isUnix())
{
// todo
}
else
{
bat returnStatus: true, script: 'sc stop Tomcat8'
sleep(time:30, unit:"SECONDS")
bat returnStatus: true, script: 'C:\\scripts\\clean.bat'
bat returnStatus: true, script: 'robocopy "target" "C:\\Program Files\\Apache Software Foundation\\Tomcat 9.0\\webapps" Test.war'
bat 'sc start Tomcat8'
sleep(time:30, unit:"SECONDS")
}
}
}
}
stage('Integration tests')
{
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode failsafe:integration-test failsafe:verify'
}
else
{
bat 'mvn --batch-mode failsafe:integration-test failsafe:verify'
}
}
}
}
}
}
Hopefully this is interesting for other developers outside there.
I will update this here when I significantly improve it over time.
For those who also wish to see a maven pom along with a Jenkinsfile please have a look at my small example project at github: TemplateEngine
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With