Using Jenkins triggers to execute a pipeline's test suite run - jenkins

We use Jenkins 2.176 to manage our CI. In our Jenkinsfile, we've defined a trigger to start the pipeline M-F at 4:30AM, and we want it to skip testing in an ephemeral environment and deploying.
pipeline {
triggers { cron('30 4 * * 1-5') }
stages {
stage('Build') {
...
}
stage('Tests') {
...
}
stage('Test in ephemeral environment') {
when { triggeredBy 'SCMTrigger' }
steps {
...
}
}
stage('Deploy') {
when { allOf { branch 'master'; triggeredBy 'SCMTrigger' } }
steps {
...
}
}
}
}
The problem is: the "Test in ephemeral environment" does not trigger when the branch is pushed via a git hook. The "Build" and "Tests" stages execute, but not the "Test in ephemeral environment". Once merged to master, I suspect I'll have a similar problem with the "Deploy" step but haven't made it that far.
What am I missing to make this work? It seems so straightforward 🤔

My solution was to simply exclude TimerTrigger explicitly from steps I didn't want to execute. From my example, I did this:
pipeline {
triggers { cron('30 4 * * 1-5') }
stages {
stage('Build') {
...
}
stage('Tests') {
...
}
stage('Test in ephemeral environment') {
when { not { triggeredBy 'TimerTrigger' } }
steps {
...
}
}
stage('Deploy') {
when { allOf { branch 'master'; not { triggeredBy 'TimerTrigger' } } }
steps {
...
}
}
}
}

Related

Graph of GitLab UI showing stages in vertical way

I have an Jenkinsfile to run some stages that I want, but after each commit, I would like to see all stages info in a clean way in my Gitlab server.
Here is the Jenkinsfile:
pipeline {
agent any
options {
gitLabConnection('gitlab connection')
}
stages {
stage('Build') {
steps {
gitlabCommitStatus(name: 'Build') {
(...)
}
}
}
stage('Static Code') {
parallel {
stage('SonarQube') {
steps {
gitlabCommitStatus(name: 'SonarQube') {
(...)
}
}
}
stage('FindBugs') {
steps {
gitlabCommitStatus(name: 'FindBugs') {
(...)
}
}
}
}
}
stage('Unit Tests') {
steps {
gitlabCommitStatus(name: 'Unit Tests') {
(...)
}
}
}
}
post {
changed {
gitlabCommitStatus(name: 'Teams Notification') {
(...)
}
}
}
}
When I run that pipeline I receive the stages info in a vertical way without any type of info on which stages run in parallel or not. All my stages show in vertical mode.
Is there anything that I can do to show something like this?
Thank you so much :)

How to configure SCM (gitHub) checkout re-try in multibranch declarative Jenkins pipeline?

My multibranch declarative Jenkins pipeline is failing very frequently during SCM checkout with timeout error and it works after one or two retries. is there anyway to automate the retry the SCM checkout?
Jenkinsfile
agent {
label "agent1"
}
stages {
stage('Test') {
parallel {
stage('Test1') {
steps { sh 'echo Test 1 passed' }
}
stage('Test2') {
steps {
sh 'echo Test2 is passed'
}
} stage('Test3') {
steps {
sh 'echo Test 3 passed'
}
}
}
}
}
You can add wrapper steps such as "retry" to retry the SCM checkout step.
agent {
label "agent1"
}
stages {
stage('Test') {
parallel {
stage('Test1') {
steps {
retry(3) {
echo "Test 1 passed"
}
}
}
stage('Test2') {
steps {
retry(3) {
echo "Test 1 passed"
}
}
}
}
}
}

Run same stages in parallel on different nodes with Jenkins pipeline

