1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from buildbot.interfaces import ITriggerableScheduler
17 from buildbot.process.buildstep import LoggingBuildStep, SUCCESS, FAILURE, EXCEPTION
18 from buildbot.process.properties import Properties, Property
19 from twisted.python import log
20 from twisted.internet import defer
21 from buildbot import config
24 name = "trigger"
25
26 renderables = [ 'set_properties', 'schedulerNames', 'sourceStamps',
27 'updateSourceStamp', 'alwaysUseLatest' ]
28
29 flunkOnFailure = True
30
31 - def __init__(self, schedulerNames=[], sourceStamp = None, sourceStamps = None,
32 updateSourceStamp=None, alwaysUseLatest=False,
33 waitForFinish=False, set_properties={},
34 copy_properties=[], **kwargs):
35 if not schedulerNames:
36 config.error(
37 "You must specify a scheduler to trigger")
38 if (sourceStamp or sourceStamps) and (updateSourceStamp is not None):
39 config.error(
40 "You can't specify both sourceStamps and updateSourceStamp")
41 if (sourceStamp or sourceStamps) and alwaysUseLatest:
42 config.error(
43 "You can't specify both sourceStamps and alwaysUseLatest")
44 if alwaysUseLatest and (updateSourceStamp is not None):
45 config.error(
46 "You can't specify both alwaysUseLatest and updateSourceStamp"
47 )
48 self.schedulerNames = schedulerNames
49 self.sourceStamps = sourceStamps or []
50 if sourceStamp:
51 self.sourceStamps.append(sourceStamp)
52 if updateSourceStamp is not None:
53 self.updateSourceStamp = updateSourceStamp
54 else:
55 self.updateSourceStamp = not (alwaysUseLatest or self.sourceStamps)
56 self.alwaysUseLatest = alwaysUseLatest
57 self.waitForFinish = waitForFinish
58 properties = {}
59 properties.update(set_properties)
60 for i in copy_properties:
61 properties[i] = Property(i)
62 self.set_properties = properties
63 self.running = False
64 self.ended = False
65 LoggingBuildStep.__init__(self, **kwargs)
66
71
72 - def end(self, result):
73 if not self.ended:
74 self.ended = True
75 return self.finished(result)
76
77
79
80
81 trigger_properties = Properties()
82 trigger_properties.update(self.set_properties, "Trigger")
83 return trigger_properties
84
85
86
105
107 if self.sourceStamps:
108 ss_for_trigger = {}
109 for ss in self.sourceStamps:
110 codebase = ss.get('codebase','')
111 assert codebase not in ss_for_trigger, "codebase specified multiple times"
112 ss_for_trigger[codebase] = ss
113 return ss_for_trigger
114
115 if self.alwaysUseLatest:
116 return {}
117
118
119 ss_for_trigger = {}
120 objs_from_build = self.build.getAllSourceStamps()
121 for ss in objs_from_build:
122 ss_for_trigger[ss.codebase] = ss.asDict()
123
124
125 if self.updateSourceStamp:
126 got = self.build.build_status.getAllGotRevisions()
127 for codebase in ss_for_trigger:
128 if codebase in got:
129 ss_for_trigger[codebase]['revision'] = got[codebase]
130
131 return ss_for_trigger
132
133 @defer.inlineCallbacks
135
136 (triggered_schedulers, invalid_schedulers) = self.getSchedulers()
137 if invalid_schedulers:
138 self.step_status.setText(['not valid scheduler:'] + invalid_schedulers)
139 self.end(FAILURE)
140 return
141
142 self.running = True
143
144 props_to_set = self.createTriggerProperties()
145
146 ss_for_trigger = self.prepareSourcestampListForTrigger()
147
148 dl = []
149 triggered_names = []
150 for sch in triggered_schedulers:
151 dl.append(sch.trigger(ss_for_trigger, set_props=props_to_set))
152 triggered_names.append(sch.name)
153 self.step_status.setText(['triggered'] + triggered_names)
154
155 if self.waitForFinish:
156 rclist = yield defer.DeferredList(dl, consumeErrors=1)
157 else:
158
159 for d in dl:
160 d.addErrback(log.err,
161 '(ignored) while invoking Triggerable schedulers:')
162 rclist = None
163 self.end(SUCCESS)
164 return
165
166 was_exception = was_failure = False
167 brids = {}
168 for was_cb, results in rclist:
169 if isinstance(results, tuple):
170 results, some_brids = results
171 brids.update(some_brids)
172
173 if not was_cb:
174 was_exception = True
175 log.err(results)
176 continue
177
178 if results==FAILURE:
179 was_failure = True
180
181 if was_exception:
182 result = EXCEPTION
183 elif was_failure:
184 result = FAILURE
185 else:
186 result = SUCCESS
187
188 if brids:
189 master = self.build.builder.botmaster.parent
190 def add_links(res):
191
192 brid_to_bn = dict((_brid,_bn) for _bn,_brid in brids.iteritems())
193
194 for was_cb, builddicts in res:
195 if was_cb:
196 for build in builddicts:
197 bn = brid_to_bn[build['brid']]
198 num = build['number']
199
200 url = master.status.getURLForBuild(bn, num)
201 self.step_status.addURL("%s #%d" % (bn,num), url)
202
203 return self.end(result)
204
205 builddicts = [master.db.builds.getBuildsForRequest(br) for br in brids.values()]
206 dl = defer.DeferredList(builddicts, consumeErrors=1)
207 dl.addCallback(add_links)
208
209 self.end(result)
210 return
211