Jenkins File - Execute shell command in active choice script - jenkins

everyone, I'm using plugin "Active Choices" in my Jenkins, I try to do something condition, and the return based on environment host that will be executed in shell command in my Jenkins file. the command like "echo ${BUILD_ENVIRONMENT}, echo ${BUILD_VERSION}..etc".
Already doing this but the list is still empty. now, what do I have to do to make this work? thank you.
JenkinsFile:
properties([
parameters([
[$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'ENVIRONMENT',
description: 'Select Environment',
script: [
$class: 'GroovyScript',
script: [
classpath: [],
sandbox: true,
script: '''
def getEnvVar(String name) {
return sh(script: "echo \${$name}", returnStdout: true).trim()
}
def env = getEnvVar("ENVIRONMENT")
if (envs != "testing") {
return ["stage", "dev", "prod"]
}else{
return ["testing"]
}
''',
],
]
]
])
])
Output:

im fix it with another solution, but maybe isnt the best option.
1st create a method to load the env file (i set the values on it), then define to jenkins global variable.
getEnvHosts = { ->
node {
script {
// Get the environment hosts file
def props = readProperties file: '/var/lib/jenkins/env/dast-service-env'
//define to jenkins global variable
env.BUILD_ENVIRONMENT = props['BUILD_ENVIRONMENT']
}
}
}
and then i call the "BUILD_ENVIRONMENT" with ${env.BUILD_ENVIRONMENT} like this in active choice parameter:
getEnvHosts()
properties([
parameters([
[$class : 'ChoiceParameter',
choiceType : 'PT_SINGLE_SELECT',
name : 'BUILD_ENVIRONMENT',
description: "Select Environment default is ${env.BUILD_ENVIRONMENT}",
script : [
$class: 'GroovyScript',
script: [
classpath: [],
sandbox : true,
script : """
def envs = "${env.BUILD_ENVIRONMENT}"
if (envs == "stage") {
choices = ["stage", "dev", "prod", "testing"]
}else if (envs == "dev") {
choices = ["dev", "prod", "stage", "testing"]
}else if (envs == "prod") {
choices = ["prod", "dev", "stage", "testing"]
}else{
choices = ["testing", "stage", "dev", "prod"]
}
return choices
""",
],
]
],
])
])

Related

Is it possible to pass variable from steps to script in jenkinsfile

I have one pipeline and I want to pass one Arraylist that I get from a groovy method into the script that is running in Master Jenkins.
stages {
stage('Get Tests Parameter') {
steps {
code = returnList()
script {
properties([
parameters([
[$class : 'CascadeChoiceParameter',
choiceType : 'PT_CHECKBOX',
description : 'Select a choice',
defaultValue : '',
filterLength : 1,
filterable : false,
name : 'Tests',
referencedParameters: 'role',
script : [$class : 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox : true,
script : 'return ["ERROR"]'
],
script : [
classpath: [],
sandbox : false,
script : code
]
]
]
])
])
}
}
}
}
...
def returnList() {
def stringList = []
def fileContent = readFile "/var/jenkins_home/example.txt"
for (line in fileContent.readLines()) {
stringList.add(line.split(",")[0] + ":selected");
}
return stringList
}
That stages are running in a slave, so I couldn't execute that method returnList() inside the script because the script is running in Master. So I'm trying to get returnList ArrayList to a variable and use that variable in the script part.
Is that possible?
If you want to execute a specific step in a specific node then you can specify the agent within the stage block. So what you can do is execute the file reading logic on the master in the initial stage and then use it in consecutive stages. Check the example below.
def code
pipeline {
agent none
stages {
stage('LoadParameters') {
agent { label 'master' }
steps {
scipt {
code = returnList()
}
}
}
stage('Get Tests Parameter') {
steps {
script {
properties([
parameters([
[$class : 'CascadeChoiceParameter',
choiceType : 'PT_CHECKBOX',
description : 'Select a choice',
defaultValue : '',
filterLength : 1,
filterable : false,
name : 'Tests',
referencedParameters: 'role',
script : [$class : 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox : true,
script : 'return ["ERROR"]'
],
script : [
classpath: [],
sandbox : false,
script : code
]
]
]
])
])
}
}
}
}
}
def returnList() {
def stringList = []
def fileContent = readFile "/var/jenkins_home/example.txt"
for (line in fileContent.readLines()) {
stringList.add(line.split(",")[0] + ":selected");
}
return stringList
}

Dynamically filling parameters from a file in a Jenkins pipeline

