Load declarative pipeline from inline function - jenkins

I've seen this example on how to load declarative piplines form a shared Library:
https://jenkins.io/doc/book/pipeline/shared-libraries/#defining-declarative-pipelines
But I would like to have the pipeline as inline functions:
def linux_platform = "U1604_x64_gcc54"
def windows_platform = "WIN10_x64_vc141"
properties(
[
parameters(
[
choice(name: 'platform', choices: [linux_platform, windows_platform], description: 'Platform'),
string(defaultValue: "-1", description: 'Upsteam Project build number', name: 'upsteam_project_build_number')
]
)
]
)
if(params.platform == windows_platform) {
windows(params.upsteam_project_build_number)
}
def windows(upsteam_project_build_number) {
pipeline {
agent {
label windows_platform
}
environment {
WINDOWS_ENV = "C:/my_path"
}
stages {
stage('Do stuff') {
steps{
echo "Doing stuff"
}
}
}
post {
failure {
job_status_mail(currentBuild.currentResult, JOB_NAME, BUILD_NUMBER, BUILD_URL)
}
fixed {
job_status_mail("fixed", JOB_NAME, BUILD_NUMBER, BUILD_URL)
}
}
}
}
Im getting the following error:
java.lang.NoSuchMethodError: No such DSL method 'agent' found among steps
Is my syntax some how wrong or is it not possible to load a pipeline from a inlne function?
I'm running:
Jenkins ver. 2.138.4
Declarative Pipeline Plugin ver. 1.3.8

Related

Jenkins parameters using groovy script

