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")
}```
Related
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 :)
I have a Jenkins pipeline with some jobs running in parallel. I want to manage the timing out of one of them and keep the pipeline running. I have followed this very well-done guide, but I can't avoid that when my job times out; all the other parallel jobs and the whole process fail too.
Following, how I have implemented the pipeline:
pipeline {
agent any;
stages {
stage('Stage-1') {
steps {
sh 'job-1.sh'
}
}
stage('Stage-2') {
failFast false
parallel {
stage('Stage-2-1') {
steps {
sh 'job-2-1.sh'
}
}
stage('Stage2-2') {
stages {
stage('job-2-2-1') {
options {
timeout(time: 10, unit: "SECONDS")
}
steps {
script {
Exception caughtException = null
catchError(buildResult: 'SUCCESS', stageResult: 'ABORTED') {
try {
sh 'job-2-2-1.sh'
}
catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
echo "Time out"
TIMEOUT="1"
} catch (Throwable e) {
caughtException = e
}
}
if (caughtException) {
error caughtException.message
}
}
}
}
stage('job-2-2-2') {
when {
expression { TIMEOUT=="0" }
}
steps {
sh 'job-2-2-2.sh'
}
}
}
}
stage('Stage-2-3') {
steps {
sh 'job-2-3.sh'
}
}
}
}
stage('Stage-3') {
steps {
sh 'job-3.sh'
}
}
}
}
I tried to set failFast to false because I don't know if it has a default value.
How can I keep the other jobs run and get the successful final build?
Thanks
I have list of apps as checkboxes (using extended choice parameter with ',' as multiSelectDelimiter).
I want to execute a stage if a matching checkbox is checked, else skip it.
For eg: apps: app1,app3 [checkboxes selected]
checkboxes selected image
stages{
paralle{
stage('First'){
when {
// execute this when app1 is selected
}
steps {
}
}
stage('Second'){
when {
// execute this when app2 is selected, should skip this as 'app2' is not checked
}
steps {
}
}
stage('Third'){
when {
// execute this when app3 is selected
}
steps {
}
}
stage('Fourth'){
when {
// execute this when app4 is selected, else skip it
}
steps {
}
}
}
}
It can be done this way
def choice=[]
node {
choice = params["my-checkbox"].split(",")
}
pipeline {
agent any;
parameters {
checkboxParameter name:'my-checkbox', format:'JSON', uri:'https://raw.githubusercontent.com/samitkumarpatel/test0/main/checkbox.json'
/*
consider this is the structure of CheckBox in https://raw.githubusercontent.com/samitkumarpatel/test0/main/checkbox.json URI
{
"key": "stage1",
"value": "stage1"
},
{
"key": "stage2",
"value": "stage2"
},
{
"key": "stage3",
"value": "stage3"
}
*/
}
stages {
stage('stage1') {
when {
expression {
'stage1' in choice
}
}
steps {
echo "${env.STAGE_NAME} execuated"
}
}
stage('stage2') {
when {
expression {
'stage2' in choice
}
}
steps {
echo "${env.STAGE_NAME} execuated"
}
}
stage('stage3') {
when {
expression {
'stage3' in choice
}
}
steps {
echo "${env.STAGE_NAME} execuated"
}
}
}
}
This pipeline will run the stages which are selected during the build
with this parameter, it will only trigger stage1 and stage2
I used below piece in the pipeline to select the stage based on parameters provided in the Jenkins UI. "Boolean parameter" can be useful instead of "Extended Choice Parameter" to avoid clutter in the pipeline.
Reference - https://www.jenkins.io/doc/book/pipeline/syntax/#when
stage("Install Application1"){
when { environment name: 'APP_1', value: 'true' }
steps{
sh '''
Steps to install the application1
'''
}
}
stage("Install Application2"){
when { environment name: 'APP_2', value: 'true' }
steps{
sh '''
Steps to install the application2
'''
}
}
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.
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 {
...
}
}
}
}