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 import time
39 from twisted.internet import defer
40 from twisted.python import log
41 from buildbot.sourcestamp import SourceStamp
42 from buildbot.schedulers import base
43
65
66 -class Periodic(base.BaseScheduler, TimedBuildMixin):
67 """Instead of watching for Changes, this Scheduler can just start a build
68 at fixed intervals. The C{periodicBuildTimer} parameter sets the number
69 of seconds to wait between such periodic builds. The first build will be
70 run immediately."""
71
72
73
74 compare_attrs = ('name', 'builderNames', 'periodicBuildTimer', 'branch',
75 'properties')
76
77 - def __init__(self, name, builderNames, periodicBuildTimer,
78 branch=None, properties={}):
84
86 return {"last_build": None}
87
96
101
117
118
119 -class Nightly(base.BaseScheduler, base.ClassifierMixin, TimedBuildMixin):
120 """Imitate 'cron' scheduling. This can be used to schedule a nightly
121 build, or one which runs are certain times of the day, week, or month.
122
123 Pass some subset of minute, hour, dayOfMonth, month, and dayOfWeek; each
124 may be a single number or a list of valid values. The builds will be
125 triggered whenever the current time matches these values. Wildcards are
126 represented by a '*' string. All fields default to a wildcard except
127 'minute', so with no fields this defaults to a build every hour, on the
128 hour.
129
130 For example, the following master.cfg clause will cause a build to be
131 started every night at 3:00am::
132
133 s = Nightly(name='nightly', builderNames=['builder1', 'builder2'],
134 hour=3, minute=0)
135 c['schedules'].append(s)
136
137 This scheduler will perform a build each monday morning at 6:23am and
138 again at 8:23am::
139
140 s = Nightly(name='BeforeWork', builderNames=['builder1'],
141 dayOfWeek=0, hour=[6,8], minute=23)
142
143 The following runs a build every two hours::
144
145 s = Nightly(name='every2hours', builderNames=['builder1'],
146 hour=range(0, 24, 2))
147
148 And this one will run only on December 24th::
149
150 s = Nightly(name='SleighPreflightCheck',
151 builderNames=['flying_circuits', 'radar'],
152 month=12, dayOfMonth=24, hour=12, minute=0)
153
154 For dayOfWeek and dayOfMonth, builds are triggered if the date matches
155 either of them. All time values are compared against the tuple returned
156 by time.localtime(), so month and dayOfMonth numbers start at 1, not
157 zero. dayOfWeek=0 is Monday, dayOfWeek=6 is Sunday.
158
159 When onlyIfChanged is True, the build is triggered only if changes have
160 arrived on the given branch since the last build was performed. As a
161 further restriction, if fileIsImportant= is provided (a one-argument
162 callable which takes a Change object and returns a bool), then the build
163 will be triggered only if at least one of those changes qualifies as
164 'important'. The following example will run a build at 3am, but only when
165 a source code file (.c/.h) has been changed:
166
167 def isSourceFile(change):
168 for fn in change.files:
169 if fn.endswith('.c') or fn.endswith('.h'):
170 return True
171 return False
172 s = Nightly(name='nightly-when-changed', builderNames=['builder1'],
173 hour=3, minute=0,
174 onlyIfChanged=True, fileIsImportant=isSourceFile)
175
176 onlyIfChanged defaults to False, which means a build will be performed
177 even if nothing has changed.
178 """
179
180 compare_attrs = ('name', 'builderNames',
181 'minute', 'hour', 'dayOfMonth', 'month',
182 'dayOfWeek', 'branch', 'onlyIfChanged',
183 'fileIsImportant', 'properties')
184
185 - def __init__(self, name, builderNames, minute=0, hour='*',
186 dayOfMonth='*', month='*', dayOfWeek='*',
187 branch=None, fileIsImportant=None, onlyIfChanged=False,
188 properties={}):
213
215 return {
216 "last_build": None,
217 "last_processed": max_changeid,
218 }
219
221 now = time.time()
222 next = self._calculateNextRunTimeFrom(now)
223
224 return [next]
225
234
236 now = time.time()
237 s = self.get_state(t)
238 last_build = s["last_build"]
239 if last_build is None:
240 next = self._calculateNextRunTimeFrom(self._start_time)
241 else:
242 next = self._calculateNextRunTimeFrom(last_build)
243
244
245 if next >= now:
246 return next + 1.0
247
248 self._maybe_start_build(t)
249 self.update_last_build(t, now)
250
251
252 return self._check_timer(t)
253
255 if self.onlyIfChanged:
256 db = self.parent.db
257 res = db.scheduler_get_classified_changes(self.schedulerid, t)
258 (important, unimportant) = res
259 if not important:
260 log.msg("Nightly Scheduler <%s>: "
261 "skipping build - No important change" % self.name)
262 return
263 relevant_changes = [c for c in (important + unimportant) if
264 c.branch == self.branch]
265 if not relevant_changes:
266 log.msg("Nightly Scheduler <%s>: "
267 "skipping build - No relevant change on branch" %
268 self.name)
269 return
270 self.start_requested_build(t, relevant_changes)
271
272 changeids = [c.number for c in relevant_changes]
273 db.scheduler_retire_changes(self.schedulerid, changeids, t)
274 else:
275
276 self.start_HEAD_build(t)
277
279 return time.localtime(time.mktime(timetuple)+secs)
280
282 def check(ourvalue, value):
283 if ourvalue == '*': return True
284 if isinstance(ourvalue, int): return value == ourvalue
285 return (value in ourvalue)
286
287 if not check(self.minute, timetuple[4]):
288
289 return False
290
291 if not check(self.hour, timetuple[3]):
292
293 return False
294
295 if not check(self.month, timetuple[1]):
296
297 return False
298
299 if self.dayOfMonth != '*' and self.dayOfWeek != '*':
300
301
302
303 if not (check(self.dayOfMonth, timetuple[2]) or
304 check(self.dayOfWeek, timetuple[6])):
305
306 return False
307 else:
308 if not check(self.dayOfMonth, timetuple[2]):
309
310 return False
311
312 if not check(self.dayOfWeek, timetuple[6]):
313
314 return False
315
316 return True
317
319 dateTime = time.localtime(now)
320
321
322 dateTime = self._addTime(dateTime, 60-dateTime[5])
323
324
325
326
327 yearLimit = dateTime[0]+2
328 while not self._isRunTime(dateTime):
329 dateTime = self._addTime(dateTime, 60)
330
331 assert dateTime[0] < yearLimit, 'Something is wrong with this code'
332 return time.mktime(dateTime)
333