diff options
Diffstat (limited to 'buildbot/buildbot/steps/trigger.py')
-rw-r--r-- | buildbot/buildbot/steps/trigger.py | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/buildbot/buildbot/steps/trigger.py b/buildbot/buildbot/steps/trigger.py new file mode 100644 index 0000000..7903e70 --- /dev/null +++ b/buildbot/buildbot/steps/trigger.py @@ -0,0 +1,122 @@ +from buildbot.process.buildstep import LoggingBuildStep, SUCCESS, FAILURE, EXCEPTION +from buildbot.process.properties import Properties +from buildbot.scheduler import Triggerable +from twisted.internet import defer + +class Trigger(LoggingBuildStep): + """I trigger a scheduler.Triggerable, to use one or more Builders as if + they were a single buildstep (like a subroutine call). + """ + name = "trigger" + + flunkOnFailure = True + + def __init__(self, schedulerNames=[], updateSourceStamp=True, + waitForFinish=False, set_properties={}, **kwargs): + """ + Trigger the given schedulers when this step is executed. + + @param schedulerNames: A list of scheduler names that should be + triggered. Schedulers can be specified using + WithProperties, if desired. + + @param updateSourceStamp: If True (the default), I will try to give + the schedulers an absolute SourceStamp for + their builds, so that a HEAD build will use + the same revision even if more changes have + occurred since my build's update step was + run. If False, I will use the original + SourceStamp unmodified. + + @param waitForFinish: If False (the default), this step will finish + as soon as I've started the triggered + schedulers. If True, I will wait until all of + the triggered schedulers have finished their + builds. + + @param set_properties: A dictionary of properties to set for any + builds resulting from this trigger. To copy + existing properties, use WithProperties. These + properties will override properties set in the + Triggered scheduler's constructor. + + """ + assert schedulerNames, "You must specify a scheduler to trigger" + self.schedulerNames = schedulerNames + self.updateSourceStamp = updateSourceStamp + self.waitForFinish = waitForFinish + self.set_properties = set_properties + self.running = False + LoggingBuildStep.__init__(self, **kwargs) + self.addFactoryArguments(schedulerNames=schedulerNames, + updateSourceStamp=updateSourceStamp, + waitForFinish=waitForFinish, + set_properties=set_properties) + + def interrupt(self, reason): + # TODO: this doesn't actually do anything. + if self.running: + self.step_status.setText(["interrupted"]) + + def start(self): + properties = self.build.getProperties() + + # make a new properties object from a dict rendered by the old + # properties object + props_to_set = Properties() + props_to_set.update(properties.render(self.set_properties), "Trigger") + + self.running = True + ss = self.build.getSourceStamp() + if self.updateSourceStamp: + got = properties.getProperty('got_revision') + if got: + ss = ss.getAbsoluteSourceStamp(got) + + # (is there an easier way to find the BuildMaster?) + all_schedulers = self.build.builder.botmaster.parent.allSchedulers() + all_schedulers = dict([(sch.name, sch) for sch in all_schedulers]) + unknown_schedulers = [] + triggered_schedulers = [] + + # TODO: don't fire any schedulers if we discover an unknown one + dl = [] + for scheduler in self.schedulerNames: + scheduler = properties.render(scheduler) + if all_schedulers.has_key(scheduler): + sch = all_schedulers[scheduler] + if isinstance(sch, Triggerable): + dl.append(sch.trigger(ss, set_props=props_to_set)) + triggered_schedulers.append(scheduler) + else: + unknown_schedulers.append(scheduler) + else: + unknown_schedulers.append(scheduler) + + if unknown_schedulers: + self.step_status.setText(['no scheduler:'] + unknown_schedulers) + rc = FAILURE + else: + rc = SUCCESS + self.step_status.setText(['triggered'] + triggered_schedulers) + + if self.waitForFinish: + d = defer.DeferredList(dl, consumeErrors=1) + else: + d = defer.succeed([]) + + def cb(rclist): + rc = SUCCESS # (this rc is not the same variable as that above) + for was_cb, buildsetstatus in rclist: + # TODO: make this algo more configurable + if not was_cb: + rc = EXCEPTION + break + if buildsetstatus.getResults() == FAILURE: + rc = FAILURE + return self.finished(rc) + + def eb(why): + return self.finished(FAILURE) + + d.addCallbacks(cb, eb) |