There is a way to execute steps/post-actions on different nodes in parallel described in this article: https://jenkins.io/blog/2017/09/25/declarative-1/
stage('Run Tests') {
parallel {
stage('Test On Windows') {
agent {
label "windows"
}
steps {
bat "run-tests.bat"
}
post {
always {
junit "**/TEST-*.xml" // DUPLICATE CODE
}
}
}
stage('Test On Linux') {
agent {
label "linux"
}
steps {
sh "run-tests.sh"
}
post {
always {
junit "**/TEST-*.xml" // DUPLICATE CODE
}
}
}
}
}
Is there any possibility to execute same stages on multiple nodes without duplicating code?
Something like this:
stage('Run Tests') {
parallel {
stage("Test On ${NODE_NAME}") {
agents {
label "windows"
label "linux"
}
steps {
// do test steps
}
post {
always {
junit "**/TEST-*.xml"
}
}
}
}
}
You can create dynamic stages, but for your case not needed
pipeline {
agent any
stages {
stage ("Test") {
steps {
script {
testStages = ["Windows", "Linux"].collectEntries {
["${it}" : runTests(it)]
}
parallel testStages
}
}
}
}
}
def runTests(def name){
return {
node(name) {
stage("Run on ${name}") {
script {
command = "run-tests"
try {
switch(name.toLowerCase()) {
case "windows":
command += ".bat"
break;
case "linux":
command += ".sh"
break;
}
echo command
} catch (Exception ex) {
echo ex
} finally {
echo "post ${name}"
}
}
}
}
}
}
Declarative Matrix worked best for me:
pipeline {
agent none
stages {
stage('BuildAndTest') {
matrix {
agent {
label "${PLATFORM}-agent"
}
axes {
axis {
name 'PLATFORM'
values 'linux', 'windows'
}
}
stages {
stage('Test') {
steps {
echo "Do Test for ${PLATFORM}"
}
}
}
post {
always {
junit "**/TEST-*.xml"
}
}
}
}
}
}
This pipeline will execute the defined stages incl. post build actions on both platforms without any code duplication.
Quote from a Jenkins blog post about declartive matrix:
An equivalent pipeline created without matrix would easily be several
times larger, and much harder to understand and maintain.

Jenkinsfile nested stage(s) throwing error

I have the following Jenkinsfile which I believe is setup correctly. I used https://jenkins.io/doc/book/pipeline/syntax/#sequential-stages as an example but for some reason when I run this in jenkins I am receiving,
WorkflowScript: 11: Unknown stage section "stages". Starting with
version 0.5, steps in a stage must be in a steps block
Can someone tell me what I am missing or doing wrong?
pipeline {
agent {label 'windows'}
stages {
stage('Quick Build') {
steps {
echo 'Building'
}
}
stage('Deploy to Dev') {
// when {
// branch 'develop'
// }
stages {
stage('Building Distributable Package') {
steps {
echo 'Building'
}
}
stage('Archiving Package') {
steps {
echo 'Archiving Aritfacts'
archiveArtifacts artifacts: '/*.zip', fingerprint: true
}
}
stage('Deploying Dev') {
steps {
echo 'Deploying'
timeout(time:3, unit:'DAYS') {
input message: "Approve build?"
}
}
}
}
}
stage('Deploy to Test') {
when {
branch 'develop'
}
steps {
echo 'deploying..'
timeout(time:3, unit:'DAYS') {
input message: "Approve build?"
}
}
}
stage('Deploy to Prod') {
when {
branch 'release'
}
steps {
timeout(time:3, unit:'DAYS') {
input message: "Deploy to Prod?"
}
echo 'Deploying....'
}
}
}
}
Thanks in advance!
This ended up being a problem in version 2.107.3. Once upgraded to 2.121.2 this functionality started working.

JenkinsFile how to query if job exists

In a declarative Jenkinsfile how can you determine if a job exists?
I want to conditionally run a stage if another job exists, like so:
pipeline {
agent { label 'mylabel' }
// Run the the stages:
stages {
stage('Pre-Build') {
steps {
timestamps { ansiColor('xterm') { sh 'build/jenkins_prebuild.sh' } }
}
}
stage('Pre-Build') {
steps {
timestamps { ansiColor('xterm') { sh 'build/jenkins_build.sh' } }
}
}
stage('Trigger Remote If Exists'){
when { JOB_EXISTS }
steps {
timestamps {
ansiColor('xterm') {
sh 'build/pre-trigger.sh'
build job: "../myjob/foo", wait: false, parameters: [booleanParam(name: 'FOO', value: true)]
}
}
}
}
}
}
Basically, what should I do for JOB_EXISTS?
if (jenkins.model.Jenkins.instance.getItem("YOUR_JOB_NAME") != null) {
}
You may not be able to use the above snippet in your declarative pipeline. But you should be able to use this in a global shared lib.
UPDATE:
An administrator needs to approve this snippet in "Manage Jenkins -> In-process Script Approval" section.
There is also this option: https://stackoverflow.com/a/52076776/3384609
try {
println("Preparing to build the ${jobName}...")
build job:"${jobName}", propagate:false, wait:false
} catch (hudson.AbortException e) {
println("Not building the job ${jobName} as it doesn't exist")
}```

Resources