UPDATE
I have a simple pipeline where I want to receive in parameters multiple choices from a file.
In my file I have
#Test1,Accounts
#Test2,Services
#Test3,Accesses
and I want to have all of "#Test1", "#Test2" and "#Test3" in checkboxes as parameters so I would run only the tests selected.
But I'm not understanding what I'm doing wrong.
Pipeline
def code = """tests = getChoices()
return tests
def getChoices() {
def filecontent = readFile "/var/jenkins_home/test.txt"
def stringList = []
for (line in filecontent.readLines()) {stringList.add(line.split(",")[0].toString())}
List modifiedList = stringList.collect{'"' + it + '"'}
return modifiedList
}""".stripIndent()
properties([
parameters([
[$class : 'CascadeChoiceParameter',
choiceType : 'PT_CHECKBOX',
description : 'Select a choice',
filterLength : 1,
filterable : false,
name : 'choice1',
referencedParameters: 'role',
script : [$class : 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox : true,
script : 'return ["ERROR"]'
],
script : [
classpath: [],
sandbox : true,
script : code
]
]
]
])
])
pipeline {
agent {
docker { image 'node:latest' }
}
stages {
stage('Tags') {
steps {
getChoices()
}
}
}
}
def getChoices() {
def filecontent = readFile "/var/jenkins_home/test.txt"
def stringList = []
for (line in filecontent.readLines()) {
stringList.add(line.split(',')[0].toString())
}
List modifiedList = stringList.collect { '"' + it + '"' }
echo "$modifiedList"
return modifiedList
}
With this approach I know I can use multi-select checkboxes because I tried to substitute
def code = """ tests = ["Test1", "Test2", "Test3"]
return tests""".stripIndent()
and I get the output that I wanted.
But when I run my pipeline I get build SUCCESS but always get fallbackScript in my Build parameters checkbox. Can anyone help me out understand what is causing fallbackScript to run always? Thanks :)
If you want to auto-populate build parameters you have to return a list of parameters from your function. When you execute the pipeline the build with parameters will be populated. Note in this was only from the second execution of the pipeline the new parameters will be available. Refer following.
pipeline {
agent any
parameters{
choice(name: 'TESTES', choices: tests() , description: 'example')
}
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
def tests() {
return ["Test01", "Test2", "Test4"]
}
If you want to get user input each time you execute a build you should move your choice parameter into a stage. Please refer to the following.
pipeline {
agent any
stages {
stage('Get Parameters') {
steps {
script{
def choice = input message: 'Please select', ok: 'Next',
parameters: [choice(name: 'PRODUCT', choices: tests(), description: 'Please select the test')]
echo '$choice'
}
}
}
}
}
def tests() {
return ["Test01", "Test2", "Test4"]
}
Update 02
Following is how to read from a file and dynamically create the choice list.
pipeline {
agent any
stages {
stage('Get Parameters') {
steps {
script{
sh'''
echo "#Test1,Accounts" >> test.txt
echo "#Test2,Services" >> test.txt
'''
def choice = input message: 'Please select', ok: 'Next',
parameters: [choice(name: 'PRODUCT', choices: getChoices(), description: 'Please select the test')]
}
}
}
}
}
def getChoices() {
def filecontent = readFile "test.txt"
def choices = []
for(line in filecontent.readLines()) {
echo "$line"
choices.add(line.split(',')[0].split('#')[1])
}
return choices
}

How to do Multiple conditional execution of stage using 'when' in declarative pipeline?

I am trying to convert Scripted pipelines into Declarative Pipeline.
Here is a
Pipeline:
pipeline {
agent any
parameters {
string(defaultValue: '',
description: '',
name : 'BRANCH_NAME')
choice (
choices: 'DEBUG\nRELEASE\nTEST',
description: '',
name : 'BUILD_TYPE')
}
stages {
stage('Release build') {
when {
expression {params.BRANCH_NAME == "master"}
expression {params.BUILD_TYPE == 'RELEASE'}
}
steps {
echo "Executing Release\n"
}
} //stage
} //stages
} // pipeline
Intension is that all the parameter values need to be compared under when and only then I wanted executed a stage.
In scripted pipeline you can use && like in snippet below.
stage('Release build') {
if ((responses.BRANCH_NAME == 'master') &&
(responses.BUILD_TYPE == 'RELEASE')) {
echo "Executing Release\n"
}
}
How to get collective return from expression in declarative pipeline?
It has to be like
pipeline {
agent any
parameters {
string(defaultValue: '',
description: '',
name : 'BRANCH_NAME')
choice (
choices: 'DEBUG\nRELEASE\nTEST',
description: '',
name : 'BUILD_TYPE')
}
stages {
stage('Release build') {
when {
allOf {
expression {params.BRANCH_NAME == "master"};
expression {params.BUILD_TYPE == 'RELEASE'}
}
}
steps {
echo "Executing Release\n"
}
} //stage
} //stages
} // pipeline
you can find other dsl support inside when here

Use Jenkins WORKSPACE environment variable in Jenkins declarative pipeline parameter

Is there a way to use Jenkins WORKSPACE environment variable in Jenkins declarative pipeline parameters?
Below attempt failed.
pipeline {
parameters {
extendedChoice description: 'Template in project',
multiSelectDelimiter: ',', name: 'TEMPLATE',
propertyFile: env.WORKSPACE + '/templates.properties',
quoteValue: false, saveJSONParameterToFile: false, type: 'PT_MULTI_LEVEL_SINGLE_SELECT',
value: 'Project,Template', visibleItemCount: 6
...
}
stages {
...
}
propertyFile: '${WORKSPACE}/templates.properties' didn't work either.
The environment variable can be accessed in various place in Jenkinsfile like:
def workspace
node {
workspace = env.WORKSPACE
}
pipeline {
agent any;
parameters {
string(name: 'JENKINS_WORKSPACE', defaultValue: workspace, description: 'Jenkins WORKSPACE')
}
stages {
stage('access env variable') {
steps {
// in groovy
echo "${env.WORKSPACE}"
//in shell
sh 'echo $WORKSPACE'
// in groovy script
script {
print env.WORKSPACE
}
}
}
}
}
The only way that worked is putting absolute path to Jenkins master workspace where properties file is located.
pipeline {
parameters {
extendedChoice description: 'Template in project',
multiSelectDelimiter: ',', name: 'TEMPLATE',
propertyFile: 'absolute_path_to_master_workspace/templates.properties',
quoteValue: false, saveJSONParameterToFile: false, type: 'PT_MULTI_LEVEL_SINGLE_SELECT',
value: 'Project,Template', visibleItemCount: 6
...
}
stages {
...
}
It seems that environment variables are not available during pipeline parameters definition before the pipeline actually triggered.

How to share stages between Jenkins Pipelines

I have two JenkinsFile files where I want to share the same stages:
CommonJenkinsFile:
pipeline {
agent {
node {
label 'devel-slave'
}
}
stages {
stage("Select branch") {
options {
timeout(time: 3, unit: 'MINUTES')
}
steps {
script {
env.branchName = input(
id: 'userInput', message: 'Enter the name of the branch you want to deploy',
parameters: [
string(
defaultValue: '',
name: 'BranchName',
description: 'Name of the branch'),
]).replaceAll('\\/', '%2F')
}
}
}
}
Where I want to use it:
pipeline {
agent {
node {
label 'devel-slave'
}
}
load 'CommonJenkinsFile'
stages {
stage('Deploy to test') {
}
}
How can this stages be shared? Should I change to the Scripted Pipelines? Can they share stages or only steps?
CommonJenkinsfile cannot contain the pipeline directive (otherwise you are executing a pipeline within a pipeline). I think you also need to move it to the scripted syntax instead of the declarative (might be wrong there)
This file could look like this:
def commonStep(){
node('devel-slave'){
stage("Select branch") {
timeout(time: 3, unit: 'MINUTES'){
env.branchName = input ...
}
}
}
}
return this
You can then load it like this
stage('common step'){
script{
def sharedSteps = load "$workspace/common.groovy"
sharedSteps.commonStep()
}
}

Version Number Plugin in Jenkins declarative pipeline

I'm trying to use version number plugin to format a version number for our
packages.
From some reason the placement for the version variable doesn't work
and when I echo the following I only get the build number, for instance: "...54"
def Version_Major = '1'
def Version_Minor = '0'
def Version_Patch = '0'
pipeline {
environment {
VERSION = VersionNumber([
versionNumberString: '${Version_Major}.${Version_Minor}.${Version_Patch}.${BUILD_NUMBER}',
worstResultForIncrement: 'SUCCESS'
]);
}
stage ('Restore packages'){
steps {
script{
echo "${VERSION}"
}
}
}
}
Edit: It does look like an issue with the plugin usage since this works:
properties([
parameters([
string(name: 'Version_Major', defaultValue: '1', description: 'Version Major'),
string(name: 'Version_Minor', defaultValue: '0', description: 'Version Minor'),
string(name: 'Version_Patch', defaultValue: '0', description: 'Version Patch')
])
])
pipeline {
agent any
environment {
VERSION = "${params.Version_Major}.${params.Version_Minor}.${params.Version_Patch}.${BUILD_NUMBER}"
}
stages{
stage ('Test'){
steps {
echo "${VERSION}"
}
}
}
}
You must define the variables inside the pipeline.
Try this:
pipeline {
environment {
Version_Major = '1'
Version_Minor = '0'
Version_Patch = '0'
VERSION = VersionNumber([
versionNumberString: '${Version_Major}.${Version_Minor}.${Version_Patch}.${BUILD_NUMBER}',
worstResultForIncrement: 'SUCCESS'
]);
}
stage ('Restore packages'){
steps {
script{
echo "${VERSION}"
}
}
}
}
If you need to use a parameter instead that's also possible via:
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
}
usage:
"Hello ${params.PERSON}"

Resources