TL;DR:
I would like to use ActiveChoice parameters in a Multibranch Pipeline where choices are defined in a YAML file in the same repository as the pipeline.
Context:
I have config.yaml with the following contents:
CLUSTER:
dev: 'Cluster1'
test: 'Cluster2'
production: 'Cluster3'
And my Jenkinsfile looks like:
pipeline {
agent {
dockerfile {
args '-u root'
}
}
stages {
stage('Parameters') {
steps {
script {
properties([
parameters([
[$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select the Environemnt from the Dropdown List',
filterLength: 1,
filterable: false,
name: 'Env',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script:
"return['Could not get The environemnts']"
],
script: [
classpath: [],
sandbox: true,
script:
'''
// Here I would like to read the keys from config.yaml
return list
'''
]
]
]
])
])
}
}
}
stage("Loading pre-defined configs") {
steps{
script{
conf = readYaml file: "config.yaml";
}
}
}
stage("Gather Config Parameter") {
options {
timeout(time: 1, unit: 'HOURS')
}
input {
message "Please submit config parameter"
parameters {
choice(name: 'ENV', choices: ['dev', 'test', 'production'])
}
}
steps{
// Validation of input params goes here
script {
env.CLUSTER = conf.CLUSTER[ENV]
}
}
}
}
}
I added the last 2 stages just to show what I currently have working, but it's a bit ugly as a solution:
The job has to be built without parameters, so I don't have an easy track of the values I used for each job.
I can't just built it with parameters and just leave, I have to wait for the agent to start the job, reach the stage, and then it will finally ask for input.
Choices are hardcoded.
The issue I'm currently facing is that config.yaml doesn't exist in the 'Parameters' stage since (as I understand) the repository hasn't been cloned yet. I also tried using
def yamlFile = readTrusted("config.yaml")
within the groovy code but it didn't work either.
I think one solution could be to try to do a cURL to the file, but I would need Git credentials and I'm not sure that I'm going to have them at that stage.
Do you have any other ideas on how I could handle this situation?

Active choice parameter with declarative Jenkins pipeline

I'm trying to use active choice parameter with declarative Jenkins Pipeline script.
This is my simple script:
environments = 'lab\nstage\npro'
properties([
parameters([
[$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select a choice',
filterLength: 1,
filterable: true,
name: 'choice1',
randomName: 'choice-parameter-7601235200970',
script: [$class: 'GroovyScript',
fallbackScript: [classpath: [], sandbox: false, script: 'return ["ERROR"]'],
script: [classpath: [], sandbox: false,
script: """
if params.ENVIRONMENT == 'lab'
return['aaa','bbb']
else
return ['ccc', 'ddd']
"""
]]]
])
])
pipeline {
agent any
tools {
maven 'Maven 3.6'
}
options {
disableConcurrentBuilds()
timestamps()
timeout(time: 30, unit: 'MINUTES')
ansiColor('xterm')
}
parameters {
choice(name: 'ENVIRONMENT', choices: "${environments}")
}
stages {
stage("Run Tests") {
steps {
sh "echo SUCCESS on ${params.ENVIRONMENT}"
}
}
}
}
But actually the second parameter is empty
Is it possible to use together scripted active choice parameter and declarative parameter?
UPD
Is there any way to pass list variable into script? For example
List<String> someList = ['ttt', 'yyyy']
...
script: [
classpath: [],
sandbox: true,
script: """
if (ENVIRONMENT == 'lab') {
return someList
}
else {
return['ccc', 'ddd']
}
""".stripIndent()
]
You need to use Active Choices Reactive Parameter which enable current job parameter to reference another job parameter value
environments = 'lab\nstage\npro'
properties([
parameters([
[$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select a choice',
filterLength: 1,
filterable: true,
name: 'choice1',
referencedParameters: 'ENVIRONMENT',
script: [$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script: 'return ["ERROR"]'
],
script: [
classpath: [],
sandbox: true,
script: """
if (ENVIRONMENT == 'lab') {
return['aaa','bbb']
}
else {
return['ccc', 'ddd']
}
""".stripIndent()
]
]
]
])
])
pipeline {
agent any
options {
disableConcurrentBuilds()
timestamps()
timeout(time: 30, unit: 'MINUTES')
ansiColor('xterm')
}
parameters {
choice(name: 'ENVIRONMENT', choices: "${environments}")
}
stages {
stage("Run Tests") {
steps {
sh "echo SUCCESS on ${params.ENVIRONMENT}"
}
}
}
}
As of Jenkins 2.249.2 without any plugin and using a declarative pipeline,
the following pattern prompt the user with a dynamic dropdown menu (for him to choose a branch):
(the surrounding withCredentials bloc is optional, required only if your script and jenkins configuratoin do use credentials)
node {
withCredentials([[$class: 'UsernamePasswordMultiBinding',
credentialsId: 'user-credential-in-gitlab',
usernameVariable: 'GIT_USERNAME',
passwordVariable: 'GITLAB_ACCESS_TOKEN']]) {
BRANCH_NAMES = sh (script: 'git ls-remote -h https://${GIT_USERNAME}:${GITLAB_ACCESS_TOKEN}#dns.name/gitlab/PROJS/PROJ.git | sed \'s/\\(.*\\)\\/\\(.*\\)/\\2/\' ', returnStdout:true).trim()
}
}
pipeline {
agent any
parameters {
choice(
name: 'BranchName',
choices: "${BRANCH_NAMES}",
description: 'to refresh the list, go to configure, disable "this build has parameters", launch build (without parameters)to reload the list and stop it, then launch it again (with parameters)'
)
}
stages {
stage("Run Tests") {
steps {
sh "echo SUCCESS on ${BranchName}"
}
}
}
}
The drawback is that one should refresh the jenkins configration and use a blank run for the list be refreshed using the script ...
Solution (not from me): This limitation can be made less anoying using an aditional parameters used to specifically refresh the values:
parameters {
booleanParam(name: 'REFRESH_BRANCHES', defaultValue: false, description: 'refresh BRANCH_NAMES branch list and launch no step')
}
then wihtin stage:
stage('a stage') {
when {
expression {
return ! params.REFRESH_BRANCHES.toBoolean()
}
}
...
}

