I am trying to do a numerical comparison in Jenkins and perform a action based on that. COUNT is a string type parameter. But it is giving the below error.
WorkflowScript: 24: Expected a step # line 24, column 14.
if ( params.COUNT > 10 ) {
^
1 error
pipeline {
agent {
label "${node_label}"
}
parameters {
string(defaultValue: "1", description: "Number of VM's to be Added", name: "COUNT")
}
stages {
stage('Parameter Validation') {
steps {
if ( params.COUNT > 10 ) {
error("Instance count should be less than 10 and it is ${COUNT}")
}
}
}
stage('Clone Latest Repo') {
steps {
echo "Pull latest code"
build 'gitpull'
}
}
I tried different ways, but no luck
steps {
script {
sh '''#!/bin/bash
if [[ "${COUNT}" -gt "10" ]]; then
error("Instance count should be less than 10")
fi
'''
}
}
I found a way to typecast the string variable to INT def intValue = COUNT as int. This solution is working as desired
def intValue = COUNT as int
pipeline {
stages {
stage('Parameter Validation') {
steps {
script {
if ( intValue > 10 ) {
error("Instance count should be less than 10 and it is ${COUNT}")
}
}
}
}
stage('Clone Latest Repo') {
steps {
echo "Pull latest code"
build 'gitpull'
}
}
}
}
You just need to cast the string param to int :
if (Integer.parseInt(params.COUNT) > 10)
{
println ("Count > 10")
}
You complete pipeline:
pipeline {
agent {
label "${node_label}"
}
parameters {
string(defaultValue: "1", description: "Number of VM's to be Added", name: "COUNT")
}
stages {
stage('Parameter Validation') {
steps {
if ( Integer.parseInt(params.COUNT) > 10 ) {
error("Instance count should be less than 10 and it is ${COUNT}")
}
}
}
stage('Clone Latest Repo') {
steps {
echo "Pull latest code"
build 'gitpull'
}
}
Related
I looked at Call stage from function in Jenkinsfile which did some of what I wanted, but I had issues adding the code from the answer to my pipeline. I want to be able to scan for files in a folder and generate a stage for each file:
def foo = sh (
script: 'find ./collections/*.json -printf "%f\n"',
returnStdout: true
).trim().split("\n")
def parallelStagesFromMap = foo.collectEntries {
["Build ${it}" : generateStage(it)]
}
def generateStage(bar) {
return {
stage("Build ${bar}") {
echo "Building for ${bar}"
}
}
}
pipeline {
agent { label 'myExecutor' }
triggers {
pollSCM('') // empty cron expression string
cron('H 6 * * 1-5') // run every weekday at 06:00 https://crontab.guru/#0_6_*_*_1-5
}
options {
timeout(time: 20, unit: "MINUTES")
buildDiscarder(logRotator(numToKeepStr: '10', artifactNumToKeepStr: '10'))
disableConcurrentBuilds()
}
stages {
stage('Setup') {
steps {
script {
foo = ["1", "2", "3", "4", "5"]
}
}
}
stage('parallel') {
steps {
script {
parallel parallelStagesFromMap
generateStage("skipped") // no invocation, stage is skipped
generateStage("nonparallel").call()
}
}
}
}
post {
always {
echo ' * * * Doing POST actions'
//...
}
}
}
node {
parallel parallelStagesFromMap
generateStage("skipped") // no invocation, stage is skipped
generateStage("nonparallel").call()
}
This is essentially a hybrid between declarative and scripted pipelines, but it can be done like this:
Essentially you need to define the variables and execute the lookup in the setup stage and then run the stage generating code in a subsequent stage.
The node block is executed after the pipeline as you have put it, and the variable definitions are called before the code is checked out.
def foo
def parallelStagesFromMap
def generateStage(bar) {
return {
stage("Build ${bar}") {
echo "Building based on file ${bar}"
}
}
}
pipeline {
agent { label 'myExecutor' }
triggers {
pollSCM('') // empty cron expression string
cron('H 6 * * 1-5') // run every weekday at 06:00 https://crontab.guru/#0_6_*_*_1-5
}
options {
timeout(time: 20, unit: "MINUTES")
buildDiscarder(logRotator(numToKeepStr: '10', artifactNumToKeepStr: '10'))
disableConcurrentBuilds()
}
stages {
stage('Setup') {
steps {
script {
//scan collections folder for .json files
foo = sh (
script: 'find ./collections/*.json -printf "%f\n"',
returnStdout: true
).trim().split("\n")
parallelStagesFromMap = foo.collectEntries {
["Build ${it}" : generateStage(it)]
}
}
// do other setup-y stuff...
}
}
stage('Parallel Dynamic') {
steps {
script {
// https://stackoverflow.com/questions/55340071/call-stage-from-function-in-jenkinsfile
parallel parallelStagesFromMap
//generateStage("skipped") // no invocation, stage is skipped
//generateStage("nonparallel").call()
}
}
}
stage('static stage') {
steps {
// step to the mic ...
}
}
// more stages ...
}
post {
always {
echo ' * * * Doing POST actions'
//...
}
}
}
I am trying to customize a shared Library which run a stage in a specify agent by adding the possibility to specify the agent.
def call(String agentLabel) {
pipeline {
agent { label "$agentLabel" }
stages {
stage('Hello') { steps { echo 'Hello World' } }
}
}
}
This is OK but now I want to customize the type of agent (IE. either use label or docker agent) ?
This don't work :
def call(String agentLabel, String agentDockerImage = null) {
Closure agentRunner = null
if (agentDockerImage) {
agentRunner = {
docker {
label "$agentLabel"
image "$agentDockerImage"
}
}
} else {
agentRunner = {
label "$agentLabel"
}
}
pipeline {
agent { agentRunner.call() }
stages {
stage('Hello') { steps { echo 'Hello World' } }
}
}
}
WorkflowScript: 15: Invalid agent type "call" specified. Must be one of [any, docker, dockerfile, label, none] # line 15, column 29.
agent { agentRunner.call() }
^
I am trying to do a conditional step on Jenkins to see if the String Parameter contains a certain word.
I have a string for PLATFORM. The values in it can be Windows, Mac, Linux
I want to run a certain step if the value of the parameter contains Linux.
How can I do that? I downloaded the Jenkins plugin for conditional step but it doesn't have a contains clause.
You can use when directive of Jenkins to achieve the conditional steps.
Example:
pipeline {
agent any
stages {
stage ('Windows RUN') {
when {
expression { params.PLATFORM == 'Windows' }
}
steps {
echo "Hello, Windows"
}
}
stage ('Mac RUN') {
when {
expression { params.PLATFORM == 'Mac' }
}
steps {
echo "Hello, Mac"
}
}
stage ('Linux RUN') {
when {
expression { params.PLATFORM == 'Linux' }
}
steps {
echo "Hello, Linux"
}
}
}
}
Output:
I have the belo Jenkinsfile where I take user input for one and/or two parallel steps/stages. If the user input is empty, how can I exit that step/stage?
For example, if the user didn't enter any value for firstTask_build_number I need to echo "firstTask_build_number is empty - aborting firstTask!" and exit that. How can I exit safely?
pipeline {
agent any
parameters {
string(name: 'firstTask_build_number', defaultValue: '', description: 'Build ID of firstTask')
string(name: 'secondTask_build_number', defaultValue: '', description: 'Build ID of secondTask')
}
stage("Parallel") {
steps {
parallel (
"firstTask" : {
if (firstTask_build_number.size() == 0) {
echo "firstTask_build_number is empty - aborting firstTask!"
}
else {
//do some stuff
}
},
"secondTask" : {
if (secondTask_build_number.size() == 0) {
echo "secondTask_build_number is empty - aborting secondTask!"
}
else {
//do some stuff
}
}
)
}
}
}
You can just return out of it.
parallel (
"firstTask" : {
if (firstTask_build_number.size() == 0) {
echo "firstTask_build_number is empty - aborting firstTask!"
return
}
else {
//do some stuff
}
}
)
I have the following (part of a) pipeline
stages {
stage('bootstrap') {
parallel {
stage("Linux") {
agent { label 'linux' }
steps {
sh 'bootstrap.sh'
}
}
stage("Windows") {
agent { label 'Windows' }
steps {
bat 'bootstrap.bat'
}
}
}
}
stage('devenv') {
parallel {
stage('Linux') {
agent { label 'linux' }
steps {
sh 'devenv.sh'
}
}
stage('Windows') {
agent { label 'Windows' }
steps {
bat 'devenv.bat'
}
}
}
}
}
post {
always {
echo "Done"
}
}
The problem is that when bootstrap.bat fails on windows, the devenv step is now considered failed, and the linux devenv won't continue. I would like to have the results of the linux pipeline even if the windows one fails early.
An option would be to separate the stages so that linux full pipeline is on one branch of the parallel execution, and windows is on the other, but maybe there's a trick I am not aware of, because I tried it and it does not seem to be acceptable syntax.
Edit
Suggested fix does not work. This is the pipeline
pipeline {
agent none
parallel {
stage('Linux') {
agent { label 'linux' }
stages {
stage('bootstrap') {
sh "ls"
}
stage('devenv') {
sh "ls"
}
}
}
stage('windows') {
agent { label 'Windows' }
stages {
stage('bootstrap') {
bat 'dir'
}
stage('devenv') {
bat 'dir'
}
}
}
}
}
This is the error message
WorkflowScript: 8: Undefined section "parallel" # line 8, column 5.
parallel {
^
WorkflowScript: 1: Missing required section "stages" # line 1, column 1.
pipeline {
^