Jenkins Job DSL Plugin: How to Modify Parameters on other jobs - jenkins

I want to create a job in Jenkins which modifies an existing parameter on another job.
I'm using the Job DSL Plugin. The code I'm using is:
job('jobname'){
using('jobname')
parameters {
choiceParam('PARAMETER1',['newValue1', 'newValue2'],'')
}
}
However, this only adds another parameter with the same name in the other job.
I'm trying the alternative to delete all parameters and start from scratch, but I haven't found the way to do that using Job DSL (not even with the Configure block).
Another alternative would be to define the other job completely and start from scratch, but that would make the job too complicated, specially if I want to apply this change to many jobs at a time.
¿Is there a way to edit or delete lines on the config.xml file using the Job DSL plugin?

Related

Jenkins allow comma separated values to be passed one by one to generate job dsl

I have a seed job which takes in a parameter say project and invokes a "Process Job DSL" to create the generated jobs.
However, I need to do the same for multiple projects.
Wondering, if there is a way in Jenkins for me to provide the list and it iterates through each of those choices and create its job.
I looked into Extended Choice Parameter but that too passes all the parameters at once.
I am interested in a way that it iterates through the loop.
I recently wrote a python client that wraps python-jenkins to do just this. The caller supplies the dsl file and the url to the jenkins server. The python client then calls the seed job, passing the dsl file as the argument. The seed job is just:
node {
stage('create-job') {
jobDsl failOnMissingPlugin: true, scriptText: params.jobDsl
}
}
To turn it into a loop, you would just iterate over the list of projects and invoke the client for each project.

Trigger Multibranch Job from another

I have a job in Jenkins and I need to trigger another one when it ends (if it ends right).
The second job is a multibranch, so I want to know if there's any way to, when triggering this job, pass the branch I want to. For example, if I start the first job in the branch develop, I need it to trigger the second one for the develop branch also.
Is there any way to achieve this?
Just think about the multibranch job being a folder containing the real jobs named after the available branches:
Using Pipeline Job
When using the pipeline build step you'll have to use something like:
build(job: 'JOB_NAME/BRANCH_NAME'). Of course you may use a variable to specify the branch name.
Using Freestyle Job
When triggering from a Freestyle job you most probably have to
Use the parameterized trigger plugin as the plain old downstream build plugin still has issues triggering pipeline jobs (at least the version we're using)
As job name use the same pattern as described above: JOB_NAME/BRANCH_NAME
Should be possible to use a job parameter to specify the branch name here. However I didn't give it a try, though.
Yes, you can call downstream job by adding post build step: Trigger/Call build on other projects(you may need to install "Parameterized Trigger Plugin"):
where in Parameters section you define vars for the downstream job associated with vars from current job.
Also multibranch_PARAM1 and *PARAM2 must be configured in the downstreamjob:
Sometimes you want to call one or more subordinate multibranch jobs and have them build all of their branches, not just one. A script can retrieve the branch names and build them.
Because the script calls the Jenkins API, it should be in a shared library to avoid sandbox restrictions. The script should clear non-serializable references before calling the build step.
Shared library script jenkins-lib/vars/mbhelper.groovy:
def callMultibranchJob(String name) {
def item = jenkins.model.Jenkins.get().getItemByFullName(name)
def jobNames = item.allJobs.collect {it.fullName}
item = null // CPS -- remove reference to non-serializable object
for (jobName in jobNames) {
build job: jobName
}
}
Pipeline:
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
library 'jenkins-lib'
mbhelper.callMultibranchJob 'multibranch-job-one'
mbhelper.callMultibranchJob 'multibranch-job-two'
}
}
}
}
}

Trigger Jenkins Job for every parameter

I have created a Global choice Parameter using Extensible Choice Parameter plugin.
I am using this parameter list in one of my parametrized jenkins job.
Is there a way in jenkins, where I can execute the job with each of the parameters in the Global choice Parameter list?
I have had a look on Build Flow job in jenkins, as suggested in this answer, but it seems it accepts hardcoded parameters only, and not dynamic.
I finally managed to resolve this using the following steps (with great help from this post) -
As my parameters list is dynamic in nature, it could be added or modified according to other jobs, we have managed it in a text file.
Next, We have used Extensible Choice Parameter plugin to display the parameters, using the groovy script -
def list = [];
File file = new File("D:/JenkinJob/parameterList.txt")
file.eachLine { line ->
list.add("$line")
}
return list
Now I want to call this jenkins job for each of the parameter.
For this, I have installed, BuildFlow plugin, and crated a new jenkins job of BuildFlow type -
Next, get the Extended Choice Parameter plugin, and configure it as follows -
Now in the flow step of this job, write this script, where "Feature" is the parameter, that is just created above, and within call to "build" parameter, pass in the name of job which we want to call for each parameter -
def features = params['Features'].split(',')
for (feature in features ) {
build("JobYouWantToCall", JobParameter: feature,)
}

