forked from buildbot/buildbot
-
Notifications
You must be signed in to change notification settings - Fork 6
/
trigger.py
134 lines (113 loc) · 5.67 KB
/
trigger.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
from buildbot.process.buildstep import LoggingBuildStep, SUCCESS, FAILURE, EXCEPTION
from buildbot.process.properties import Properties
from buildbot.schedulers.triggerable import Triggerable
from twisted.python import log
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={}, copy_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. These
properties will override properties set in the
Triggered scheduler's constructor.
@param copy_properties: a list of property names to copy verbatim
into any builds resulting from this trigger.
"""
assert schedulerNames, "You must specify a scheduler to trigger"
self.schedulerNames = schedulerNames
self.updateSourceStamp = updateSourceStamp
self.waitForFinish = waitForFinish
self.set_properties = set_properties
self.copy_properties = copy_properties
self.running = False
LoggingBuildStep.__init__(self, **kwargs)
self.addFactoryArguments(schedulerNames=schedulerNames,
updateSourceStamp=updateSourceStamp,
waitForFinish=waitForFinish,
set_properties=set_properties,
copy_properties=copy_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")
for p in self.copy_properties:
if p not in properties:
raise RuntimeError("copy_property '%s' is not set in the triggering build" % p)
props_to_set.setProperty(p, properties[p],
"%s (in triggering build)" % properties.getPropertySource(p))
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
for scheduler in self.schedulerNames:
scheduler = properties.render(scheduler)
if all_schedulers.has_key(scheduler):
sch = all_schedulers[scheduler]
if isinstance(sch, Triggerable):
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)
return self.finished(FAILURE)
dl = []
for scheduler in triggered_schedulers:
sch = all_schedulers[scheduler]
dl.append(sch.trigger(ss, set_props=props_to_set))
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, results in rclist:
# TODO: make this algo more configurable
if not was_cb:
rc = EXCEPTION
log.err(results)
break
if results == FAILURE:
rc = FAILURE
return self.finished(rc)
def eb(why):
return self.finished(FAILURE)
d.addCallbacks(cb, eb)