Accessing jenkins env params from inside a GroovyScript in properties - jenkins

I have a jenkins job:
properties([
parameters([
[$class: 'ChoiceParameter', choiceType: 'PT_CHECKBOX', description: '''The name of the image to be used.''', filterLength: 1, filterable: true, name: 'OS', randomName: 'choice-parameter-15413073438404172', script: [$class: 'GroovyScript', fallbackScript: [classpath: [], sandbox: true, script: ''], script: [classpath: [], sandbox: true, script: '''templates = [
"BB-Win7-x32-SP1",
"BB-Win7-x64-SP1",
"BB-Win10-x64-RS1",
"BB-Win10-x64-RS2",
"BB-Win10-x32-RS5"]
return templates''']]]])
])
....
....
Which is working and generates the checkbox property for the GUI as expected.
Now, I want to generate those options dynamically, based on a file in my workspace. For this, I need the workspace environment variable inside the groovy script. How can I do that?

Jenkins needs to figure out all the parameters before it runs a pipeline. So your problem, basically, boils down to "How can I run an (arbitrary) groovy script before I run a pipeline?"
There are two options for this:
As I mentioned, ActiveChoice plugin allows you to define a parameter that returns a script. Jenkins will then run the script (don't forget to approve it) in order to show you your "Build with parameters" page. Debugging this is notoriously hard, but this can go to great lengths.
Alternatively, you may want to run a scripted pipeline before you run the Declarative (main) one, as outlined e.g. in this answer. This may look a bit like this:
def my_choices_list = []
node('master') {
stage('prepare choices') {
// read the file contents
def my_choices = sh script: "cat ${WORKSPACE}/file.txt", returnStdout:true
// make a list out of it - I haven't tested this!
my_choices_list = my_choices.trim().split("\n")
}
}
pipeline {
parameters {
choiceParam('OPTION', my_choices_list)

Related

Accessing global variables from an Active Choice parameter's script block in a declarative pipeline

I have the following code in my Jenkinsfile:
def testList = ['a','b','c']
properties([[
[$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Some description',
filterLength: 1,
filterable: true,
name: 'TestParameter',
randomName: 'choice-parameter-47114921421532360',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: false,
script: 'return [\'ERROR\']'
],
script: [
classpath: [],
sandbox: false,
script: 'return testList'
]
]]
]])
How can I get the value of testList to the script block here without string interpolation?
I do not want to use string interpolation because in production, testList will be dynamically populated. This has the nasty side effect of having to reapprove the script block in Jenkins via Script Approval every time testList is modified. I also do not want to expose an additional parameter to the user here (I could use a Choice parameter to get testList and then use "param.myChoiceParameter" to get the Active Choice working). And finally, I don't know if it would solve my issue, but I don't want the effort of creating a shared library at this time.
Things I've tried and either didn't work or had side effects.
String interpolation with inspect ("return $testList.Inspect()}" in the script block)
Adding #field to testList
Some other SO question said to add an ArrayList object to Parameters, which throws an an exception saying an ArrayList type is not recognized as a parameter type.

Get all jobs in a View in active choice parameters using groovy script

I am quite new to Jenkins and pipelines.
I have multiple jobs running in a view which needs to be say enabled and disabled at certain times.
I am able to get all the jobs and enable or disable it, I did as below
for (item in Jenkins.instance.getView("Test").items) {
println("\nJob: $item.name")
def status = Jenkins.instance.getItem("$item.name").isBuildable()
println ("\nJob $item.name is Buildable : $status ")
if (params.job_action == 'disable'){
Jenkins.instance.getItem("$item.name").setDisabled(true)
}
if (params.job_action == 'enable') {
Jenkins.instance.getItem("$item.name").setDisabled(false)
}
}
Instead using for loop using list of jobs in code i want it to pass as parameter. like jobs can be selected in active choice parameters using check boxes or multi select option etc.
I tried somethings but its not giving an output in parameters instead its coming as blank.
TIA.
This is a possible solution:
properties([
parameters([
[
$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'JobName',
description: 'Parameter that displays all jobs in a view.',
filterable: true,
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script: '''
return ['Error: The script failed or it is not allowed by Jenkins. Check Script approval from General Settings.']
'''
],
script: [
classpath: [],
sandbox: false,
script: '''
return jenkins.model.Jenkins.instance.getView("myViewName").items.collect { job -> return job.displayName }
'''
]
]
]
])
])
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo "${env.JobName}"
}
}
}
}
As the fallback script mentions, this script needs to be accepted in Script approval from General Settings. Make sure to set sandbox: false. Besides that, it is pretty straight forward. If you need help with the Active Choices Plugin maybe <your_jenkins_url>/pipeline-syntax > Snippet Generator > properties could come in handy.

Export build parameters into shared library

This is an example of my Jenkinsfile:
properties([
parameters([
booleanParam(defaultValue: false, name: 'BuildAll', description: ''),
// lots of params here, some of them are Active Choice Plugin params...
])
])
pipeline {
agent any
stages {
stage ('Initialize') {
// code...
}
}
}
Now, is it posslible to export those parameters (that are enclosed inside "properties" section) into shared library?
Jenkins shared library: https://www.jenkins.io/doc/book/pipeline/shared-libraries/
I have lots of params and many similar projects and I would like simply to define parameters on one place and include them everywhere (DRY).
create deriveJobParams.groovy in vars folder with following code in shared library project.
def call() {
properties([
parameters([
booleanParam(defaultValue: false, name: 'BuildAll', description: ''),
[$class: 'ChoiceParameter', choiceType: 'PT_CHECKBOX',
description: 'Choose environment category.',
name: 'ENVIRONMENT',
script: [
$class: 'GroovyScript',
script: [sandbox: true, script: 'return ["QA", "DEV", "PROD"]']
]
]
])
])
}
In job Jenkinsfile, import the share library and call deriveJobParams()
#Library('my-library#branch or tag') _
// call deriveJobParams at beginning
deriveJobParams()
pipeline {
stages {
}
}