How to perform a jenkins job save event through the Jenkins API in Groovy?

I'm using the ez-template to create a template and make other jobs, based on that template. Apparently, however, the template is only applied when you manually click either the save or apply buttons. I've used the following Jenkins Job DSL code to try to achieve this:
job("job_name") {
properties {
templateImplementationProperty {
exclusions(['ez-templates', 'job-params', 'disabled', 'description'])
syncAssignedLabel(true)
syncBuildTriggers(true)
syncDescription(false)
syncDisabled(false)
syncMatrixAxis(true)
syncOwnership(true)
syncScm(true)
syncSecurity(true)
templateJobName('template')
}
}
}
This creates the XML for that job just fine, but it is never applied/saved/submitted. How can I achieve this functionality through the Jenkins Job DSL API?
Job DSL uses two Jenkins API methods to create or update jobs, Jenkins#createProjectFromXML(...) (source) and AbstractItem#updateByXml(...) (source). The first method causes a ItemListener#onCreate(...) event and the second one causes a SavableListener#onChange(...) event.
The EZ Template plugin only reacts on ItemListener#onUpdated(...) (source).
If you are using Job DSL, you do not necessarily need the EZ Template plugin as Job DSL provides it's own template mechanism, see https://jenkinsci.github.io/job-dsl-plugin/#path/job-using.
job('job_name') {
using('template')
}
If you still want to use the EZ Template pluign, I suggest to file a feature request for the EZ Template plugin to also react on the two events mentioned above.
Links API docs:
http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html#createProjectFromXML(java.lang.String,%20java.io.InputStream)
http://javadoc.jenkins-ci.org/hudson/model/AbstractItem.html#updateByXml(javax.xml.transform.Source)
http://javadoc.jenkins-ci.org/hudson/model/listeners/ItemListener.html#onCreated(hudson.model.Item)
http://javadoc.jenkins-ci.org/hudson/model/listeners/SaveableListener.html#onChange(hudson.model.Saveable,%20hudson.XmlFile)
This behaviour is improved in ez-templates 1.3.0

How can I get the project details which has triggered the specific job?

I am triggering a job (child job) in 'Server B' from a job (parent job) in 'Server A' through a python script. I have 2-3 parent jobs. So I want to know which parent job is triggered the child job. How can I know which parent job triggered child job?
Can I pass the parent job name to child job name ?
Or
Can I get the parent name directly from child job ? (Environment variable / using python scripts)
Every build has an environment variable JOB_NAME. You can pass this as a string parameter to your child job.
Following description is provided in the /env-vars.html:
JOB_NAME
Name of the project of this build, such as "foo" or "foo/bar". (To strip off folder paths from a Bourne shell script, try: ${JOB_NAME##*/})
Passing the job name as an environment variable as mentioned by OltzU, may be the way to go, but that depends on how you are triggering the child job. If you are directly triggering the child job from the parent job using a post-build step, you can use something like the Parameterized Remote Build plugin to pass the Job name along. If you are using a script in the parent job to fire off the child job, you can string the Job name on as a parameter.
If you can't pass the triggering job as a parameter, you can programmatically get the build trigger(s) using Groovy. Groovy is really the only language that fully integrates with the Jenkins api, so if you want to use another language (python), you are stuck with using the rest api or jenkins cli, which are both limited in what they can give you (e.g. neither can give you the triggering job to my knowledge).
If you want to use groovy to get the trigger job, you will need the Groovy Plugin, which you will run as build step in your child job. Here's a snippet of code to get the chain of upstream jobs that triggered your build. You may need to modify the code depending on the type of trigger that is used.
def getUpstreamProjectTriggers(causes) {
def upstreamCauses = []
for (cause in causes) {
if (cause.class.toString().contains("UpstreamCause")) {
upstreamCauses.add(cause.getUpstreamProject())
}
}
return upstreamCauses
}
getUpstreamProjectTriggers(build.getCauses())
From here, if you want to use the triggering job in, say, a python script, you would need to use groovy to set the triggering job in an environment variable. This SO thread gives more info on that, or you can skip to my answer in that thread to see how I do it.
In the child Jenkinsfile this Groovy code will get the name of the triggering job:
String getTriggeringProjectName() {
if (currentBuild.upstreamBuilds) {
return currentBuild.upstreamBuilds[0].projectName
} else {
return ""
}
}
currentBuild.upstreamBuilds is a list of RunWrapper objects
You could use an additional parameter for your child job.

Resources