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
40 from buildbot import interfaces
41 from buildbot.util import collections, NotABranch
42 from buildbot.sourcestamp import SourceStamp
43 from buildbot.status.builder import SUCCESS, WARNINGS
44 from buildbot.schedulers import filter, base
45
46 -class Scheduler(base.BaseScheduler, base.ClassifierMixin):
47 fileIsImportant = None
48 compare_attrs = ('name', 'treeStableTimer', 'builderNames',
49 'fileIsImportant', 'properties', 'change_filter')
50
51 - def __init__(self, name, shouldntBeSet=NotABranch, treeStableTimer=None,
52 builderNames=None, branch=NotABranch, fileIsImportant=None,
53 properties={}, categories=None, change_filter=None):
54 """
55 @param name: the name of this Scheduler
56 @param treeStableTimer: the duration, in seconds, for which the tree
57 must remain unchanged before a build is
58 triggered. This is intended to avoid builds
59 of partially-committed fixes. If None, then
60 a separate build will be made for each
61 Change, regardless of when they arrive.
62 @param builderNames: a list of Builder names. When this Scheduler
63 decides to start a set of builds, they will be
64 run on the Builders named by this list.
65
66 @param fileIsImportant: A callable which takes one argument (a Change
67 instance) and returns True if the change is
68 worth building, and False if it is not.
69 Unimportant Changes are accumulated until the
70 build is triggered by an important change.
71 The default value of None means that all
72 Changes are important.
73
74 @param properties: properties to apply to all builds started from
75 this scheduler
76
77 @param change_filter: a buildbot.schedulers.filter.ChangeFilter instance
78 used to filter changes for this scheduler
79
80 @param branch: The branch name that the Scheduler should pay
81 attention to. Any Change that is not in this branch
82 will be ignored. It can be set to None to only pay
83 attention to the default branch.
84 @param categories: A list of categories of changes to accept
85 """
86 assert shouldntBeSet is NotABranch, \
87 "pass arguments to Scheduler using keyword arguments"
88
89 base.BaseScheduler.__init__(self, name, builderNames, properties)
90 self.make_filter(change_filter=change_filter, branch=branch, categories=categories)
91 self.treeStableTimer = treeStableTimer
92 self.branch = branch
93 if fileIsImportant:
94 assert callable(fileIsImportant)
95 self.fileIsImportant = fileIsImportant
96
98 return {"last_processed": max_changeid}
99
105
111
113 """Look at the changes that need to be processed and decide whether
114 to queue a BuildRequest or sleep until something changes.
115
116 If I decide that a build should be performed, I will add the
117 appropriate BuildRequest to the database queue, and remove the
118 (retired) changes that went into it from the scheduler_changes tabke.
119
120 Returns wakeup_delay: either None, or a float indicating when this
121 scheduler wants to be woken up next. The Scheduler is responsible for
122 padding its desired wakeup time by about a second to avoid frenetic
123 must-wake-up-at-exactly-8AM behavior. The Loop may silently impose a
124 minimum delay request of a couple seconds to prevent this sort of
125 thing, but Schedulers must still add their own padding to avoid at
126 least a double wakeup.
127 """
128
129 if not important:
130 return None
131 all_changes = important + unimportant
132 most_recent = max([c.when for c in all_changes])
133 if self.treeStableTimer is not None:
134 now = time.time()
135 stable_at = most_recent + self.treeStableTimer
136 if stable_at > now:
137
138
139 return stable_at + 1.0
140
141
142 self._add_build_and_remove_changes(t, all_changes)
143 return None
144
161
162
164 compare_attrs = ('name', 'treeStableTimer', 'builderNames',
165 'fileIsImportant', 'properties', 'change_filter')
166 - def __init__(self, name, treeStableTimer, builderNames,
167 fileIsImportant=None, properties={}, categories=None,
168 branches=NotABranch, change_filter=None):
169 """
170 @param name: the name of this Scheduler
171 @param treeStableTimer: the duration, in seconds, for which the tree
172 must remain unchanged before a build is
173 triggered. This is intended to avoid builds
174 of partially-committed fixes.
175 @param builderNames: a list of Builder names. When this Scheduler
176 decides to start a set of builds, they will be
177 run on the Builders named by this list.
178
179 @param fileIsImportant: A callable which takes one argument (a Change
180 instance) and returns True if the change is
181 worth building, and False if it is not.
182 Unimportant Changes are accumulated until the
183 build is triggered by an important change.
184 The default value of None means that all
185 Changes are important.
186
187 @param properties: properties to apply to all builds started from
188 this scheduler
189
190 @param change_filter: a buildbot.schedulers.filter.ChangeFilter instance
191 used to filter changes for this scheduler
192
193 @param branches: (deprecated)
194 @param categories: (deprecated)
195 """
196
197 base.BaseScheduler.__init__(self, name, builderNames, properties)
198 self.make_filter(change_filter=change_filter, branch=branches, categories=categories)
199 self.treeStableTimer = treeStableTimer
200 if fileIsImportant:
201 assert callable(fileIsImportant)
202 self.fileIsImportant = fileIsImportant
203
205 db = self.parent.db
206 res = db.scheduler_get_classified_changes(self.schedulerid, t)
207 (important, unimportant) = res
208 def _twolists(): return [], []
209 branch_changes = collections.defaultdict(_twolists)
210 for c in important:
211 branch_changes[c.branch][0].append(c)
212 for c in unimportant:
213 branch_changes[c.branch][1].append(c)
214 delays = []
215 for branch in branch_changes:
216 (b_important, b_unimportant) = branch_changes[branch]
217 delay = self.decide_and_remove_changes(t, b_important,
218 b_unimportant)
219 if delay is not None:
220 delays.append(delay)
221 if delays:
222 return min(delays)
223 return None
224
226
227
228 compare_attrs = ('name', 'upstream_name', 'builderNames', 'properties')
229
230 - def __init__(self, name, upstream, builderNames, properties={}):
237
241
257
258
259
260
261
262
263
264
265
266
267
268
269
270