Is there a way to get the names of all branches that the scan of a multibranch pipeline job has gathered?
I would like to set up a nightly build with dependencies on existing build jobs and therefore need to check if the multibranch jobs contain some certain branches. An other way would be to check for an existing job.
I found a way by using the Jenkins API.
In case anyone else is having this question: here is my groovy solution:
(Critics and edits welcome)
import java.util.ArrayList
import hudson.model.*;
def ArrayList<String> call(String pipelineName) {
def hi = hudson.model.Hudson.instance;
def item = hi.getItemByFullName(pipelineName);
def jobs = item.getAllJobs();
def arr = new ArrayList<String>();
Iterator<?> iterator = jobs.iterator();
while (iterator.hasNext()) {
def job = iterator.next();
arr.add(pipelineName + "/" + job.name);
}
return arr;
}
Related
I'm attempting to set up a script to kill/abort all Jenkins jobs with a certain name in them. I've had trouble finding documentation on Jenkins classes and what's contained in them.
I know there are plugins available, but I've been directed not to use them. Otherwise, I've referred to a few semi-related questions here (How to stop an unstoppable zombie job on Jenkins without restarting the server?), (Cancel queued builds and aborting executing builds using Groovy for Jenkins), and I attempted to rework some of the code from those, however it doesn't quite result in killed jobs:
import hudson.model.*
def jobList = Jenkins.instance.queue
jobList.items.findAll { it.task.name.contains('searchTerm') }.each { jobList.kill(it.task) }
I've also tried the following:
def jobname = ""
def buildnum = 85
def job = Jenkins.instance.getItemByFullName(jobname)
for (build in job.builds) {
if (buildnum == build.getNumber().toInteger()){
if (build.isBuilding()){
build.doStop();
build.doKill();
}
}
}
Instead of hard-killing jobs, the first script does nothing, while the second throws a NullPointerException:
java.lang.NullPointerException: Cannot get property 'builds' on null object
I managed to get it working; my second example wasn't working because I brainfarted and the job I was testing it on had no builds. :(
def searchTerm = ""
def matchedJobs = Jenkins.instance.items.findAll { job ->
job.name.contains(searchTerm)
def desiredState = "stop"
if (desiredState.equals("stop")) {
println "Stopping all current builds ${job.name}"
for (build in job.builds) {
if (build.isBuilding()){
build.doStop();
println build.name + " successfully stopped!"
}
}
}
In a Jenkins job, I want to trigger another Jenkins job from a Groovy script :
other_job.scheduleBuild();
But other_job is not launched on the same node than the parent job. How can I modify my script to launch other_job on the same node than the parent job ?
I used to do that with the "Trigger/call builds on other project" and "NodeLabel Parameter" plugins but I would like now to do that inside a script.
Firstly, check Restrict where this project can be run option in 'other_job' configuration - you must specify the same node name there.
Then, this should work:
import hudson.model.*
def job = Hudson.instance.getJob('other_job')
job.scheduleBuild();
If you don't want to use this option in your 'other_job', then you can use NodeLabel Parameter Plugin (which you already used) and pass the NodeLabel parameter to downstream job.
In this case, see example from Groovy plugin page how to start another job with parameters (you need to use NodeParameterValue instead of StringParameterValue):
def job = Hudson.instance.getJob('MyJobName')
def anotherBuild
try {
def params = [
new StringParameterValue('FOO', foo),
]
def future = job.scheduleBuild2(0, new Cause.UpstreamCause(build), new ParametersAction(params))
println "Waiting for the completion of " + HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName)
anotherBuild = future.get()
} catch (CancellationException x) {
throw new AbortException("${job.fullDisplayName} aborted.")
}
println HyperlinkNote.encodeTo('/' + anotherBuild.url, anotherBuild.fullDisplayName) + " completed. Result was " + anotherBuild.result
If it's not working, probably the issue is with node restrictions (e.g., there is only one executor for the node).
NOTE: I prefer to use Jenkins pipelines for job configurations. It allows you to store your build configs in Jenkinsfiles which can be loaded from repository (e.g., from GitLab). See example of triggering job with NodeParameterValue.
Based on the answer of biruk1230, here is a full solution :
import hudson.model.*;
import jenkins.model.Jenkins
import java.util.concurrent.*
import hudson.AbortException
import org.jvnet.jenkins.plugins.nodelabelparameter.*
def currentBuild = Thread.currentThread().executable
current_node = currentBuild.getBuiltOn().getNodeName()
def j = Hudson.instance.getJob('MyJobName')
try {
def params = [
new NodeParameterValue('node', current_node, current_node),
]
def future = j.scheduleBuild2(0, new Cause.UpstreamCause(build), new ParametersAction(params))
println "Waiting for the completion of " + j.getName()
anotherBuild = future.get()
} catch (CancellationException x) {
throw new AbortException("aborted.")
}
I am using the github-organization plugin to manage jenkins jobs from github but I discovered that Jenkins API does not report these builds.
In fact the API list the entire organization as a single job.
How can I build a specific repository and branch using the API?
To be clear, I am looking for some groovy code to add inside the Jenkinsfile
#!groovy
stage 'test-downstream'
node {
def job = build job: 'some-job'
}
Now, the problem is that Jenkins is seeing the entire organization as a single job!
If I use Jenkins API to retrieve the jobs, it will return only the organization, and not all the repositories and jobs inside it.
I suspect that's because the way this plugin was implemented and I suppose that I need to give some extra parameters in order to specify which repository and branch I want to build inside the organization.... building an organization does not make much sense.
The question is vague, but I am guessing “API” in this context means the REST API to trigger builds. You can use for example
curl -X POST -u user:apitoken http://jenkins/job/yourorg/job/yourrepo/job/master/build
The following code trigger job via System Groovy build step. Please note that system groovy always run on master so passing info from previous build steps might be tricky.
import jenkins.model.*
import hudson.model.*
import java.util.concurrent.*
def run_job(job_name) {
def currentBuild = Thread.currentThread().executable
def jenkins = jenkins.model.Jenkins.getInstance();
def job = jenkins.getItemByFullName(job_name);
if (job == null)
throw new hudson.AbortException("Cannot find job:" + job_name);
def params =[
new StringParameterValue('PARAMETER1', "invoke 1 param1"),
new StringParameterValue('PARAMETER2', ",invoke 1 param2")
]
def paramsAction = new ParametersAction(params)
def cause = new hudson.model.Cause.UpstreamCause(currentBuild)
def causeAction = new hudson.model.CauseAction(cause)
def future_build = job.scheduleBuild2(0,causeAction,paramsAction);
def running_build = future_build.waitForStart()
return running_build
}
run_job("runner1")
I have a jenkins job A to select any choices from parameters while building job , the same parameters values that i have selected on job A should be picked by job B automatically every time when i try to build job B . Where job B should not be downstream job of job A.
My workaround: I tried to copy the parameters that i select on job A to a file .
On job B ,i was unable to find the option in jenkins, to select the variable value to be picked up from a file in parameters section.
Any suggestions and different approaches will be greatly appreciated.
You can do this using a System Groovy script. You find the most recent job A build, and copy the parameter values into Job B.
import hudson.model.*
def hif = Hudson.instance
//Get build variables for this build
def buildMap = build.getBuildVariables()
//get most recent build of project A
def a = hif.getItems(hudson.model.Project).find {it.displayName.toUpperCase()=='PROJECT A'}.getBuilds().first()
//Add parameter to the build variables for this build
buildMap['MYPARAM']=a.buildVariableResolver.resolve('MYPARAM')
println(buildMap['MYPARAM'])
//Assign the new parameters back to job B
setBuildParameters(buildMap)
def setBuildParameters(map) {
def npl = new ArrayList<StringParameterValue>()
for (e in map) {
npl.add(new StringParameterValue(e.key.toString(), e.value.toString()))
}
def newPa = null
def oldPa = build.getAction(ParametersAction.class)
if (oldPa != null) {
build.actions.remove(oldPa)
newPa = oldPa.createUpdated(npl)
} else {
newPa = new ParametersAction(npl)
}
build.actions.add(newPa)
}
I try to launch a job from a parametrized trigger and I would compute the name from a given variable.
Is it possible to set in field :
Build Triggers Projects to build
a value like this
${RELEASE}-MAIN-${PROJECT}-LOAD_START
?
Unfortunately, this isn't possible with the Build Triggers. I looked for a solution for this "higher order build job" that would allow you to create a dynamic build name with a one of the parameterized build plugins, but I couldn't find one.
However, using the Groovy Postbuild Plugin, you can do a lot of powerful things. Below is a script that can be modified to do what you want. In particular, notice that it gets environmental variables using build.buildVariables.get("MY_ENV_VAR"). The environmental variable TARGET_BUILD_JOB specifies the name of the build job to build. In your case, you would want to build TARGET_BUILD_JOB using these two environmental variables:
build.buildVariables.get("RELEASE")
build.buildVariables.get("PROJECT")
The script is commented so that if you're not familiar with Groovy, which is based off Java, it should hopefully make sense!
import hudson.model.*
import hudson.model.queue.*
import hudson.model.labels.*
import org.jvnet.jenkins.plugins.nodelabelparameter.*
def failBuild(msg)
{
throw new RuntimeException("[GROOVY] User message, exiting with error: " + msg)
}
// Get the current build job
def thr = Thread.currentThread()
def build = thr?.executable
// Get the parameters for the current build job
// For ?:, see "Elvis Operator" (http://groovy.codehaus.org/Operators#Operators-ElvisOperator)
def currentParameters = build.getAction(ParametersAction.class)?.getParameters() ?:
failBuild("There are no parameters to pass down.")
def nodeName = build.getBuiltOnStr()
def newParameters = new ArrayList(currentParameters); newParameters << new NodeParameterValue("param_NODE",
"Target node -- the node of the previous job", nodeName)
// Retrieve information about the target build job
def targetJobName = build.buildVariables.get("TARGET_BUILD_JOB")
def targetJobObject = Hudson.instance.getItem(targetJobName) ?:
failBuild("Could not find a build job with the name $targetJobName. (Are you sure the spelling is correct?)")
println("$targetJobObject, $targetJobName")
def buildNumber = targetJobObject.getNextBuildNumber()
// Add information about downstream job to log
def jobUrl = targetJobObject.getAbsoluteUrl()
println("Starting downstream job $targetJobName ($jobUrl)" + "\n")
println("======= DOWNSTREAM PARAMETERS =======")
println("$newParameters")
// Start the downstream build job if this build job was successful
boolean targetBuildQueued = targetJobObject.scheduleBuild(5,
new Cause.UpstreamCause(build),
new ParametersAction(newParameters)
);
if (targetBuildQueued)
{
println("Build started successfully")
println("Console (wait a few seconds before clicking): $jobUrl/$buildNumber/console")
}
else
failBuild("Could not start target build job")