jenkinsfile page load event

Is there a way to dynamically load a dropdown on page load
def loadfolders() {
checkout scm
dir("environments/qa") {
sh "ls -d */ | cut -f1 -d'/' > list_of_files.txt"
sh 'cat list_of_files.txt'
liste = readFile 'list_of_files.txt'
echo "please click on the link here to chose the branch to build"
env.BRANCH_SCOPE = input message: 'Please choose the branch to build ', ok: 'Validate!',
parameters: [choice(name: 'BRANCH_NAME', choices: "${liste}", description: 'Branch to build?')]
}
}
The above code works but it works on click event . This code performs checkout, goes to the folder environments/qa which has n sub-folders
which gets populated in a drop-down where the users selects the input from drop-down.
Is it possible to just load the drop-down when I kick start the job ?
There is a way, with ActiveChoice Plugin.
You may need something like this in your Jenkinsfile:
properties([
parameters([
[$class: 'ChoiceParameter',
name: 'BRANCH_NAME',
choiceType: 'PT_SINGLE_SELECT',
description: 'Branch to build?',
filterable: false,
script:
[$class: 'GroovyScript',
script:
[classpath: [], sandbox: false, script: loadfolders()],
fallbackScript:
[classpath: [], sandbox: false, script: 'return "master"']
]
]
This allows you to run groovy scripts to populate your choices.
Debugging it is hell, as you need to approve each change to your script, and strange bugs occur, but in the end it works.

How to send referencedParameters value in Jenkins pipeline for CascadeChoiceParameter to ScriptlerScript

I'm declaring 2 parameters in properties section of a Jenkins pipeline:
a data center (can have multiple environment types)
an environment type
The data center is of type ChoiceParameter; the list is retrieved from a database; when the data center changes in the drop-down list, the environment types should populate accordingly, also from the database, through a ScriptlerScript.
The problem is that when changing selection on data center, nothing happens for environment types list, which is a CascadeChoiceParameter with referencedParameters: 'DataCenter'.
How should I link the referenced parameter to the scriptlet script I'm using - what do I have to send ?
The issue is with [name:'DataCenter', value: '$DataCenter'] for second parameter - the value is not sent to the ScriptletScript when first drop-down value changes.
If I define the 2 parameters from the Jenkins interface - so not through the DSL pipeline - under Configure section, everything works as expected.
It's not working for me to use something other than properties section - I've tried using activeChoiceParameter inside pipeline section, but I get an error 'Build parameters definitions cannot have blocks # line (...)', which is a known issue (see first example link below).
Examples I've used:
Jenkinsfile Active Choice Parameter
Active Choices Reactive Reference Parameter in jenkins pipeline
properties([
parameters([
[
$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'DataCenter',
script: [
$class: 'ScriptlerScript',
scriptlerScriptId:'getdatacenters.groovy',
parameters: [
[name:'StatusId', value:'']
]
]
],
[
$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'EnvironmentType',
script: [
$class: 'ScriptlerScript',
scriptlerScriptId:'getenvtypesbydatacenter.groovy',
referencedParameters: 'DataCenter',
parameters: [
[name:'DataCenter', value: '$DataCenter']
]
]
]
])
])
pipeline {
...
Expected result: Second drop-down list populates when data center changes
Actual result: Nothing happens when data center changes
Pipeline with params configured in UI - behaves ok (environment types loading on data center change):
One thing to keep in mind: Scriptlers are not secure, you should not use them: https://wiki.jenkins.io/display/JENKINS/Scriptler+Plugin !.
That being said, if you still want to go on and use Scriptler plugin and CascadeChoiceParameter, the code might look like this:
properties([
parameters([
[
$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'DataCenter',
randomName: 'datacenter-choice-parameter-102102304304506506',
script: [
$class: 'ScriptlerScript',
scriptlerScriptId:'getdatacenters.groovy',
fallbackScript: [ classpath: [], script: 'return ["N/A"]']
]
],
[
$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'EnvironmentType',
randomName: 'envtype-choice-parameter-101012020230303404',
referencedParameters: 'DataCenter',
script: [
$class: 'ScriptlerScript',
scriptlerScriptId:'getenvtypesbydatacenter.groovy',
fallbackScript: [ classpath: [], script: 'return ["N/A"]'],
]
]
])
])
The groovy code for getdatacenters.groovy for demo purposes is (but might be retrieved from a DB, as an alternative):
return["Dev","Prod"]
The groovy code for getenvtypesbydatacenter.groovy might look like this:
import groovy.sql.Sql
import jenkins.model.*
nodes = Jenkins.instance.globalNodeProperties
nodes.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class)
sql = Sql.newInstance("jdbc:sqlserver://SQLServerHere;connectionDataHere", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
envTypes = sql.rows("exec [DbHere].[schema].[GetEnvTypes] #DataCenter = $DataCenter").collect({ query -> query.EnvTypeName})
envTypes.add(0,'')
return envTypes
The most important thing to note here is that referencedParameters: 'DataCenter' was not inside the script block, but at the "root" level. If you need more parameters, you can separate them with comma.
Because DataCenter is a referenced parameter and automatically transmitted to the scriptler, $DataCenter variable from inside the SQL query will be mapped with its value. As a note, DataCenter should be added as parameter of the scriptler, in the UI Parameters section.
Credits for the solution go to CloudBees.

Resources