Jenkins Job DSL: unknown return statement - jenkins

some days ago I bumped into a code snippet used to override the default configuration of the Jenkins plugin "GitHub SCM Source" (unknown author):
Closure configOverride(String repo, int id, String cred) {
return {
it / sources / 'data' / 'jenkins.branch.BranchSource' << {
source(class: 'org.jenkinsci.plugins.github_branch_source.GitHubSCMSource') {
id(id)
scanCredentialsId(cred)
checkoutCredentialsId('SAME')
repoOwner('owner')
repository(repo)
includes('*')
buildOriginBranch('true')
buildOriginBranchWithPR('true')
buildOriginPRMerge('false')
buildOriginPRHead('false')
buildForkPRMerge('true')
buildForkPRHead('false')
}
}
}
}
All it's good except that I can't understand the following line:
it / sources / 'data' / 'jenkins.branch.BranchSource' << { ... }
I tried to find some explanation about the use of '/' in groovy but no luck. Maybe I don't know what exactly to search.
Could someone help me please with a link to the docs or a short explanation.

This is overloading of
operators
Groovy allows you to overload the various operators so that they can be used with your own classes. Consider this simple class:
class Bucket {
int size
Bucket(int size) { this.size = size }
Bucket plus(Bucket other) {
return new Bucket(this.size + other.size)
}
}
Just by implementing the plus() method, the Bucket class can now be used with the + operator like so:
def b1 = new Bucket(4)
def b2 = new Bucket(11)
assert (b1 + b2).size == 15
For / one would override T div(T x)

This code snippet is used in Jenkins DSL for the "multibranchPipelineJob". The closure configOverride is used to generate an XML object which replace the default configuration in config.xml on the following path "sources/data/jenkins.branch.BranchSource".

Related

How to set ForkPullRequestDiscoveryTrait trustId to Collaborators - Jenkins