Jenkins declarative pipeline: if-else statement inside parameters directive

I'm trying to display a choice parameter if I have options to choose from, or else display an input text, something like this (which does not work):
pipeline {
agent any
parameters {
if (someOptions) {
choice(name: 'FIELD_NAME', choices: "$someOptions", description: 'Field description')
} else {
string(name: 'FIELD_NAME', defaultValue: '', description: 'Field description')
}
}
environment {
// environment params
}
stages {
// stages
}
}
Is there a way of doing this?
To expand on #Matt Schuchard's comment, here's what this might look like:
def my_param = []
if (someOptions) {
my_param = [$class: 'ChoiceParameter',
name: 'FIELD_NAME',
choiceType: 'PT_SINGLE_SELECT',
description: 'Choose the desired option',
script:
[$class: 'GroovyScript',
fallbackScript:
[classpath: [], sandbox: false, script: 'return ""'],
script:
[classpath: [], sandbox: false, script: "return $someOptions"]
]
]
} else {
my_param = [$class: 'StringParameterDefinition',
name: 'FIELD_NAME',
defaultValue: false,
description: '']
}
properties([
parameters([my_param,
// other parameters
Don't forget to approve Groovy scripts in script approval console.

Jenkinsfile class CascadeChoiceParameter return my array as a string

I'm trying to use the CascadeChoiceParameter to dynamically mount my parameters form, using commands to create my list of options:
choiceType: 'PT_SINGLE_SELECT',
description: 'Informations about the application on kubernetes',
name: 'deployments',
omitValueField: false,
randomName: 'choice-parameter-5633384460832175',
referencedParameters: 'namespaces',
script: [
$class: 'GroovyScript',
script: [
classpath: [],
sandbox: true,
script: """
if (namespaces.equals("Select")){
return["Nothing to do - Select your deployment"]
} else {
def kubecmd = "kubectl get deploy --kubeconfig=${kubefileHlg} -o jsonpath={.items[*].metadata.name} -n " + namespaces
return [kubecmd.execute().in.text.split()]
}
"""
]
The form parameter on Jenkins shows me this - a single option with all values comma separated:
Do you have any idea how can I mount these options as a real list on it?
Your script in the "else" part returns a list that contains a single element of type String[] (an array of strings). What you need to return instead is a List<String>. Replace
return [kubecmd.execute().in.text.split()]
with
return kubecmd.execute().in.text.split().toList()
and you will see the expected result.
Quick example:
node {
properties([
parameters([
[
$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'someChoice',
script: [
$class: 'GroovyScript',
script: [
sandbox: true,
classpath: [],
script: '''
return "Lorem ipsum dolor sit amet".split().toList()
'''
]
]
]
])
])
stage("Test") {
echo env.someChoice
}
}
Output:

Resources