1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import time
17 from twisted.internet import defer
18 from twisted.python import log
19 from buildbot.sourcestamp import SourceStamp
20 from buildbot.schedulers import base
21
43
44 -class Periodic(base.BaseScheduler, TimedBuildMixin):
45 """Instead of watching for Changes, this Scheduler can just start a build
46 at fixed intervals. The C{periodicBuildTimer} parameter sets the number
47 of seconds to wait between such periodic builds. The first build will be
48 run immediately."""
49
50
51
52 compare_attrs = ('name', 'builderNames', 'periodicBuildTimer', 'branch',
53 'properties')
54
55 - def __init__(self, name, builderNames, periodicBuildTimer,
56 branch=None, properties={}):
62
64 return {"last_build": None}
65
74
79
95
96
97 -class Nightly(base.BaseScheduler, base.ClassifierMixin, TimedBuildMixin):
98 """Imitate 'cron' scheduling. This can be used to schedule a nightly
99 build, or one which runs are certain times of the day, week, or month.
100
101 Pass some subset of minute, hour, dayOfMonth, month, and dayOfWeek; each
102 may be a single number or a list of valid values. The builds will be
103 triggered whenever the current time matches these values. Wildcards are
104 represented by a '*' string. All fields default to a wildcard except
105 'minute', so with no fields this defaults to a build every hour, on the
106 hour.
107
108 For example, the following master.cfg clause will cause a build to be
109 started every night at 3:00am::
110
111 s = Nightly(name='nightly', builderNames=['builder1', 'builder2'],
112 hour=3, minute=0)
113 c['schedules'].append(s)
114
115 This scheduler will perform a build each monday morning at 6:23am and
116 again at 8:23am::
117
118 s = Nightly(name='BeforeWork', builderNames=['builder1'],
119 dayOfWeek=0, hour=[6,8], minute=23)
120
121 The following runs a build every two hours::
122
123 s = Nightly(name='every2hours', builderNames=['builder1'],
124 hour=range(0, 24, 2))
125
126 And this one will run only on December 24th::
127
128 s = Nightly(name='SleighPreflightCheck',
129 builderNames=['flying_circuits', 'radar'],
130 month=12, dayOfMonth=24, hour=12, minute=0)
131
132 For dayOfWeek and dayOfMonth, builds are triggered if the date matches
133 either of them. All time values are compared against the tuple returned
134 by time.localtime(), so month and dayOfMonth numbers start at 1, not
135 zero. dayOfWeek=0 is Monday, dayOfWeek=6 is Sunday.
136
137 When onlyIfChanged is True, the build is triggered only if changes have
138 arrived on the given branch since the last build was performed. As a
139 further restriction, if fileIsImportant= is provided (a one-argument
140 callable which takes a Change object and returns a bool), then the build
141 will be triggered only if at least one of those changes qualifies as
142 'important'. The following example will run a build at 3am, but only when
143 a source code file (.c/.h) has been changed:
144
145 def isSourceFile(change):
146 for fn in change.files:
147 if fn.endswith('.c') or fn.endswith('.h'):
148 return True
149 return False
150 s = Nightly(name='nightly-when-changed', builderNames=['builder1'],
151 hour=3, minute=0,
152 onlyIfChanged=True, fileIsImportant=isSourceFile)
153
154 onlyIfChanged defaults to False, which means a build will be performed
155 even if nothing has changed.
156 """
157
158 compare_attrs = ('name', 'builderNames',
159 'minute', 'hour', 'dayOfMonth', 'month',
160 'dayOfWeek', 'branch', 'onlyIfChanged',
161 'fileIsImportant', 'properties')
162
163 - def __init__(self, name, builderNames, minute=0, hour='*',
164 dayOfMonth='*', month='*', dayOfWeek='*',
165 branch=None, fileIsImportant=None, onlyIfChanged=False,
166 properties={}):
191
193 return {
194 "last_build": None,
195 "last_processed": max_changeid,
196 }
197
199 now = time.time()
200 next = self._calculateNextRunTimeFrom(now)
201
202 return [next]
203
213
215 now = time.time()
216 s = self.get_state(t)
217 last_build = s["last_build"]
218 if last_build is None:
219 next = self._calculateNextRunTimeFrom(self._start_time)
220 else:
221 next = self._calculateNextRunTimeFrom(last_build)
222
223
224 if next >= now:
225 return next + 1.0
226
227 self._maybe_start_build(t)
228 self.update_last_build(t, now)
229
230
231 return self._check_timer(t)
232
262
264 return time.localtime(time.mktime(timetuple)+secs)
265
267 def check(ourvalue, value):
268 if ourvalue == '*': return True
269 if isinstance(ourvalue, int): return value == ourvalue
270 return (value in ourvalue)
271
272 if not check(self.minute, timetuple[4]):
273
274 return False
275
276 if not check(self.hour, timetuple[3]):
277
278 return False
279
280 if not check(self.month, timetuple[1]):
281
282 return False
283
284 if self.dayOfMonth != '*' and self.dayOfWeek != '*':
285
286
287
288 if not (check(self.dayOfMonth, timetuple[2]) or
289 check(self.dayOfWeek, timetuple[6])):
290
291 return False
292 else:
293 if not check(self.dayOfMonth, timetuple[2]):
294
295 return False
296
297 if not check(self.dayOfWeek, timetuple[6]):
298
299 return False
300
301 return True
302
304 dateTime = time.localtime(now)
305
306
307 dateTime = self._addTime(dateTime, 60-dateTime[5])
308
309
310
311
312 yearLimit = dateTime[0]+2
313 while not self._isRunTime(dateTime):
314 dateTime = self._addTime(dateTime, 60)
315
316 assert dateTime[0] < yearLimit, 'Something is wrong with this code'
317 return time.mktime(dateTime)
318