newbie here.
In Jenkins, I need to set "Discover pull requests from forks" setting as a code with Trust set to Collaborators. What trustId I should use?
configure {
def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits
traits << 'org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait' {
strategyId(1)
}
All I managed to find is this. But I can't see collaborators setting anywhere.
trustID('1')
// Values
// 0 : Everyone
// 1 : Forks in the same account
// 2 : Nobody
Wanted option can be found and set using GUI.
Edit:
I've found something like this. Running build like this throws: groovy.lang.MissingPropertyException: No such property: TrustContributors for class: groovy.lang.Binding
def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits
traits << 'org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait' {
strategyId(1)
trust(class: 'org.jenkinsci.plugins.github_branch_source.ForkPullRequestDiscoveryTrait$TrustContributors')
} ```
I finally got it to work. Here's what it looks like.
configure {
def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits
traits << 'org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait' {
strategyId (1)
extension(class: 'org.jenkinsci.plugins.github_branch_source.ForkPullRequestDiscoveryTrait') {
trust(TrustContributors)
}
}
}

How to Set multiple credentials using withcredentials in jenkins pipeline groovy file

I need to set two or more credentials to a job, my plan is to use it separately like below, so that it can be used in multiple jobs
static void _artifactoryCredentialBinding(Job job) {
job.with {
wrappers {
credentialsBinding {
usernamePassword('USERNAME', 'PASSWORD', 'xxxxx')
}
}
}
}
static void _jasyptCredentialBinding(Job job) {
return job.with {
wrappers {
credentialsBinding {
usernamePassword('', 'PASSWORD', 'jasypt-credentials')
}
}
}
}
When I do this the first credential is getting over ridden by the second credential.
I will be calling these two methods as a helper method in where ever necessary in my groovy file.
I would require to add multiple credentials in few jobs and only one credential in a job.
Adding the credentials under one wrapper will work - multiple-credentials, but I will not be able to reuse if I add multiple under the same.
I tried returning the Job in the above methods and used the same methods to set the creds but getting the error while building -
ERROR: (CredentialBindingUtil.groovy, line 28) No signature of method: xxxx.CredentialBindingUtil$__pfJasyptCredentialBinding_closure3.wrappers() is applicable for argument types: (xxx.CredentialBindingUtil$__pfJasyptCredentialBinding_closure3$_closure9) values: [xxxx.CredentialBindingUtil$__pfJasyptCredentialBinding_closure3$_closure9#11b4d391]
[Office365connector] No webhooks to notify
How do I make the credentials to be appended with the existing ones ?
As discussed in the comments, it's possible to achieve this through the Configure Block.
static void _artifactoryCredentialBinding(def job) {
job.with {
configure { node ->
node / 'buildWrappers' / 'org.jenkinsci.plugins.credentialsbinding.impl.SecretBuildWrapper' / 'bindings' << 'org.jenkinsci.plugins.credentialsbinding.impl.UsernamePasswordMultiBinding' {
usernameVariable 'some-credential-id'
credentialsId PASS1
passwordVariable USER1
}
}
}
}
static void _jasyptCredentialBinding(def job) {
job.with {
configure { node ->
node / 'buildWrappers' / 'org.jenkinsci.plugins.credentialsbinding.impl.SecretBuildWrapper' / 'bindings' << 'org.jenkinsci.plugins.credentialsbinding.impl.UsernamePasswordMultiBinding' {
usernameVariable 'some-credential-id'
credentialsId PASS2
passwordVariable USER2
}
}
}
}
def a_job = job('a-temporaryjob')
_artifactoryCredentialBinding(a_job)
_jasyptCredentialBinding(a_job)
To understand how the Configure Block works I highly suggest reading the wiki page and an older blog post which explains step by step how to configure an unsupported plugin.

extract parameters from a jenkins previous build

I am working on Jenkins version 2.32.1 pipeline. I want to extract the parameters that were chosen in the previous build of my job.
In our previous Jenkins instance ( 1.627 ) we were using jenkins.model.Jenkins.instance.getItem(job).lastBuild.getBuildVariables().get(param);
For some reason this is not working in this version (I also tried disabling the sandbox).
Any pointers on how to accomplish it?
Simplified version of the previous script:
def build = Jenkins.get().getItems(org.jenkinsci.plugins.workflow.job.WorkflowJob).find {it.displayName == 'YOUR_JOB_NAME_HERE'}?.getLastBuild()
build.actions.find{ it instanceof ParametersAction }?.parameters.each {echo "${it.name}=${it.value}"}
Actually a little bit shorter version for those who want to get the params for the current build from the previous run and is working on new 2+ Jenkins versions.
To get 1 particular parameter:
def cls = currentBuild.getPreviousBuild().getRawBuild().actions.find{ it instanceof ParametersAction }?.parameters.find{it.name == 'cls'}?.value
Get all params respectfully:
def cls = currentBuild.getPreviousBuild().getRawBuild().actions.find{ it instanceof ParametersAction }?.parameters
Something like this might work, based on https://stackoverflow.com/a/19564602/3920342:
def h = hudson.model.Hudson.instance
def r = null
h.getItems(org.jenkinsci.plugins.workflow.job.WorkflowJob).each {project ->
if (project.displayName.equals('YOUR_JOB_NAME')) {
r = project
}
}
r.getBuilds().findAll { b -> // here we loop over all past builds, apply some filter if necessary
def p = b?.actions.find{ it instanceof ParametersAction }?.parameters
p.each {
echo "parameter ${it.name}: ${it.value}"
}
}
For those who are not able to access getActions() due to admin permissions i.e. facing the following error:
Scripts not permitted to use method hudson.model.Actionable getActions
They can copy the parameter variables to the env and get them using build.previousBuild.buildVariables
stage('Prepare environment') {
steps {
script {
env.MY_PARAM_COPY = "${MY_PARAM}"
}
}
}
println("MY_PARAM in previous build: ${currentBuild.previousBuild.buildVariables["MY_PARAM_COPY"]}")
That's how I made it works, answer from #dan.goriaynov and #jherb caused some CPS closure issues for me.
(the gist of the code is to allow only greater TAG number than the previous one to be deployed)
stage('Validate build number') {
def previous_build = currentBuild.getPreviousBuild().getRawBuild();
def PREVIOUS_TAG = '';
for (int i = 0; i < previous_build.allActions.size(); i++) {
if (previous_build.allActions[i] in hudson.model.ParametersAction) {
PREVIOUS_TAG = previous_build.allActions[i].getParameter("TAG").value
}
}
if (PREVIOUS_TAG.toInteger() > TAG.toInteger()) {
echo PREVIOUS_TAG
error('TAG number needs to be greater than the previous one')
}
}

jenkins DSL dynamic parameters

This is my configure block to generate dynamic parameters. But it is not working. Can someone help?
configure { project ->
def paramDefs = project / 'properties' / 'hudson.model.ParametersDefinitionProperty' / 'parameterDefinitions'
paramDefs << 'com.seitenbau.jenkins.plugins.dynamicparameter.scriptler.ScriptlerStringParameterDefinition' {
name('BUILD_VERSION')
description('Overall Build version')
__remote(false)
__scriptlerScriptId('**/build_versions.groovy')
}
}
Short answer: Don't use the plugin anymore, just use normal groovy code in combination with the default jenkins parameters
Full answer: Please have a look at this answer https://stackoverflow.com/a/42230455/4486169
The answer to this question didn't help so here is an example with StringParameterDefinition (just replace with sriptler.ScriptlerStringParameterDefinition if you're using the Scriptler alternative), you can find node names by opening a configured job xml:
configure { root ->
def paramDefs = root / 'properties' / 'hudson.model.ParametersDefinitionProperty' / 'parameterDefinitions'
paramDefs << 'com.seitenbau.jenkins.plugins.dynamicparameter.StringParameterDefinition' {
delegate.createNode('name', 'FirstParam')
delegate.createNode('__script', 'someScriptString')
__localBaseDirectory(serialization: 'custom') {
'hudson.FilePath' {
'default' {
delegate.createNode('remote', "${JENKINS_HOME}/dynamic_parameter/classpath")
}
delegate.createNode('boolean', true)
}
}
delegate.createNode('__remoteBaseDirectory', 'dynamic_parameter_classpath')
delegate.createNode('__classPath', '')
}
paramDefs << 'com.seitenbau.jenkins.plugins.dynamicparameter.StringParameterDefinition' {
delegate.createNode('name', 'SecondParam')
delegate.createNode('__script', 'someScriptString')
__localBaseDirectory(serialization: 'custom') {
'hudson.FilePath' {
'default' {
delegate.createNode('remote', "${JENKINS_HOME}/dynamic_parameter/classpath")
}
delegate.createNode('boolean', true)
}
}
delegate.createNode('__remoteBaseDirectory', 'dynamic_parameter_classpath')
delegate.createNode('__classPath', '')
}
...
}

Jenkins Pipeline Execute Multiple FreeStyleProjects in Parallel [duplicate]

The script is not iterating through all the values of the 'modules' array.
class Module {
public String name = '';
public Boolean isCustom = false;
public Module(String name, Boolean custom){
this.name = name;
this.isCustom = custom;
}
}
//creates array from the ext_module env var
modules = [];
EXT_MODULE.split(',').each {
modules.add(new Module(it, false));
}
println modules;
modules.each {
println "MODULE NAME ::::: ${it.name}"
if(it.isCustom)
{
println "install custom";
} else {
println "install non custom";
}
};
This is the result of the run. The array shows 4 elements, but the code inside the .each black only executes once.
Running: Print Message
[Module#71f09325, Module#e1ddb41, Module#7069a674, Module#1f68f952]
Running: Print Message
MODULE NAME ::::: puppetlabs-ntp
Running: Print Message
install non custom
Running: End of Workflow
Finished: SUCCESS
The messages "Running: Print Message" and "Running: End of Workflow" indicate that you are using the new workflow plugin: https://wiki.jenkins-ci.org/display/JENKINS/Workflow+Plugin. This plugin currently has a bug causing at least some Groovy iterations involving a closure to be aborted after one iteration: https://issues.jenkins-ci.org/browse/JENKINS-26481
The workaround is to simply use an old school for loop (code below).
Also, NonCPS is another workaround.
There is an open issue for this matter. See here: https://issues.jenkins-ci.org/browse/JENKINS-26481
Update, Oct 24th, 2016
/**
* Dumps environment varibles to the log, using an old school for loop.
*/
import com.cloudbees.groovy.cps.NonCPS
def version = '1.0'
#NonCPS
def dumpEnvVars() {
def str = "Dumping build environment variables...\n"
for (Map.Entry<String, String> entry : currentBuild.build().environment) {
str += " ${entry.key} = ${entry.value}\n"
}
echo str
}
return this;
As of yesterday, the new Pipeline plugin was delivered in version 2.0 and correct this problem.
.each closures now work, but .collect still only iterate once.

Resources