Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Side by Side Diff: third_party/buildbot_7_12/buildbot/interfaces.py

Issue 12207158: Bye bye buildbot 0.7.12. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1
2 """Interface documentation.
3
4 Define the interfaces that are implemented by various buildbot classes.
5 """
6
7 from zope.interface import Interface, Attribute
8
9 # exceptions that can be raised while trying to start a build
10 class NoSlaveError(Exception):
11 pass
12 class BuilderInUseError(Exception):
13 pass
14 class BuildSlaveTooOldError(Exception):
15 pass
16 class LatentBuildSlaveFailedToSubstantiate(Exception):
17 pass
18
19 # other exceptions
20 class BuildbotNotRunningError(Exception):
21 pass
22
23 class IChangeSource(Interface):
24 """Object which feeds Change objects to the changemaster. When files or
25 directories are changed and the version control system provides some
26 kind of notification, this object should turn it into a Change object
27 and pass it through::
28
29 self.changemaster.addChange(change)
30 """
31
32 def start():
33 """Called when the buildmaster starts. Can be used to establish
34 connections to VC daemons or begin polling."""
35
36 def stop():
37 """Called when the buildmaster shuts down. Connections should be
38 terminated, polling timers should be canceled."""
39
40 def describe():
41 """Should return a string which briefly describes this source. This
42 string will be displayed in an HTML status page."""
43
44 class IScheduler(Interface):
45 """I watch for Changes in the source tree and decide when to trigger
46 Builds. I create BuildSet objects and submit them to the BuildMaster. I
47 am a service, and the BuildMaster is always my parent.
48
49 @ivar properties: properties to be applied to all builds started by this
50 scheduler
51 @type properties: L<buildbot.process.properties.Properties>
52 """
53
54 def addChange(change):
55 """A Change has just been dispatched by one of the ChangeSources.
56 Each Scheduler will receive this Change. I may decide to start a
57 build as a result, or I might choose to ignore it."""
58
59 def listBuilderNames():
60 """Return a list of strings indicating the Builders that this
61 Scheduler might feed."""
62
63 def getPendingBuildTimes():
64 """Return a list of timestamps for any builds that are waiting in the
65 tree-stable-timer queue. This is only relevant for Change-based
66 schedulers, all others can just return an empty list."""
67 # TODO: it might be nice to make this into getPendingBuildSets, which
68 # would let someone subscribe to the buildset being finished.
69 # However, the Scheduler doesn't actually create the buildset until
70 # it gets submitted, so doing this would require some major rework.
71
72 class IUpstreamScheduler(Interface):
73 """This marks an IScheduler as being eligible for use as the 'upstream='
74 argument to a buildbot.scheduler.Dependent instance."""
75
76 def subscribeToSuccessfulBuilds(target):
77 """Request that the target callbable be invoked after every
78 successful buildset. The target will be called with a single
79 argument: the SourceStamp used by the successful builds."""
80
81 def listBuilderNames():
82 """Return a list of strings indicating the Builders that this
83 Scheduler might feed."""
84
85 class IDownstreamScheduler(Interface):
86 """This marks an IScheduler to be listening to other schedulers.
87 On reconfigs, these might get notified to check if their upstream
88 scheduler are stil the same."""
89
90 def checkUpstreamScheduler():
91 """Check if the upstream scheduler is still alive, and if not,
92 get a new upstream object from the master."""
93
94
95 class ISourceStamp(Interface):
96 """
97 @cvar branch: branch from which source was drawn
98 @type branch: string or None
99
100 @cvar revision: revision of the source, or None to use CHANGES
101 @type revision: varies depending on VC
102
103 @cvar patch: patch applied to the source, or None if no patch
104 @type patch: None or tuple (level diff)
105
106 @cvar changes: the source step should check out hte latest revision
107 in the given changes
108 @type changes: tuple of L{buildbot.changes.changes.Change} instances,
109 all of which are on the same branch
110 """
111
112 def canBeMergedWith(self, other):
113 """
114 Can this SourceStamp be merged with OTHER?
115 """
116
117 def mergeWith(self, others):
118 """Generate a SourceStamp for the merger of me and all the other
119 BuildRequests. This is called by a Build when it starts, to figure
120 out what its sourceStamp should be."""
121
122 def getAbsoluteSourceStamp(self, got_revision):
123 """Get a new SourceStamp object reflecting the actual revision found
124 by a Source step."""
125
126 def getText(self):
127 """Returns a list of strings to describe the stamp. These are
128 intended to be displayed in a narrow column. If more space is
129 available, the caller should join them together with spaces before
130 presenting them to the user."""
131
132 class IEmailSender(Interface):
133 """I know how to send email, and can be used by other parts of the
134 Buildbot to contact developers."""
135 pass
136
137 class IEmailLookup(Interface):
138 def getAddress(user):
139 """Turn a User-name string into a valid email address. Either return
140 a string (with an @ in it), None (to indicate that the user cannot
141 be reached by email), or a Deferred which will fire with the same."""
142
143 class IStatus(Interface):
144 """I am an object, obtainable from the buildmaster, which can provide
145 status information."""
146
147 def getProjectName():
148 """Return the name of the project that this Buildbot is working
149 for."""
150 def getProjectURL():
151 """Return the URL of this Buildbot's project."""
152 def getBuildbotURL():
153 """Return the URL of the top-most Buildbot status page, or None if
154 this Buildbot does not provide a web status page."""
155 def getURLForThing(thing):
156 """Return the URL of a page which provides information on 'thing',
157 which should be an object that implements one of the status
158 interfaces defined in L{buildbot.interfaces}. Returns None if no
159 suitable page is available (or if no Waterfall is running)."""
160
161 def getChangeSources():
162 """Return a list of IChangeSource objects."""
163
164 def getChange(number):
165 """Return an IChange object."""
166
167 def getSchedulers():
168 """Return a list of ISchedulerStatus objects for all
169 currently-registered Schedulers."""
170
171 def getBuilderNames(categories=None):
172 """Return a list of the names of all current Builders."""
173 def getBuilder(name):
174 """Return the IBuilderStatus object for a given named Builder. Raises
175 KeyError if there is no Builder by that name."""
176
177 def getSlaveNames():
178 """Return a list of buildslave names, suitable for passing to
179 getSlave()."""
180 def getSlave(name):
181 """Return the ISlaveStatus object for a given named buildslave."""
182
183 def getBuildSets():
184 """Return a list of active (non-finished) IBuildSetStatus objects."""
185
186 def generateFinishedBuilds(builders=[], branches=[],
187 num_builds=None, finished_before=None,
188 max_search=200):
189 """Return a generator that will produce IBuildStatus objects each
190 time you invoke its .next() method, starting with the most recent
191 finished build and working backwards.
192
193 @param builders: this is a list of Builder names, and the generator
194 will only produce builds that ran on the given
195 Builders. If the list is empty, produce builds from
196 all Builders.
197
198 @param branches: this is a list of branch names, and the generator
199 will only produce builds that used the given
200 branches. If the list is empty, produce builds from
201 all branches.
202
203 @param num_builds: the generator will stop after providing this many
204 builds. The default of None means to produce as
205 many builds as possible.
206
207 @type finished_before: int: a timestamp, seconds since the epoch
208 @param finished_before: if provided, do not produce any builds that
209 finished after the given timestamp.
210
211 @type max_search: int
212 @param max_search: this method may have to examine a lot of builds
213 to find some that match the search parameters,
214 especially if there aren't any matching builds.
215 This argument imposes a hard limit on the number
216 of builds that will be examined within any given
217 Builder.
218 """
219
220 def subscribe(receiver):
221 """Register an IStatusReceiver to receive new status events. The
222 receiver will immediately be sent a set of 'builderAdded' messages
223 for all current builders. It will receive further 'builderAdded' and
224 'builderRemoved' messages as the config file is reloaded and builders
225 come and go. It will also receive 'buildsetSubmitted' messages for
226 all outstanding BuildSets (and each new BuildSet that gets
227 submitted). No additional messages will be sent unless the receiver
228 asks for them by calling .subscribe on the IBuilderStatus objects
229 which accompany the addedBuilder message."""
230
231 def unsubscribe(receiver):
232 """Unregister an IStatusReceiver. No further status messgaes will be
233 delivered."""
234
235 class IBuildSetStatus(Interface):
236 """I represent a set of Builds, each run on a separate Builder but all
237 using the same source tree."""
238
239 def getSourceStamp():
240 """Return a SourceStamp object which can be used to re-create
241 the source tree that this build used.
242
243 This method will return None if the source information is no longer
244 available."""
245 pass
246 def getReason():
247 pass
248 def getID():
249 """Return the BuildSet's ID string, if any. The 'try' feature uses a
250 random string as a BuildSetID to relate submitted jobs with the
251 resulting BuildSet."""
252 def getResponsibleUsers():
253 pass # not implemented
254 def getInterestedUsers():
255 pass # not implemented
256 def getBuilderNames():
257 """Return a list of the names of all Builders on which this set will
258 do builds."""
259 def getBuildRequests():
260 """Return a list of IBuildRequestStatus objects that represent my
261 component Builds. This list might correspond to the Builders named by
262 getBuilderNames(), but if builder categories are used, or 'Builder
263 Aliases' are implemented, then they may not."""
264 def isFinished():
265 pass
266 def waitUntilSuccess():
267 """Return a Deferred that fires (with this IBuildSetStatus object)
268 when the outcome of the BuildSet is known, i.e., upon the first
269 failure, or after all builds complete successfully."""
270 def waitUntilFinished():
271 """Return a Deferred that fires (with this IBuildSetStatus object)
272 when all builds have finished."""
273 def getResults():
274 pass
275
276 class IBuildRequestStatus(Interface):
277 """I represent a request to build a particular set of source code on a
278 particular Builder. These requests may be merged by the time they are
279 finally turned into a Build."""
280
281 def getSourceStamp():
282 """Return a SourceStamp object which can be used to re-create
283 the source tree that this build used. This method will
284 return an absolute SourceStamp if possible, and its results
285 may change as the build progresses. Specifically, a "HEAD"
286 build may later be more accurately specified by an absolute
287 SourceStamp with the specific revision information.
288
289 This method will return None if the source information is no longer
290 available."""
291 pass
292 def getBuilderName():
293 pass
294 def getBuilds():
295 """Return a list of IBuildStatus objects for each Build that has been
296 started in an attempt to satify this BuildRequest."""
297
298 def subscribe(observer):
299 """Register a callable that will be invoked (with a single
300 IBuildStatus object) for each Build that is created to satisfy this
301 request. There may be multiple Builds created in an attempt to handle
302 the request: they may be interrupted by the user or abandoned due to
303 a lost slave. The last Build (the one which actually gets to run to
304 completion) is said to 'satisfy' the BuildRequest. The observer will
305 be called once for each of these Builds, both old and new."""
306 def unsubscribe(observer):
307 """Unregister the callable that was registered with subscribe()."""
308 def getSubmitTime():
309 """Return the time when this request was submitted"""
310 def setSubmitTime(t):
311 """Sets the time when this request was submitted"""
312
313
314 class ISlaveStatus(Interface):
315 def getName():
316 """Return the name of the build slave."""
317
318 def getAdmin():
319 """Return a string with the slave admin's contact data."""
320
321 def getHost():
322 """Return a string with the slave host info."""
323
324 def isConnected():
325 """Return True if the slave is currently online, False if not."""
326
327 def lastMessageReceived():
328 """Return a timestamp (seconds since epoch) indicating when the most
329 recent message was received from the buildslave."""
330
331 class ISchedulerStatus(Interface):
332 def getName():
333 """Return the name of this Scheduler (a string)."""
334
335 def getPendingBuildsets():
336 """Return an IBuildSet for all BuildSets that are pending. These
337 BuildSets are waiting for their tree-stable-timers to expire."""
338 # TODO: this is not implemented anywhere
339
340
341 class IBuilderStatus(Interface):
342 def getName():
343 """Return the name of this Builder (a string)."""
344
345 def getCategory():
346 """Return the category of this builder (a string)."""
347
348 def getState():
349 # TODO: this isn't nearly as meaningful as it used to be
350 """Return a tuple (state, builds) for this Builder. 'state' is the
351 so-called 'big-status', indicating overall status (as opposed to
352 which step is currently running). It is a string, one of 'offline',
353 'idle', or 'building'. 'builds' is a list of IBuildStatus objects
354 (possibly empty) representing the currently active builds."""
355
356 def getSlaves():
357 """Return a list of ISlaveStatus objects for the buildslaves that are
358 used by this builder."""
359
360 def getPendingBuilds():
361 """Return an IBuildRequestStatus object for all upcoming builds
362 (those which are ready to go but which are waiting for a buildslave
363 to be available."""
364
365 def getCurrentBuilds():
366 """Return a list containing an IBuildStatus object for each build
367 currently in progress."""
368 # again, we could probably provide an object for 'waiting' and
369 # 'interlocked' too, but things like the Change list might still be
370 # subject to change
371
372 def getLastFinishedBuild():
373 """Return the IBuildStatus object representing the last finished
374 build, which may be None if the builder has not yet finished any
375 builds."""
376
377 def getBuild(number):
378 """Return an IBuildStatus object for a historical build. Each build
379 is numbered (starting at 0 when the Builder is first added),
380 getBuild(n) will retrieve the Nth such build. getBuild(-n) will
381 retrieve a recent build, with -1 being the most recent build
382 started. If the Builder is idle, this will be the same as
383 getLastFinishedBuild(). If the Builder is active, it will be an
384 unfinished build. This method will return None if the build is no
385 longer available. Older builds are likely to have less information
386 stored: Logs are the first to go, then Steps."""
387
388 def getEvent(number):
389 """Return an IStatusEvent object for a recent Event. Builders
390 connecting and disconnecting are events, as are ping attempts.
391 getEvent(-1) will return the most recent event. Events are numbered,
392 but it probably doesn't make sense to ever do getEvent(+n)."""
393
394 def generateFinishedBuilds(branches=[],
395 num_builds=None,
396 max_buildnum=None, finished_before=None,
397 max_search=200,
398 ):
399 """Return a generator that will produce IBuildStatus objects each
400 time you invoke its .next() method, starting with the most recent
401 finished build, then the previous build, and so on back to the oldest
402 build available.
403
404 @param branches: this is a list of branch names, and the generator
405 will only produce builds that involve the given
406 branches. If the list is empty, the generator will
407 produce all builds regardless of what branch they
408 used.
409
410 @param num_builds: if provided, the generator will stop after
411 providing this many builds. The default of None
412 means to produce as many builds as possible.
413
414 @param max_buildnum: if provided, the generator will start by
415 providing the build with this number, or the
416 highest-numbered preceding build (i.e. the
417 generator will not produce any build numbered
418 *higher* than max_buildnum). The default of None
419 means to start with the most recent finished
420 build. -1 means the same as None. -2 means to
421 start with the next-most-recent completed build,
422 etc.
423
424 @type finished_before: int: a timestamp, seconds since the epoch
425 @param finished_before: if provided, do not produce any builds that
426 finished after the given timestamp.
427
428 @type max_search: int
429 @param max_search: this method may have to examine a lot of builds
430 to find some that match the search parameters,
431 especially if there aren't any matching builds.
432 This argument imposes a hard limit on the number
433 of builds that will be examined.
434 """
435
436 def subscribe(receiver):
437 """Register an IStatusReceiver to receive new status events. The
438 receiver will be given builderChangedState, buildStarted, and
439 buildFinished messages."""
440
441 def unsubscribe(receiver):
442 """Unregister an IStatusReceiver. No further status messgaes will be
443 delivered."""
444
445 class IEventSource(Interface):
446 def eventGenerator(branches=[], categories=[], committers=[], minTime=0):
447 """This function creates a generator which will yield all of this
448 object's status events, starting with the most recent and progressing
449 backwards in time. These events provide the IStatusEvent interface.
450 At the moment they are all instances of buildbot.status.builder.Event
451 or buildbot.status.builder.BuildStepStatus .
452
453 @param branches: a list of branch names. The generator should only
454 return events that are associated with these branches. If the list is
455 empty, events for all branches should be returned (i.e. an empty list
456 means 'accept all' rather than 'accept none').
457
458 @param categories: a list of category names. The generator
459 should only return events that are categorized within the
460 given category. If the list is empty, events for all
461 categories should be returned.
462
463 @param comitters: a list of committers. The generator should only
464 return events caused by one of the listed committers. If the list is
465 empty or None, events from every committers should be returned.
466
467 @param minTime: a timestamp. Do not generate events occuring prior to
468 this timestamp.
469 """
470
471 class IBuildStatus(Interface):
472 """I represent the status of a single Build/BuildRequest. It could be
473 in-progress or finished."""
474
475 def getBuilder():
476 """
477 Return the BuilderStatus that owns this build.
478
479 @rtype: implementor of L{IBuilderStatus}
480 """
481
482 def isFinished():
483 """Return a boolean. True means the build has finished, False means
484 it is still running."""
485
486 def waitUntilFinished():
487 """Return a Deferred that will fire when the build finishes. If the
488 build has already finished, this deferred will fire right away. The
489 callback is given this IBuildStatus instance as an argument."""
490
491 def getProperty(propname):
492 """Return the value of the build property with the given name. Raises
493 KeyError if there is no such property on this build."""
494
495 def getReason():
496 """Return a string that indicates why the build was run. 'changes',
497 'forced', and 'periodic' are the most likely values. 'try' will be
498 added in the future."""
499
500 def getSourceStamp():
501 """Return a SourceStamp object which can be used to re-create
502 the source tree that this build used.
503
504 This method will return None if the source information is no longer
505 available."""
506 # TODO: it should be possible to expire the patch but still remember
507 # that the build was r123+something.
508
509 def getChanges():
510 """Return a list of Change objects which represent which source
511 changes went into the build."""
512
513 def getResponsibleUsers():
514 """Return a list of Users who are to blame for the changes that went
515 into this build. If anything breaks (at least anything that wasn't
516 already broken), blame them. Specifically, this is the set of users
517 who were responsible for the Changes that went into this build. Each
518 User is a string, corresponding to their name as known by the VC
519 repository."""
520
521 def getInterestedUsers():
522 """Return a list of Users who will want to know about the results of
523 this build. This is a superset of getResponsibleUsers(): it adds
524 people who are interested in this build but who did not actually
525 make the Changes that went into it (build sheriffs, code-domain
526 owners)."""
527
528 def getNumber():
529 """Within each builder, each Build has a number. Return it."""
530
531 def getPreviousBuild():
532 """Convenience method. Returns None if the previous build is
533 unavailable."""
534
535 def getSteps():
536 """Return a list of IBuildStepStatus objects. For invariant builds
537 (those which always use the same set of Steps), this should always
538 return the complete list, however some of the steps may not have
539 started yet (step.getTimes()[0] will be None). For variant builds,
540 this may not be complete (asking again later may give you more of
541 them)."""
542
543 def getTimes():
544 """Returns a tuple of (start, end). 'start' and 'end' are the times
545 (seconds since the epoch) when the Build started and finished. If
546 the build is still running, 'end' will be None."""
547
548 # while the build is running, the following methods make sense.
549 # Afterwards they return None
550
551 def getETA():
552 """Returns the number of seconds from now in which the build is
553 expected to finish, or None if we can't make a guess. This guess will
554 be refined over time."""
555
556 def getCurrentStep():
557 """Return an IBuildStepStatus object representing the currently
558 active step."""
559
560 # Once you know the build has finished, the following methods are legal.
561 # Before ths build has finished, they all return None.
562
563 def getSlavename():
564 """Return the name of the buildslave which handled this build."""
565
566 def getText():
567 """Returns a list of strings to describe the build. These are
568 intended to be displayed in a narrow column. If more space is
569 available, the caller should join them together with spaces before
570 presenting them to the user."""
571
572 def getResults():
573 """Return a constant describing the results of the build: one of the
574 constants in buildbot.status.builder: SUCCESS, WARNINGS,
575 FAILURE, SKIPPED or EXCEPTION."""
576
577 def getLogs():
578 """Return a list of logs that describe the build as a whole. Some
579 steps will contribute their logs, while others are are less important
580 and will only be accessible through the IBuildStepStatus objects.
581 Each log is an object which implements the IStatusLog interface."""
582
583 def getTestResults():
584 """Return a dictionary that maps test-name tuples to ITestResult
585 objects. This may return an empty or partially-filled dictionary
586 until the build has completed."""
587
588 # subscription interface
589
590 def subscribe(receiver, updateInterval=None):
591 """Register an IStatusReceiver to receive new status events. The
592 receiver will be given stepStarted and stepFinished messages. If
593 'updateInterval' is non-None, buildETAUpdate messages will be sent
594 every 'updateInterval' seconds."""
595
596 def unsubscribe(receiver):
597 """Unregister an IStatusReceiver. No further status messgaes will be
598 delivered."""
599
600 class ITestResult(Interface):
601 """I describe the results of a single unit test."""
602
603 def getName():
604 """Returns a tuple of strings which make up the test name. Tests may
605 be arranged in a hierarchy, so looking for common prefixes may be
606 useful."""
607
608 def getResults():
609 """Returns a constant describing the results of the test: SUCCESS,
610 WARNINGS, FAILURE."""
611
612 def getText():
613 """Returns a list of short strings which describe the results of the
614 test in slightly more detail. Suggested components include
615 'failure', 'error', 'passed', 'timeout'."""
616
617 def getLogs():
618 # in flux, it may be possible to provide more structured information
619 # like python Failure instances
620 """Returns a dictionary of test logs. The keys are strings like
621 'stdout', 'log', 'exceptions'. The values are strings."""
622
623
624 class IBuildStepStatus(Interface):
625 """I hold status for a single BuildStep."""
626
627 def getName():
628 """Returns a short string with the name of this step. This string
629 may have spaces in it."""
630
631 def getBuild():
632 """Returns the IBuildStatus object which contains this step."""
633
634 def getTimes():
635 """Returns a tuple of (start, end). 'start' and 'end' are the times
636 (seconds since the epoch) when the Step started and finished. If the
637 step has not yet started, 'start' will be None. If the step is still
638 running, 'end' will be None."""
639
640 def getExpectations():
641 """Returns a list of tuples (name, current, target). Each tuple
642 describes a single axis along which the step's progress can be
643 measured. 'name' is a string which describes the axis itself, like
644 'filesCompiled' or 'tests run' or 'bytes of output'. 'current' is a
645 number with the progress made so far, while 'target' is the value
646 that we expect (based upon past experience) to get to when the build
647 is finished.
648
649 'current' will change over time until the step is finished. It is
650 'None' until the step starts. When the build is finished, 'current'
651 may or may not equal 'target' (which is merely the expectation based
652 upon previous builds)."""
653
654 def getURLs():
655 """Returns a dictionary of URLs. Each key is a link name (a short
656 string, like 'results' or 'coverage'), and each value is a URL. These
657 links will be displayed along with the LogFiles.
658 """
659
660 def getLogs():
661 """Returns a list of IStatusLog objects. If the step has not yet
662 finished, this list may be incomplete (asking again later may give
663 you more of them)."""
664
665
666 def isFinished():
667 """Return a boolean. True means the step has finished, False means it
668 is still running."""
669
670 def waitUntilFinished():
671 """Return a Deferred that will fire when the step finishes. If the
672 step has already finished, this deferred will fire right away. The
673 callback is given this IBuildStepStatus instance as an argument."""
674
675 # while the step is running, the following methods make sense.
676 # Afterwards they return None
677
678 def getETA():
679 """Returns the number of seconds from now in which the step is
680 expected to finish, or None if we can't make a guess. This guess will
681 be refined over time."""
682
683 # Once you know the step has finished, the following methods are legal.
684 # Before ths step has finished, they all return None.
685
686 def getText():
687 """Returns a list of strings which describe the step. These are
688 intended to be displayed in a narrow column. If more space is
689 available, the caller should join them together with spaces before
690 presenting them to the user."""
691
692 def getResults():
693 """Return a tuple describing the results of the step: (result,
694 strings). 'result' is one of the constants in
695 buildbot.status.builder: SUCCESS, WARNINGS, FAILURE, or SKIPPED.
696 'strings' is an optional list of strings that the step wants to
697 append to the overall build's results. These strings are usually
698 more terse than the ones returned by getText(): in particular,
699 successful Steps do not usually contribute any text to the overall
700 build."""
701
702 # subscription interface
703
704 def subscribe(receiver, updateInterval=10):
705 """Register an IStatusReceiver to receive new status events. The
706 receiver will be given logStarted and logFinished messages. It will
707 also be given a ETAUpdate message every 'updateInterval' seconds."""
708
709 def unsubscribe(receiver):
710 """Unregister an IStatusReceiver. No further status messgaes will be
711 delivered."""
712
713 class IStatusEvent(Interface):
714 """I represent a Builder Event, something non-Build related that can
715 happen to a Builder."""
716
717 def getTimes():
718 """Returns a tuple of (start, end) like IBuildStepStatus, but end==0
719 indicates that this is a 'point event', which has no duration.
720 SlaveConnect/Disconnect are point events. Ping is not: it starts
721 when requested and ends when the response (positive or negative) is
722 returned"""
723
724 def getText():
725 """Returns a list of strings which describe the event. These are
726 intended to be displayed in a narrow column. If more space is
727 available, the caller should join them together with spaces before
728 presenting them to the user."""
729
730
731 LOG_CHANNEL_STDOUT = 0
732 LOG_CHANNEL_STDERR = 1
733 LOG_CHANNEL_HEADER = 2
734
735 class IStatusLog(Interface):
736 """I represent a single Log, which is a growing list of text items that
737 contains some kind of output for a single BuildStep. I might be finished,
738 in which case this list has stopped growing.
739
740 Each Log has a name, usually something boring like 'log' or 'output'.
741 These names are not guaranteed to be unique, however they are usually
742 chosen to be useful within the scope of a single step (i.e. the Compile
743 step might produce both 'log' and 'warnings'). The name may also have
744 spaces. If you want something more globally meaningful, at least within a
745 given Build, try::
746
747 '%s.%s' % (log.getStep.getName(), log.getName())
748
749 The Log can be presented as plain text, or it can be accessed as a list
750 of items, each of which has a channel indicator (header, stdout, stderr)
751 and a text chunk. An HTML display might represent the interleaved
752 channels with different styles, while a straight download-the-text
753 interface would just want to retrieve a big string.
754
755 The 'header' channel is used by ShellCommands to prepend a note about
756 which command is about to be run ('running command FOO in directory
757 DIR'), and append another note giving the exit code of the process.
758
759 Logs can be streaming: if the Log has not yet finished, you can
760 subscribe to receive new chunks as they are added.
761
762 A ShellCommand will have a Log associated with it that gathers stdout
763 and stderr. Logs may also be created by parsing command output or
764 through other synthetic means (grepping for all the warnings in a
765 compile log, or listing all the test cases that are going to be run).
766 Such synthetic Logs are usually finished as soon as they are created."""
767
768
769 def getName():
770 """Returns a short string with the name of this log, probably 'log'.
771 """
772
773 def getStep():
774 """Returns the IBuildStepStatus which owns this log."""
775 # TODO: can there be non-Step logs?
776
777 def isFinished():
778 """Return a boolean. True means the log has finished and is closed,
779 False means it is still open and new chunks may be added to it."""
780
781 def waitUntilFinished():
782 """Return a Deferred that will fire when the log is closed. If the
783 log has already finished, this deferred will fire right away. The
784 callback is given this IStatusLog instance as an argument."""
785
786 def subscribe(receiver, catchup):
787 """Register an IStatusReceiver to receive chunks (with logChunk) as
788 data is added to the Log. If you use this, you will also want to use
789 waitUntilFinished to find out when the listener can be retired.
790 Subscribing to a closed Log is a no-op.
791
792 If 'catchup' is True, the receiver will immediately be sent a series
793 of logChunk messages to bring it up to date with the partially-filled
794 log. This allows a status client to join a Log already in progress
795 without missing any data. If the Log has already finished, it is too
796 late to catch up: just do getText() instead.
797
798 If the Log is very large, the receiver will be called many times with
799 a lot of data. There is no way to throttle this data. If the receiver
800 is planning on sending the data on to somewhere else, over a narrow
801 connection, you can get a throttleable subscription by using
802 C{subscribeConsumer} instead."""
803
804 def unsubscribe(receiver):
805 """Remove a receiver previously registered with subscribe(). Attempts
806 to remove a receiver which was not previously registered is a no-op.
807 """
808
809 def subscribeConsumer(consumer):
810 """Register an L{IStatusLogConsumer} to receive all chunks of the
811 logfile, including all the old entries and any that will arrive in
812 the future. The consumer will first have their C{registerProducer}
813 method invoked with a reference to an object that can be told
814 C{pauseProducing}, C{resumeProducing}, and C{stopProducing}. Then the
815 consumer's C{writeChunk} method will be called repeatedly with each
816 (channel, text) tuple in the log, starting with the very first. The
817 consumer will be notified with C{finish} when the log has been
818 exhausted (which can only happen when the log is finished). Note that
819 a small amount of data could be written via C{writeChunk} even after
820 C{pauseProducing} has been called.
821
822 To unsubscribe the consumer, use C{producer.stopProducing}."""
823
824 # once the log has finished, the following methods make sense. They can
825 # be called earlier, but they will only return the contents of the log up
826 # to the point at which they were called. You will lose items that are
827 # added later. Use C{subscribe} or C{subscribeConsumer} to avoid missing
828 # anything.
829
830 def hasContents():
831 """Returns True if the LogFile still has contents available. Returns
832 False for logs that have been pruned. Clients should test this before
833 offering to show the contents of any log."""
834
835 def getText():
836 """Return one big string with the contents of the Log. This merges
837 all non-header chunks together."""
838
839 def readlines(channel=LOG_CHANNEL_STDOUT):
840 """Read lines from one channel of the logfile. This returns an
841 iterator that will provide single lines of text (including the
842 trailing newline).
843 """
844
845 def getTextWithHeaders():
846 """Return one big string with the contents of the Log. This merges
847 all chunks (including headers) together."""
848
849 def getChunks():
850 """Generate a list of (channel, text) tuples. 'channel' is a number,
851 0 for stdout, 1 for stderr, 2 for header. (note that stderr is merged
852 into stdout if PTYs are in use)."""
853
854 class IStatusLogConsumer(Interface):
855 """I am an object which can be passed to IStatusLog.subscribeConsumer().
856 I represent a target for writing the contents of an IStatusLog. This
857 differs from a regular IStatusReceiver in that it can pause the producer.
858 This makes it more suitable for use in streaming data over network
859 sockets, such as an HTTP request. Note that the consumer can only pause
860 the producer until it has caught up with all the old data. After that
861 point, C{pauseProducing} is ignored and all new output from the log is
862 sent directoy to the consumer."""
863
864 def registerProducer(producer, streaming):
865 """A producer is being hooked up to this consumer. The consumer only
866 has to handle a single producer. It should send .pauseProducing and
867 .resumeProducing messages to the producer when it wants to stop or
868 resume the flow of data. 'streaming' will be set to True because the
869 producer is always a PushProducer.
870 """
871
872 def unregisterProducer():
873 """The previously-registered producer has been removed. No further
874 pauseProducing or resumeProducing calls should be made. The consumer
875 should delete its reference to the Producer so it can be released."""
876
877 def writeChunk(chunk):
878 """A chunk (i.e. a tuple of (channel, text)) is being written to the
879 consumer."""
880
881 def finish():
882 """The log has finished sending chunks to the consumer."""
883
884 class IStatusReceiver(Interface):
885 """I am an object which can receive build status updates. I may be
886 subscribed to an IStatus, an IBuilderStatus, or an IBuildStatus."""
887
888 def buildsetSubmitted(buildset):
889 """A new BuildSet has been submitted to the buildmaster.
890
891 @type buildset: implementor of L{IBuildSetStatus}
892 """
893
894 def requestSubmitted(request):
895 """A new BuildRequest has been submitted to the buildmaster.
896
897 @type request: implementor of L{IBuildRequestStatus}
898 """
899
900 def requestCancelled(builder, request):
901 """A BuildRequest has been cancelled on the given Builder.
902
903 @type builder: L{buildbot.status.builder.BuilderStatus}
904 @type request: implementor of L{IBuildRequestStatus}
905 """
906
907 def builderAdded(builderName, builder):
908 """
909 A new Builder has just been added. This method may return an
910 IStatusReceiver (probably 'self') which will be subscribed to receive
911 builderChangedState and buildStarted/Finished events.
912
913 @type builderName: string
914 @type builder: L{buildbot.status.builder.BuilderStatus}
915 @rtype: implementor of L{IStatusReceiver}
916 """
917
918 def builderChangedState(builderName, state):
919 """Builder 'builderName' has changed state. The possible values for
920 'state' are 'offline', 'idle', and 'building'."""
921
922 def buildStarted(builderName, build):
923 """Builder 'builderName' has just started a build. The build is an
924 object which implements IBuildStatus, and can be queried for more
925 information.
926
927 This method may return an IStatusReceiver (it could even return
928 'self'). If it does so, stepStarted and stepFinished methods will be
929 invoked on the object for the steps of this one build. This is a
930 convenient way to subscribe to all build steps without missing any.
931 This receiver will automatically be unsubscribed when the build
932 finishes.
933
934 It can also return a tuple of (IStatusReceiver, interval), in which
935 case buildETAUpdate messages are sent ever 'interval' seconds, in
936 addition to the stepStarted and stepFinished messages."""
937
938 def buildETAUpdate(build, ETA):
939 """This is a periodic update on the progress this Build has made
940 towards completion."""
941
942 def changeAdded(change):
943 """A new Change was added to the ChangeMaster. By the time this event
944 is received, all schedulers have already received the change."""
945
946 def stepStarted(build, step):
947 """A step has just started. 'step' is the IBuildStepStatus which
948 represents the step: it can be queried for more information.
949
950 This method may return an IStatusReceiver (it could even return
951 'self'). If it does so, logStarted and logFinished methods will be
952 invoked on the object for logs created by this one step. This
953 receiver will be automatically unsubscribed when the step finishes.
954
955 Alternatively, the method may return a tuple of an IStatusReceiver
956 and an integer named 'updateInterval'. In addition to
957 logStarted/logFinished messages, it will also receive stepETAUpdate
958 messages about every updateInterval seconds."""
959
960 def stepTextChanged(build, step, text):
961 """The text for a step has been updated.
962
963 This is called when calling setText() on the step status, and
964 hands in the text list."""
965
966 def stepText2Changed(build, step, text2):
967 """The text2 for a step has been updated.
968
969 This is called when calling setText2() on the step status, and
970 hands in text2 list."""
971
972 def stepETAUpdate(build, step, ETA, expectations):
973 """This is a periodic update on the progress this Step has made
974 towards completion. It gets an ETA (in seconds from the present) of
975 when the step ought to be complete, and a list of expectation tuples
976 (as returned by IBuildStepStatus.getExpectations) with more detailed
977 information."""
978
979 def logStarted(build, step, log):
980 """A new Log has been started, probably because a step has just
981 started running a shell command. 'log' is the IStatusLog object
982 which can be queried for more information.
983
984 This method may return an IStatusReceiver (such as 'self'), in which
985 case the target's logChunk method will be invoked as text is added to
986 the logfile. This receiver will automatically be unsubsribed when the
987 log finishes."""
988
989 def logChunk(build, step, log, channel, text):
990 """Some text has been added to this log. 'channel' is one of
991 LOG_CHANNEL_STDOUT, LOG_CHANNEL_STDERR, or LOG_CHANNEL_HEADER, as
992 defined in IStatusLog.getChunks."""
993
994 def logFinished(build, step, log):
995 """A Log has been closed."""
996
997 def stepFinished(build, step, results):
998 """A step has just finished. 'results' is the result tuple described
999 in IBuildStepStatus.getResults."""
1000
1001 def buildFinished(builderName, build, results):
1002 """
1003 A build has just finished. 'results' is the result tuple described
1004 in L{IBuildStatus.getResults}.
1005
1006 @type builderName: string
1007 @type build: L{buildbot.status.builder.BuildStatus}
1008 @type results: tuple
1009 """
1010
1011 def builderRemoved(builderName):
1012 """The Builder has been removed."""
1013
1014 def slaveConnected(slaveName):
1015 """The slave has connected."""
1016
1017 def slaveDisconnected(slaveName):
1018 """The slave has disconnected."""
1019
1020 class IControl(Interface):
1021 def addChange(change):
1022 """Add a change to all builders. Each Builder will decide for
1023 themselves whether the change is interesting or not, and may initiate
1024 a build as a result."""
1025
1026 def submitBuildSet(buildset):
1027 """Submit a BuildSet object, which will eventually be run on all of
1028 the builders listed therein."""
1029
1030 def getBuilder(name):
1031 """Retrieve the IBuilderControl object for the given Builder."""
1032
1033 class IBuilderControl(Interface):
1034 def requestBuild(request):
1035 """Queue a L{buildbot.process.base.BuildRequest} object for later
1036 building."""
1037
1038 def requestBuildSoon(request):
1039 """Submit a BuildRequest like requestBuild, but raise a
1040 L{buildbot.interfaces.NoSlaveError} if no slaves are currently
1041 available, so it cannot be used to queue a BuildRequest in the hopes
1042 that a slave will eventually connect. This method is appropriate for
1043 use by things like the web-page 'Force Build' button."""
1044
1045 def resubmitBuild(buildStatus, reason="<rebuild, no reason given>"):
1046 """Rebuild something we've already built before. This submits a
1047 BuildRequest to our Builder using the same SourceStamp as the earlier
1048 build. This has no effect (but may eventually raise an exception) if
1049 this Build has not yet finished."""
1050
1051 def getPendingBuilds():
1052 """Return a list of L{IBuildRequestControl} objects for this Builder.
1053 Each one corresponds to a pending build that has not yet started (due
1054 to a scarcity of build slaves). These upcoming builds can be canceled
1055 through the control object."""
1056
1057 def getBuild(number):
1058 """Attempt to return an IBuildControl object for the given build.
1059 Returns None if no such object is available. This will only work for
1060 the build that is currently in progress: once the build finishes,
1061 there is nothing to control anymore."""
1062
1063 def ping():
1064 """Attempt to contact the slave and see if it is still alive. This
1065 returns a Deferred which fires with either True (the slave is still
1066 alive) or False (the slave did not respond). As a side effect, adds an
1067 event to this builder's column in the waterfall display containing the
1068 results of the ping. Note that this may not fail for a long time, it is
1069 implemented in terms of the timeout on the underlying TCP connection."""
1070 # TODO: this ought to live in ISlaveControl, maybe with disconnect()
1071 # or something. However the event that is emitted is most useful in
1072 # the Builder column, so it kinda fits here too.
1073
1074 class IBuildRequestControl(Interface):
1075 def subscribe(observer):
1076 """Register a callable that will be invoked (with a single
1077 IBuildControl object) for each Build that is created to satisfy this
1078 request. There may be multiple Builds created in an attempt to handle
1079 the request: they may be interrupted by the user or abandoned due to
1080 a lost slave. The last Build (the one which actually gets to run to
1081 completion) is said to 'satisfy' the BuildRequest. The observer will
1082 be called once for each of these Builds, both old and new."""
1083 def unsubscribe(observer):
1084 """Unregister the callable that was registered with subscribe()."""
1085 def cancel():
1086 """Remove the build from the pending queue. Has no effect if the
1087 build has already been started."""
1088
1089 class IBuildControl(Interface):
1090 def getStatus():
1091 """Return an IBuildStatus object for the Build that I control."""
1092 def stopBuild(reason="<no reason given>"):
1093 """Halt the build. This has no effect if the build has already
1094 finished."""
1095
1096 class ILogFile(Interface):
1097 """This is the internal interface to a LogFile, used by the BuildStep to
1098 write data into the log.
1099 """
1100 def addStdout(data):
1101 pass
1102 def addStderr(data):
1103 pass
1104 def addHeader(data):
1105 pass
1106 def finish():
1107 """The process that is feeding the log file has finished, and no
1108 further data will be added. This closes the logfile."""
1109
1110 class ILogObserver(Interface):
1111 """Objects which provide this interface can be used in a BuildStep to
1112 watch the output of a LogFile and parse it incrementally.
1113 """
1114
1115 # internal methods
1116 def setStep(step):
1117 pass
1118 def setLog(log):
1119 pass
1120
1121 # methods called by the LogFile
1122 def logChunk(build, step, log, channel, text):
1123 pass
1124
1125 class IBuildSlave(Interface):
1126 # this is a marker interface for the BuildSlave class
1127 pass
1128
1129 class ILatentBuildSlave(IBuildSlave):
1130 """A build slave that is not always running, but can run when requested.
1131 """
1132 substantiated = Attribute('Substantiated',
1133 'Whether the latent build slave is currently '
1134 'substantiated with a real instance.')
1135
1136 def substantiate():
1137 """Request that the slave substantiate with a real instance.
1138
1139 Returns a deferred that will callback when a real instance has
1140 attached."""
1141
1142 # there is an insubstantiate too, but that is not used externally ATM.
1143
1144 def buildStarted(sb):
1145 """Inform the latent build slave that a build has started.
1146
1147 ``sb`` is a LatentSlaveBuilder as defined in buildslave.py. The sb
1148 is the one for whom the build started.
1149 """
1150
1151 def buildFinished(sb):
1152 """Inform the latent build slave that a build has finished.
1153
1154 ``sb`` is a LatentSlaveBuilder as defined in buildslave.py. The sb
1155 is the one for whom the build finished.
1156 """
OLDNEW
« no previous file with comments | « third_party/buildbot_7_12/buildbot/ec2buildslave.py ('k') | third_party/buildbot_7_12/buildbot/locks.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698