I'm trying to define a parallel section in my declarative jenkins pipeline.
I'm basing the syntax of this: https://jenkins.io/blog/2017/09/25/declarative-1/
But I get this error:
WorkflowScript: 74: Expected one of "steps", "stages", or "parallel" for stage "app cores" # line 74, column 3.
stage('bat cores') {
^
I've tried moving the parallel block around, but then I get other errors. As far as I can see I match the blog post above.
Any ideas?
Versions:
Jenkins ver. 2.138.1
Pipeline: Declarative version 1.3.2
My full pipeline looks like this:
pipeline {
agent { label 'master' }
options {
ansiColor('xterm')
}
parameters {
choice(name: 'STOP_ON_FIRST_FAILURE', choices: ['true', 'false'], description: '....')
choice(name: 'RUN_MODE', choices: [
'plan, confirm, apply',
'plan, confirm, apply, then destroy',
'destroy'],
description: "Choose to destroy resources at end" )
string(name: 'GIT_REPO_BRANCH', defaultValue: 'production', description: '...')
}
stages {
stage('thing container') {
steps {
build job: '/DevWork/DT/production branch/FA1/FA1 thing Creation', propagate: params.STOP_ON_FIRST_FAILURE
}
}
stage('bat cores') {
steps {
build(
job: '/DevWork/DT/production branch/FA1/FA1 thing Creation',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
build(
job: '/DevWork/DT/production branch/FA1/FA103/FA103 bat Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
build(
job: '/DevWork/DT/production branch/FA1/FA104/FA104 bat Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
build(
job: '/DevWork/DT/production branch/FA1/FA101/FA101 bat Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
build(
job: '/DevWork/DT/production branch/FA1/FA102/FA102 bat Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
}
}
stage('app cores') {
steps {
parallel {
stage('FA10302 Application Core') {
steps {
build(
job: '/DevWork/DT/production branch/FA1/FA103/FA10302 Application Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
}
}
stage('FA10301 Application Core') {
steps {
build(
job: '/DevWork/DT/production branch/FA1/FA103/FA10301 Application Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
}
}
stage('FA10101 Application Core') {
steps {
build(
job: '/DevWork/DT/production branch/FA1/FA101/FA10101 Application Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
}
}
}
}
}
}
}
You made the mistake to use the "negative" example of the development blog:
In earlier versions of Declarative Pipeline, the only way to run
chunks of Pipeline code in parallel was to use the parallel step
inside the steps block for a stage, like this: YOUR EXAMPLE
While this works, it doesn’t integrate well with the rest of the
Declarative Pipeline syntax.
I think your issue is located here:
stage('app cores') {
steps { // This step{} is causing the issue, remove it
The "real" syntax is labeled like the following in the development blog:
But now with Declarative Pipeline 1.2, we’ve introduced a true
Declarative syntax for running stages in parallel:
This would look like the following (simply remove your steps{} from above):
stage('app cores')
{
parallel {
stage('FA10302 Application Core') {
steps {
build(
job: '/DevWork/DT/production branch/FA1/FA103/FA10302 Application Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
}
}
stage('FA10301 Application Core') {
steps {
build(
job: '/DevWork/DT/production branch/FA1/FA103/FA10301 Application Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
}
}
stage('FA10101 Application Core') {
steps {
build(
job: '/DevWork/DT/production branch/FA1/FA101/FA10101 Application Core',
propagate: params.STOP_ON_FIRST_FAILURE,
parameters: [
[$class: 'StringParameterValue', name: 'RUN_MODE', value: params.RUN_MODE],
[$class: 'StringParameterValue', name: 'GIT_REPO_BRANCH', value: params.GIT_REPO_BRANCH],
]
)
}
}
} // close the stage 'app cores'
It might sounds stupid, but as I've found out today, also typo in the word parallel can throw this exception.
Related
I am using this groovy script to parameterize a Jenkins Job:
properties([
parameters([
[$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select param1',
filterLength: 1,
filterable: false,
name: 'param1',
randomName: 'choice-parameter-5631314439613978',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script:
'return[\'Could not get param1\']'
],
script: [
classpath: [],
sandbox: true,
script:
'return["value1", "value2", "value3"]'
]
]
],
[$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select param3',
filterLength: 1,
filterable: false,
name: 'param3',
randomName: 'choice-parameter-10000000000000000',
referencedParameters: 'param1',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script:
'return[\'Could not get param3\']'
],
script: [
classpath: [],
sandbox: true,
script:
''' if (param1.equalsIgnoreCase('value1')){
return["1", "2"]
}
else if(param1.equalsIgnoreCase("value2")){
return["3", "4"]
}
else if(param1.equalsIgnoreCase("value3")){
return["5", "6"]
}
'''
]
]
]
])
])
pipeline {
agent any
parameters {
string(name: "param2", defaultValue: "test1", description: "Test value")
}
stages {
stage ("Example") {
steps {
script{
echo 'Hello'
}
}
}
}
}
If I use this script as is, On the Jenkins job, parameters will be shown in this order: param2, param1, param3. What I really want, is to have them in this order: param1, param2, param3.
From the code as you can see, for param 1 and 3 I am using Active Choice Parameter and Active Choice Reactive Parameter which will be dependent from the value selected in param1. For param2, I need it as string.
Is there a way to achieve this, have them in this order: param1, param2, param3?
Okay, i found that i can use also this in the properties:
[$class: 'StringParameterDefinition',
description: 'Enter param2',
name: 'param2',
defaultValue: '',
randomName: 'string-parameter-1343433232',
trim: true
]
So I have a Jenkinsfile that has following steps
stage"xyzclientj_maven_common"
build job: 'xyzclientj_maven_common', propagate: true, parameters:
[
[$class: 'StringParameterValue', name: 'SVN_TAG', value: env.SVN_TAG],
[$class: 'StringParameterValue', name: 'VERSION', value: env.VERSION]
],
parallel (
"multios" : {
build job: 'ccsmp_tag_multios', parameters:
[
[$class: 'StringParameterValue', name: 'SVN_TAG', value: env.SVN_TAG],
[$class: 'StringParameterValue', name: 'VERSION', value: env.VERSION]
],
propagate: true
},
"OpenVms-ia64" : {
build job: 'ccsmp_tag_OpenVms-ia64', parameters:
[
[$class: 'StringParameterValue', name: 'SVN_TAG', value: env.SVN_TAG],
[$class: 'StringParameterValue', name: 'VERSION', value: env.VERSION]
],
propagate: true
},
"win_platform" : {
build job: 'ccsmp_tag_win_platform', parameters:
[
[$class: 'StringParameterValue', name: 'SVN_TAG', value: env.SVN_TAG],
[$class: 'StringParameterValue', name: 'VERSION', value: env.VERSION]
],
propagate: true
},
"iphoneOS_176" : {
build job: 'ccsmp_tag_iphoneOS_176', parameters:
[
[$class: 'StringParameterValue', name: 'SVN_TAG', value: env.SVN_TAG],
[$class: 'StringParameterValue', name: 'VERSION', value: env.VERSION]
],
propagate: true
},
"epoll-linux26-x64" : {
build job: 'ccsmp_tag_epoll-linux26-x64', parameters:
[
[$class: 'StringParameterValue', name: 'SVN_TAG', value: env.SVN_TAG],
[$class: 'StringParameterValue', name: 'VERSION', value: env.VERSION]
],
propagate: true
},
"android" : {
build job: 'android', parameters:
[
[$class: 'StringParameterValue', name: 'SVN_TAG', value: env.SVN_TAG],
[$class: 'StringParameterValue', name: 'VERSION', value: env.VERSION]
],
propagate: true
},
failFast: false
)
Is there any way to achieve and copy the artifacts made by these downstream jobs to my top level multibranch pipeline job.
( Some background details- So I have a top level branch agnostic multibranch pipeline job called ccsmp and It uses my Jenkinsfile to trigger downstream jobs, some of these jobs are sequential and also parallel. These jobs produce artifacts and I don't know how to achieve and copy these artifacts produced by these jobs to my top level job. I just cant wrap my head around this.)
Please help me any suggestions would be highly appreciated.
// trigger the other job and wait for it to complete
final job_result = build job: 'TheOtherJob',
wait: true,
parameters: [
string(name: 'NAME1', value: "value1"), // etc.
]
// get downstream job build number
def downstream_job_number = "${job_result.number}"
// copy artifact of the other job to this workspace
// provided by a Jenkins Plugin
def path_to_artifact = 'my_file.txt'
step([
$class: 'CopyArtifact',
filter: path_to_artifact,
fingerprintArtifacts: true,
optional: true,
projectName: "TheOtherJob",
selector: [$class: 'SpecificBuildSelector',
buildNumber: downstream_job_number]
])
// you can read that artifact now
def artifact_text = readFile file: path_to_artifact
println artifact_text
// or archive it as your job artifact
archiveArtifacts allowEmptyArchive: true,
artifacts: "${path_to_artifact}",
caseSensitive: false, defaultExcludes: false, onlyIfSuccessful: true
I have a jenkins pipeline configured which calls different build job and passes different values to the job. I have multiple suites configured which would trigger jobs to run in parallel.
Here is the sample code:
pipeline {
agent any
parameters {
string(name: 'ARRAY', defaultValue: 'AR1234', description: 'Enter array. ')
string(name: 'email_recepients', defaultValue: 'abc#xyz.com', description: 'Enter email id')
choice(name: 'regression_suite', choices: ['suite1', 'suite2', 'all'], description: '')
choice(name: 'PRODUCT_RELEASE', choices: ['R1', 'R2'], description: 'Release on which test is being run')
choice(name: 'interface', choices: ['int1', 'int2'], description: 'interface to use?')
choice(name: 'Update_UTMS', choices: ['false', 'true'], description: 'Update UTMS/QC? If yes, select true')
string(name: 'testset_id_1', defaultValue: 'NA', description: 'If Suite1, enter xxx ID <br> \
If Suite2, enter yyy ID <br> ')
string(name: 'testset_id_2', defaultValue: 'NA', description: 'If Suite1, enter zzz ID <br> \
If Suite2, enter aaa ID <br> ')
string(name: 'testset_id_3', defaultValue: 'NA', description: 'If Suite1, enter bbb ID <br> \
If Suite2, enter ccc ID <br>')
string(name: 'testset_id_4', defaultValue: 'NA', description: 'If Suite1, enter ddd ID <br> \
If Suite2, enter fff ID <br>')
string(name: 'testset_id_5', defaultValue: 'NA', description: 'If Suite1, enter eee ID')
string(name: 'testset_all', defaultValue: '1,2,3,4,5,6,7,8,9', description: 'All of Testset IDs')
}
stages {
stage('Starting Suite1 (Parallel execution)') {
when {
expression {
params.regression_suite == "suite1" || params.regression_suite == "all"
}
}
steps {
script {
try {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
suite1()
}
} finally {
echo "Suite1 completed, but we continue"
}
}
}
}
stage('Starting Suites2 (Parallel execution)') {
when {
expression {
params.regression_suite == "suite2" || params.regression_suite == "all"
}
}
steps {
script {
try {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
suite2()
}
} finally {
echo "Suite2 completed, but we continue"
}
}
}
}
}
}
def suite1() {
parallel(
bla1: {
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla1'), string(name: 'Interface', value: params.interface + '_0'),booleanParam(name: 'Update_UTMS', value: params.Update_UTMS), string(name: 'utms_testset_id', value: "${params.testset_id_1}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
bla1: {
sleep(60)
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla2'), string(name: 'Interface', value: params.interface + '_1'),booleanParam(name: 'Update_UTMS', value: params.Update_UTMS), string(name: 'utms_testset_id', value: "${params.testset_id_2}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
bla3: {
sleep(120)
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla3'), string(name: 'Interface', value: params.interface + '_2'),booleanParam(name: 'Update_UTMS', value: params.Update_UTMS), string(name: 'utms_testset_id', value: "${params.testset_id_3}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
bla4: {
sleep(180)
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla4'), string(name: 'Interface', value: params.interface + '_3'),booleanParam(name: 'Update_UTMS', value: false), string(name: 'utms_testset_id', value: "${params.testset_id_4}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
bla5: {
sleep(240)
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla5'), string(name: 'Interface', value: params.interface + '_4'),booleanParam(name: 'Update_UTMS', value: params.Update_UTMS), string(name: 'utms_testset_id', value: "${params.testset_id_5}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
failFast: false)
}
def suite2() {
parallel(
bla6: {
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla6'), string(name: 'Interface', value: params.interface + '_0'), string(name: 'utms_testset_id', value: "${params.testset_id_1}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
bla7: {
sleep(60)
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla7'), string(name: 'Interface', value: params.interface + '_1'), string(name: 'utms_testset_id', value: "${params.testset_id_2}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
bla8: {
sleep(180)
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla8'), string(name: 'Interface', value: params.interface + '_3'), string(name: 'utms_testset_id', value: "${params.testset_id_3}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
bla9: {
sleep(240)
build job: 'sd_regression',
parameters: [string(name: 'ARRAY', value: "${params.ARRAY}"), string(name: 'email_recepients', value: "${params.email_recepients}"), string(name: 'test_type', value: 'bla9'), string(name: 'Interface', value: params.interface + '_4'), string(name: 'utms_testset_id', value: "${params.testset_id_4}"), string(name: 'PRODUCT_RELEASE', value: params.PRODUCT_RELEASE)]
},
failFast: false)
}
Here I have input parameter called regression_suite which has option called all.
If all is selected, then user would provide comma separated values to parameter testset_all (example: 1,2,3,4,5).
I want a code where I would read these values and split them and store it in variables. I would then substitute these values to my job params.
Example:
var_1= 1
var_2= 2
var_3= 3 and so on.
Thank you.
You could use below pipeline script, I have looped through array and printed the value, instead echo statement you can assign that to a variable.
def loop_func(values){
values.each {
item -> echo "Hello ${item}"
}
}
pipeline {
agent any
parameters {
choice(name: 'regression_suite', choices: ['suite1', 'suite2', 'all'], description: '')
string(name: 'testset_all', defaultValue: '1,2,3,4,5,6,7,8,9', description: 'All of Testset IDs')
}
stages {
stage ("Test Stage"){
when {
expression {
"${params.regression_suite}" == "all"
}
}
steps {
script {
def values = "${params.testset_all}".split(',')
loop_func(values)
}
}
}
}
}
Updated:
def loop_func(values){
for (int i=0; i<values.size();i++) {
env."var_${i}"=values[i]
}
}
pipeline {
agent any
parameters {
choice(name: 'regression_suite', choices: ['suite1', 'suite2', 'all'], description: '')
string(name: 'testset_all', defaultValue: '1,2,3,4,5,6,7,8,9', description: 'All of Testset IDs')
}
stages {
stage ("Test Stage"){
when {
expression {
"${params.regression_suite}" == "all"
}
}
steps {
script {
def values = "${params.testset_all}".split(',')
loop_func(values)
echo "The final Value is : ${env.var_6}"
}
}
}
stage("Test Stage2"){
steps{
echo "${env.var_8}"
}
}
}
}
In jenkinsfile, I have around 10 jobs and to each Job I am passing parameters as below
stage('Test1 )
steps {
script {
echo 'Starting "test1"'
build job: './test1
parameters: [
[$class: 'StringParameterValue', name: 'INSTANCE_NAME', value: params.INSTANCE_NAME ],
[$class: 'StringParameterValue', name: 'WORKSPACE', value: params.WORKSPACE ],
[$class: 'StringParameterValue', name: 'APP_NAME', value: 'test' ],
[$class: 'StringParameterValue', name: 'GIT_BRANCH', value: params.GIT_BRANCH ],
] } }
stage('Test2 )
steps {
script {
echo 'Starting "test2"'
build job: './test2' ,
parameters: [
[$class: 'StringParameterValue', name: 'INSTANCE_NAME', value: params.INSTANCE_NAME ],
[$class: 'StringParameterValue', name: 'WORKSPACE', value: params.WORKSPACE ],
[$class: 'StringParameterValue', name: 'APP_NAME', value: 'test' ],
[$class: 'StringParameterValue', name: 'GIT_BRANCH', value: params.GIT_BRANCH ],
] } }
Is there a way I can define this section outside and use it to pass to the jobs
I am trying the same query # Pass (same) parameters to multiple build jobs in a Jenkins pipeline
Thank you
We could pass a map with parameters to build job
def jobParameters = [:]
jobParameters['INSTANCE_NAME'] = params.INSTANCE_NAME
jobParameters['WORKSPACE'] = params.WORKSPACE
def paramsObjects = []
jobParameters.each {
key, value ->
paramsObjects.push([$class: 'StringParameterValue', name: key, value: value])
}
paramsObjects would look like this:
[
[$class:StringParameterValue, name:param1, value:value1],
[$class:StringParameterValue, name:param2, value:value2]
]
The stage config will look like this:
stages {
stage('Test1')
steps {
script {
echo 'Starting "test1"'
build job: './test1'
parameters:
paramsObjects
}
}
stage('Test2')
steps {
script {
echo 'Starting "test2"'
build job: './test2',
parameters: paramsObjects
}
}
}
I wrote below code to execute jobs in sequence in Pipeline script Jenkins, but I have a requirement to run 'build' and 'Undeploy' from below as parallel and then 'Deploy' after that
node: {
stage 'build'
build job: 'JenkinsTest', parameters: [
[$class: 'StringParameterValue', name: 'VERSION', value: "${VERSION}"],
[$class: 'StringParameterValue', name: 'RBFLAG', value: "${RBFLAG}"],
[$class: 'StringParameterValue', name: 'SET_ENV', value: "${SET_ENV}"]
]
stage 'Undeploy'
build job: 'Undeploy job', parameters: [
[$class: 'StringParameterValue', name: 'RBFLAG', value: "${RBFLAG}"]
]
stage 'Deploy'
build job: 'Deploy job', parameters: [
[$class: 'StringParameterValue', name: 'RBFLAG', value: "${RBFLAG}"]
]
}
Please help.
Give it a try with something like below, using parallel: 1
pipeline {
agent any
stages {
stage('First Stage'){
steps{
script{
parallel(
"build":{
build job: 'JenkinsTest', parameters: [
[$class: 'StringParameterValue', name: 'VERSION', value: "${VERSION}"],
[$class: 'StringParameterValue', name: 'RBFLAG', value: "${RBFLAG}"],
[$class: 'StringParameterValue', name: 'SET_ENV', value: "${SET_ENV}"]
]
},
"undeploy":{
build job: 'Undeploy job', parameters: [
[$class: 'StringParameterValue', name: 'RBFLAG', value: "${RBFLAG}"]
]
}
)
}
}
}
stage('Second stage') {
steps{
script{
build job: 'Deploy job', parameters: [
[$class: 'StringParameterValue', name: 'RBFLAG', value: "${RBFLAG}"]
]
}
}
}
}
}