How do I dynamically trigger downstream builds in jenkins?

22,832

Solution 1

def job = hudson.model.Hudson.instance.getJob("job")
def params = new StringParameterValue('PARAMTEST', "somestring")  
def paramsAction = new ParametersAction(params) 
def cause = new hudson.model.Cause.UpstreamCause(currentBuild)
def causeAction = new hudson.model.CauseAction(cause) 
hudson.model.Hudson.instance.queue.schedule(job, 0, causeAction, paramsAction) 

This is what finally worked for me.

Solution 2

NOTE: The Pipeline Plugin should render this question moot, but I haven't had a chance to update our infrastructure.

To start a downstream job without parameters:

job = manager.hudson.getItem(name)
cause = new hudson.model.Cause.UpstreamCause(manager.build)
causeAction = new hudson.model.CauseAction(cause)
manager.hudson.queue.schedule(job, 0, causeAction)

To start a downstream job with parameters, you have to add a ParametersAction. Suppose Job1 has parameters A and C which default to "B" and "D" respectively. I.e.:

A == "B"
C == "D"

Suppose Job2 has the same A and B parameters, but also takes parameter E which defaults to "F". The following post build script in Job1 will copy its A and C parameters and set parameter E to the concatenation of A's and C's values:

params = []
val = ''
manager.build.properties.actions.each {
    if (it instanceof hudson.model.ParametersAction) {
        it.parameters.each {
            value = it.createVariableResolver(manager.build).resolve(it.name)
            params += it
            val += value
        }
    }
}

params += new hudson.model.StringParameterValue('E', val)
paramsAction = new hudson.model.ParametersAction(params)

jobName = 'Job2'
job = manager.hudson.getItem(jobName)
cause = new hudson.model.Cause.UpstreamCause(manager.build)
causeAction = new hudson.model.CauseAction(cause)
def waitingItem = manager.hudson.queue.schedule(job, 0, causeAction, paramsAction)
def childFuture = waitingItem.getFuture()
def childBuild = childFuture.get()

hudson.plugins.parameterizedtrigger.BuildInfoExporterAction.addBuildInfoExporterAction(
    manager.build, childProjectName, childBuild.number, childBuild.result
)

You have to add $JENKINS_HOME/plugins/parameterized-trigger/WEB-INF/classes to the Groovy Postbuild plugin's Additional groovy classpath.

Solution 3

Execute this Groovy script

import hudson.model.*
import jenkins.model.*

def build = Thread.currentThread().executable

def jobPattern = "PUTHEREYOURJOBNAME"     
def matchedJobs = Jenkins.instance.items.findAll { job ->
    job.name =~ /$jobPattern/
}
matchedJobs.each { job ->
    println "Scheduling job name is: ${job.name}"
    job.scheduleBuild(1, new Cause.UpstreamCause(build), new ParametersAction([ new StringParameterValue("PROPERTY1", "PROPERTY1VALUE"),new StringParameterValue("PROPERTY2", "PROPERTY2VALUE")]))
}

If you don't need to pass in properties from one build to the other just take the ParametersAction out.

The build you scheduled will have the same "cause" as your initial build. That's a nice way to pass in the "Changes". If you don't need this just do not use new Cause.UpstreamCause(build) in the function call

Solution 4

This worked for me using "Execute system groovy script"

import hudson.model.*

def currentBuild = Thread.currentThread().executable

def job = hudson.model.Hudson.instance.getJob("jobname")
def params = new StringParameterValue('paramname', "somestring")  
def paramsAction = new ParametersAction(params) 
def cause = new hudson.model.Cause.UpstreamCause(currentBuild)
def causeAction = new hudson.model.CauseAction(cause) 
hudson.model.Hudson.instance.queue.schedule(job, 0, causeAction, paramsAction)

Solution 5

Since you are already starting the downstream jobs dynamically, how about you wait until they done and copy the test result files (I would archive them on the downstream jobs and then just download the 'build' artifacts) to the parent workspace. You might need to aggregate the files manually, depending if the Test plugin can work with several test result pages. In the post build step of the parent jobs configure the appropriate test plugin.

Share:
22,832
willkil
Author by

willkil

Updated on July 05, 2022

Comments

  • willkil
    willkil almost 2 years

    We want to dynamically trigger integration tests in different downstream builds in jenkins. We have a parametrized integration test project that takes a test name as a parameter. We dynamically determine our test names from the git repo.

    We have a parent project that uses jenkins-cli to start a build of the integration project for each test found in the source code. The parent project and integration project are related via matching fingerprints.

    The problem with this approach is that the aggregate test results doesn't work. I think the problem is that the "downstream" integration tests are started via jenkins-cli, so jenkins doesn't realize they are downstream.

    I've looked at many jenkins plugins to try to get this working. The Join and Parameterized Trigger plugins don't help because they expect a static list of projects to build. The parameter factories available for Parameterized Trigger won't work either because there's no factory to create an arbitrary list of parameters. The Log Trigger plugin won't work.

    The Groovy Postbuild Plugin looks like it should work, but I couldn't figure out how to trigger a build from it.

  • willkil
    willkil over 12 years
    That's not what I was hoping for, but that sounds like it will work. I'll leave this open for a bit in hopes of a simpler solution.
  • willkil
    willkil over 11 years
    I finally got a chance to try this out, 9 months later. Your code doesn't work, but it got me started. The script has to say manager.hudson instead of hudson. The Join Plugin then gives an error saying a CauseAction is required, so I used manager.hudson.queue.schedule(job, 0 causeAction). Thanks for giving me the spark I needed.
  • willkil
    willkil about 10 years
    What is currentBuild?
  • willkil
    willkil about 10 years
    Nevermind. I see "build - the current build (see hudson.model.AbstractBuild)" on the Groovy Postbuild Plugin page. I don't think that existed when I asked the question or wrote my answer.
  • Christian Goetze
    Christian Goetze almost 9 years
    When I do this, I would like to see the build appear as a downstream build of the current build. It correctly shows the launching build as an upstream build of the launched build, but not the other way - any way achieve that?
  • Ian Marcinkowski
    Ian Marcinkowski about 8 years
    @willkil I had that exact same question, so I created and answered the following Question: stackoverflow.com/questions/36581015/…
  • Ajith Antony
    Ajith Antony about 8 years
    @ChristianGoetze Did you ever figure this out? How to link the downstream build from the upstream build? The way that the regular "trigger other projects" build step does?
  • Christian Goetze
    Christian Goetze about 8 years
    Sorry, no. I ended up going on a completely different tack in the end, writing a new plugin based on the Multiproject plugin which includes the dynamic launch logic. I hope to be able to someday contribute it back..
  • willkil
    willkil over 7 years
    @Ajith I updated my answer to add the link from the upstream build to the downstream build.
  • gaoithe
    gaoithe over 6 years
    Works for me also. Thanks. Except remove hudson.model. from each method call.
  • snowindy
    snowindy over 2 years
    If you do this from script console, there is no current build. In this case it's good to use def cause = new hudson.triggers.TimerTrigger.TimerTriggerCause()