Package buildbot :: Package steps :: Module trigger
[frames] | no frames]

Source Code for Module buildbot.steps.trigger

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16  from buildbot.process.buildstep import LoggingBuildStep, SUCCESS, FAILURE, EXCEPTION 
 17  from buildbot.process.properties import Properties 
 18  from buildbot.schedulers.triggerable import Triggerable 
 19  from twisted.python import log 
 20  from twisted.internet import defer 
 21   
22 -class Trigger(LoggingBuildStep):
23 """I trigger a scheduler.Triggerable, to use one or more Builders as if 24 they were a single buildstep (like a subroutine call). 25 """ 26 name = "trigger" 27 28 flunkOnFailure = True 29
30 - def __init__(self, schedulerNames=[], updateSourceStamp=True, 31 waitForFinish=False, set_properties={}, copy_properties=[], **kwargs):
32 """ 33 Trigger the given schedulers when this step is executed. 34 35 @param schedulerNames: A list of scheduler names that should be 36 triggered. Schedulers can be specified using 37 WithProperties, if desired. 38 39 @param updateSourceStamp: If True (the default), I will try to give 40 the schedulers an absolute SourceStamp for 41 their builds, so that a HEAD build will use 42 the same revision even if more changes have 43 occurred since my build's update step was 44 run. If False, I will use the original 45 SourceStamp unmodified. 46 47 @param waitForFinish: If False (the default), this step will finish 48 as soon as I've started the triggered 49 schedulers. If True, I will wait until all of 50 the triggered schedulers have finished their 51 builds. 52 53 @param set_properties: A dictionary of properties to set for any 54 builds resulting from this trigger. These 55 properties will override properties set in the 56 Triggered scheduler's constructor. 57 58 @param copy_properties: a list of property names to copy verbatim 59 into any builds resulting from this trigger. 60 61 """ 62 assert schedulerNames, "You must specify a scheduler to trigger" 63 self.schedulerNames = schedulerNames 64 self.updateSourceStamp = updateSourceStamp 65 self.waitForFinish = waitForFinish 66 self.set_properties = set_properties 67 self.copy_properties = copy_properties 68 self.running = False 69 self.ended = False 70 LoggingBuildStep.__init__(self, **kwargs) 71 self.addFactoryArguments(schedulerNames=schedulerNames, 72 updateSourceStamp=updateSourceStamp, 73 waitForFinish=waitForFinish, 74 set_properties=set_properties, 75 copy_properties=copy_properties)
76
77 - def interrupt(self, reason):
78 if self.running: 79 self.step_status.setText(["interrupted"]) 80 return self.end(EXCEPTION)
81
82 - def end(self, result):
83 if not self.ended: 84 self.ended = True 85 return self.finished(result)
86
87 - def start(self):
88 properties = self.build.getProperties() 89 90 # make a new properties object from a dict rendered by the old 91 # properties object 92 props_to_set = Properties() 93 props_to_set.update(properties.render(self.set_properties), "Trigger") 94 for p in self.copy_properties: 95 if p not in properties: 96 raise RuntimeError("copy_property '%s' is not set in the triggering build" % p) 97 props_to_set.setProperty(p, properties[p], 98 "%s (in triggering build)" % properties.getPropertySource(p)) 99 100 self.running = True 101 ss = self.build.getSourceStamp() 102 if self.updateSourceStamp: 103 got = properties.getProperty('got_revision') 104 if got: 105 ss = ss.getAbsoluteSourceStamp(got) 106 107 # (is there an easier way to find the BuildMaster?) 108 all_schedulers = self.build.builder.botmaster.parent.allSchedulers() 109 all_schedulers = dict([(sch.name, sch) for sch in all_schedulers]) 110 unknown_schedulers = [] 111 triggered_schedulers = [] 112 113 # TODO: don't fire any schedulers if we discover an unknown one 114 for scheduler in self.schedulerNames: 115 scheduler = properties.render(scheduler) 116 if all_schedulers.has_key(scheduler): 117 sch = all_schedulers[scheduler] 118 if isinstance(sch, Triggerable): 119 triggered_schedulers.append(scheduler) 120 else: 121 unknown_schedulers.append(scheduler) 122 else: 123 unknown_schedulers.append(scheduler) 124 125 if unknown_schedulers: 126 self.step_status.setText(['no scheduler:'] + unknown_schedulers) 127 return self.end(FAILURE) 128 129 dl = [] 130 for scheduler in triggered_schedulers: 131 sch = all_schedulers[scheduler] 132 dl.append(sch.trigger(ss, set_props=props_to_set)) 133 self.step_status.setText(['triggered'] + triggered_schedulers) 134 135 if self.waitForFinish: 136 d = defer.DeferredList(dl, consumeErrors=1) 137 else: 138 d = defer.succeed([]) 139 140 def cb(rclist): 141 rc = SUCCESS # (this rc is not the same variable as that above) 142 for was_cb, results in rclist: 143 # TODO: make this algo more configurable 144 if not was_cb: 145 rc = EXCEPTION 146 log.err(results) 147 break 148 if results == FAILURE: 149 rc = FAILURE 150 return self.end(rc)
151 152 def eb(why): 153 return self.end(FAILURE)
154 155 d.addCallbacks(cb, eb) 156