Package buildbot :: Module interfaces
[frames] | no frames]

Source Code for Module buildbot.interfaces

   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
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
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=[]):
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
464 -class IBuildStatus(Interface):
465 """I represent the status of a single Build/BuildRequest. It could be 466 in-progress or finished.""" 467
468 - def getBuilder():
469 """ 470 Return the BuilderStatus that owns this build. 471 472 @rtype: implementor of L{IBuilderStatus} 473 """
474
475 - def isFinished():
476 """Return a boolean. True means the build has finished, False means 477 it is still running."""
478
479 - def waitUntilFinished():
480 """Return a Deferred that will fire when the build finishes. If the 481 build has already finished, this deferred will fire right away. The 482 callback is given this IBuildStatus instance as an argument."""
483
484 - def getProperty(propname):
485 """Return the value of the build property with the given name. Raises 486 KeyError if there is no such property on this build."""
487
488 - def getReason():
489 """Return a string that indicates why the build was run. 'changes', 490 'forced', and 'periodic' are the most likely values. 'try' will be 491 added in the future."""
492
493 - def getSourceStamp():
494 """Return a SourceStamp object which can be used to re-create 495 the source tree that this build used. 496 497 This method will return None if the source information is no longer 498 available."""
499 # TODO: it should be possible to expire the patch but still remember 500 # that the build was r123+something. 501
502 - def getChanges():
503 """Return a list of Change objects which represent which source 504 changes went into the build."""
505
506 - def getResponsibleUsers():
507 """Return a list of Users who are to blame for the changes that went 508 into this build. If anything breaks (at least anything that wasn't 509 already broken), blame them. Specifically, this is the set of users 510 who were responsible for the Changes that went into this build. Each 511 User is a string, corresponding to their name as known by the VC 512 repository."""
513
514 - def getInterestedUsers():
515 """Return a list of Users who will want to know about the results of 516 this build. This is a superset of getResponsibleUsers(): it adds 517 people who are interested in this build but who did not actually 518 make the Changes that went into it (build sheriffs, code-domain 519 owners)."""
520
521 - def getNumber():
522 """Within each builder, each Build has a number. Return it."""
523
524 - def getPreviousBuild():
525 """Convenience method. Returns None if the previous build is 526 unavailable."""
527
528 - def getSteps():
529 """Return a list of IBuildStepStatus objects. For invariant builds 530 (those which always use the same set of Steps), this should always 531 return the complete list, however some of the steps may not have 532 started yet (step.getTimes()[0] will be None). For variant builds, 533 this may not be complete (asking again later may give you more of 534 them)."""
535
536 - def getTimes():
537 """Returns a tuple of (start, end). 'start' and 'end' are the times 538 (seconds since the epoch) when the Build started and finished. If 539 the build is still running, 'end' will be None."""
540 541 # while the build is running, the following methods make sense. 542 # Afterwards they return None 543
544 - def getETA():
545 """Returns the number of seconds from now in which the build is 546 expected to finish, or None if we can't make a guess. This guess will 547 be refined over time."""
548
549 - def getCurrentStep():
550 """Return an IBuildStepStatus object representing the currently 551 active step."""
552 553 # Once you know the build has finished, the following methods are legal. 554 # Before ths build has finished, they all return None. 555
556 - def getSlavename():
557 """Return the name of the buildslave which handled this build."""
558
559 - def getText():
560 """Returns a list of strings to describe the build. These are 561 intended to be displayed in a narrow column. If more space is 562 available, the caller should join them together with spaces before 563 presenting them to the user."""
564
565 - def getResults():
566 """Return a constant describing the results of the build: one of the 567 constants in buildbot.status.builder: SUCCESS, WARNINGS, 568 FAILURE, SKIPPED or EXCEPTION."""
569
570 - def getLogs():
571 """Return a list of logs that describe the build as a whole. Some 572 steps will contribute their logs, while others are are less important 573 and will only be accessible through the IBuildStepStatus objects. 574 Each log is an object which implements the IStatusLog interface."""
575
576 - def getTestResults():
577 """Return a dictionary that maps test-name tuples to ITestResult 578 objects. This may return an empty or partially-filled dictionary 579 until the build has completed."""
580 581 # subscription interface 582
583 - def subscribe(receiver, updateInterval=None):
584 """Register an IStatusReceiver to receive new status events. The 585 receiver will be given stepStarted and stepFinished messages. If 586 'updateInterval' is non-None, buildETAUpdate messages will be sent 587 every 'updateInterval' seconds."""
588
589 - def unsubscribe(receiver):
590 """Unregister an IStatusReceiver. No further status messgaes will be 591 delivered."""
592
593 -class ITestResult(Interface):
594 """I describe the results of a single unit test.""" 595
596 - def getName():
597 """Returns a tuple of strings which make up the test name. Tests may 598 be arranged in a hierarchy, so looking for common prefixes may be 599 useful."""
600
601 - def getResults():
602 """Returns a constant describing the results of the test: SUCCESS, 603 WARNINGS, FAILURE."""
604
605 - def getText():
606 """Returns a list of short strings which describe the results of the 607 test in slightly more detail. Suggested components include 608 'failure', 'error', 'passed', 'timeout'."""
609
610 - def getLogs():
611 # in flux, it may be possible to provide more structured information 612 # like python Failure instances 613 """Returns a dictionary of test logs. The keys are strings like 614 'stdout', 'log', 'exceptions'. The values are strings."""
615 616
617 -class IBuildStepStatus(Interface):
618 """I hold status for a single BuildStep.""" 619
620 - def getName():
621 """Returns a short string with the name of this step. This string 622 may have spaces in it."""
623
624 - def getBuild():
625 """Returns the IBuildStatus object which contains this step."""
626
627 - def getTimes():
628 """Returns a tuple of (start, end). 'start' and 'end' are the times 629 (seconds since the epoch) when the Step started and finished. If the 630 step has not yet started, 'start' will be None. If the step is still 631 running, 'end' will be None."""
632
633 - def getExpectations():
634 """Returns a list of tuples (name, current, target). Each tuple 635 describes a single axis along which the step's progress can be 636 measured. 'name' is a string which describes the axis itself, like 637 'filesCompiled' or 'tests run' or 'bytes of output'. 'current' is a 638 number with the progress made so far, while 'target' is the value 639 that we expect (based upon past experience) to get to when the build 640 is finished. 641 642 'current' will change over time until the step is finished. It is 643 'None' until the step starts. When the build is finished, 'current' 644 may or may not equal 'target' (which is merely the expectation based 645 upon previous builds)."""
646
647 - def getURLs():
648 """Returns a dictionary of URLs. Each key is a link name (a short 649 string, like 'results' or 'coverage'), and each value is a URL. These 650 links will be displayed along with the LogFiles. 651 """
652
653 - def getLogs():
654 """Returns a list of IStatusLog objects. If the step has not yet 655 finished, this list may be incomplete (asking again later may give 656 you more of them)."""
657 658
659 - def isFinished():
660 """Return a boolean. True means the step has finished, False means it 661 is still running."""
662
663 - def waitUntilFinished():
664 """Return a Deferred that will fire when the step finishes. If the 665 step has already finished, this deferred will fire right away. The 666 callback is given this IBuildStepStatus instance as an argument."""
667 668 # while the step is running, the following methods make sense. 669 # Afterwards they return None 670
671 - def getETA():
672 """Returns the number of seconds from now in which the step is 673 expected to finish, or None if we can't make a guess. This guess will 674 be refined over time."""
675 676 # Once you know the step has finished, the following methods are legal. 677 # Before ths step has finished, they all return None. 678
679 - def getText():
680 """Returns a list of strings which describe the step. These are 681 intended to be displayed in a narrow column. If more space is 682 available, the caller should join them together with spaces before 683 presenting them to the user."""
684
685 - def getResults():
686 """Return a tuple describing the results of the step: (result, 687 strings). 'result' is one of the constants in 688 buildbot.status.builder: SUCCESS, WARNINGS, FAILURE, or SKIPPED. 689 'strings' is an optional list of strings that the step wants to 690 append to the overall build's results. These strings are usually 691 more terse than the ones returned by getText(): in particular, 692 successful Steps do not usually contribute any text to the overall 693 build."""
694 695 # subscription interface 696
697 - def subscribe(receiver, updateInterval=10):
698 """Register an IStatusReceiver to receive new status events. The 699 receiver will be given logStarted and logFinished messages. It will 700 also be given a ETAUpdate message every 'updateInterval' seconds."""
701
702 - def unsubscribe(receiver):
703 """Unregister an IStatusReceiver. No further status messgaes will be 704 delivered."""
705
706 -class IStatusEvent(Interface):
707 """I represent a Builder Event, something non-Build related that can 708 happen to a Builder.""" 709
710 - def getTimes():
711 """Returns a tuple of (start, end) like IBuildStepStatus, but end==0 712 indicates that this is a 'point event', which has no duration. 713 SlaveConnect/Disconnect are point events. Ping is not: it starts 714 when requested and ends when the response (positive or negative) is 715 returned"""
716
717 - def getText():
718 """Returns a list of strings which describe the event. These are 719 intended to be displayed in a narrow column. If more space is 720 available, the caller should join them together with spaces before 721 presenting them to the user."""
722 723 724 LOG_CHANNEL_STDOUT = 0 725 LOG_CHANNEL_STDERR = 1 726 LOG_CHANNEL_HEADER = 2 727
728 -class IStatusLog(Interface):
729 """I represent a single Log, which is a growing list of text items that 730 contains some kind of output for a single BuildStep. I might be finished, 731 in which case this list has stopped growing. 732 733 Each Log has a name, usually something boring like 'log' or 'output'. 734 These names are not guaranteed to be unique, however they are usually 735 chosen to be useful within the scope of a single step (i.e. the Compile 736 step might produce both 'log' and 'warnings'). The name may also have 737 spaces. If you want something more globally meaningful, at least within a 738 given Build, try:: 739 740 '%s.%s' % (log.getStep.getName(), log.getName()) 741 742 The Log can be presented as plain text, or it can be accessed as a list 743 of items, each of which has a channel indicator (header, stdout, stderr) 744 and a text chunk. An HTML display might represent the interleaved 745 channels with different styles, while a straight download-the-text 746 interface would just want to retrieve a big string. 747 748 The 'header' channel is used by ShellCommands to prepend a note about 749 which command is about to be run ('running command FOO in directory 750 DIR'), and append another note giving the exit code of the process. 751 752 Logs can be streaming: if the Log has not yet finished, you can 753 subscribe to receive new chunks as they are added. 754 755 A ShellCommand will have a Log associated with it that gathers stdout 756 and stderr. Logs may also be created by parsing command output or 757 through other synthetic means (grepping for all the warnings in a 758 compile log, or listing all the test cases that are going to be run). 759 Such synthetic Logs are usually finished as soon as they are created.""" 760 761
762 - def getName():
763 """Returns a short string with the name of this log, probably 'log'. 764 """
765
766 - def getStep():
767 """Returns the IBuildStepStatus which owns this log."""
768 # TODO: can there be non-Step logs? 769
770 - def isFinished():
771 """Return a boolean. True means the log has finished and is closed, 772 False means it is still open and new chunks may be added to it."""
773
774 - def waitUntilFinished():
775 """Return a Deferred that will fire when the log is closed. If the 776 log has already finished, this deferred will fire right away. The 777 callback is given this IStatusLog instance as an argument."""
778
779 - def subscribe(receiver, catchup):
780 """Register an IStatusReceiver to receive chunks (with logChunk) as 781 data is added to the Log. If you use this, you will also want to use 782 waitUntilFinished to find out when the listener can be retired. 783 Subscribing to a closed Log is a no-op. 784 785 If 'catchup' is True, the receiver will immediately be sent a series 786 of logChunk messages to bring it up to date with the partially-filled 787 log. This allows a status client to join a Log already in progress 788 without missing any data. If the Log has already finished, it is too 789 late to catch up: just do getText() instead. 790 791 If the Log is very large, the receiver will be called many times with 792 a lot of data. There is no way to throttle this data. If the receiver 793 is planning on sending the data on to somewhere else, over a narrow 794 connection, you can get a throttleable subscription by using 795 C{subscribeConsumer} instead."""
796
797 - def unsubscribe(receiver):
798 """Remove a receiver previously registered with subscribe(). Attempts 799 to remove a receiver which was not previously registered is a no-op. 800 """
801
802 - def subscribeConsumer(consumer):
803 """Register an L{IStatusLogConsumer} to receive all chunks of the 804 logfile, including all the old entries and any that will arrive in 805 the future. The consumer will first have their C{registerProducer} 806 method invoked with a reference to an object that can be told 807 C{pauseProducing}, C{resumeProducing}, and C{stopProducing}. Then the 808 consumer's C{writeChunk} method will be called repeatedly with each 809 (channel, text) tuple in the log, starting with the very first. The 810 consumer will be notified with C{finish} when the log has been 811 exhausted (which can only happen when the log is finished). Note that 812 a small amount of data could be written via C{writeChunk} even after 813 C{pauseProducing} has been called. 814 815 To unsubscribe the consumer, use C{producer.stopProducing}."""
816 817 # once the log has finished, the following methods make sense. They can 818 # be called earlier, but they will only return the contents of the log up 819 # to the point at which they were called. You will lose items that are 820 # added later. Use C{subscribe} or C{subscribeConsumer} to avoid missing 821 # anything. 822
823 - def hasContents():
824 """Returns True if the LogFile still has contents available. Returns 825 False for logs that have been pruned. Clients should test this before 826 offering to show the contents of any log."""
827
828 - def getText():
829 """Return one big string with the contents of the Log. This merges 830 all non-header chunks together."""
831
832 - def readlines(channel=LOG_CHANNEL_STDOUT):
833 """Read lines from one channel of the logfile. This returns an 834 iterator that will provide single lines of text (including the 835 trailing newline). 836 """
837
838 - def getTextWithHeaders():
839 """Return one big string with the contents of the Log. This merges 840 all chunks (including headers) together."""
841
842 - def getChunks():
843 """Generate a list of (channel, text) tuples. 'channel' is a number, 844 0 for stdout, 1 for stderr, 2 for header. (note that stderr is merged 845 into stdout if PTYs are in use)."""
846
847 -class IStatusLogConsumer(Interface):
848 """I am an object which can be passed to IStatusLog.subscribeConsumer(). 849 I represent a target for writing the contents of an IStatusLog. This 850 differs from a regular IStatusReceiver in that it can pause the producer. 851 This makes it more suitable for use in streaming data over network 852 sockets, such as an HTTP request. Note that the consumer can only pause 853 the producer until it has caught up with all the old data. After that 854 point, C{pauseProducing} is ignored and all new output from the log is 855 sent directoy to the consumer.""" 856
857 - def registerProducer(producer, streaming):
858 """A producer is being hooked up to this consumer. The consumer only 859 has to handle a single producer. It should send .pauseProducing and 860 .resumeProducing messages to the producer when it wants to stop or 861 resume the flow of data. 'streaming' will be set to True because the 862 producer is always a PushProducer. 863 """
864
865 - def unregisterProducer():
866 """The previously-registered producer has been removed. No further 867 pauseProducing or resumeProducing calls should be made. The consumer 868 should delete its reference to the Producer so it can be released."""
869
870 - def writeChunk(chunk):
871 """A chunk (i.e. a tuple of (channel, text)) is being written to the 872 consumer."""
873
874 - def finish():
875 """The log has finished sending chunks to the consumer."""
876
877 -class IStatusReceiver(Interface):
878 """I am an object which can receive build status updates. I may be 879 subscribed to an IStatus, an IBuilderStatus, or an IBuildStatus.""" 880
881 - def buildsetSubmitted(buildset):
882 """A new BuildSet has been submitted to the buildmaster. 883 884 @type buildset: implementor of L{IBuildSetStatus} 885 """
886
887 - def requestSubmitted(request):
888 """A new BuildRequest has been submitted to the buildmaster. 889 890 @type request: implementor of L{IBuildRequestStatus} 891 """
892
893 - def requestCancelled(builder, request):
894 """A BuildRequest has been cancelled on the given Builder. 895 896 @type builder: L{buildbot.status.builder.BuilderStatus} 897 @type request: implementor of L{IBuildRequestStatus} 898 """
899
900 - def builderAdded(builderName, builder):
901 """ 902 A new Builder has just been added. This method may return an 903 IStatusReceiver (probably 'self') which will be subscribed to receive 904 builderChangedState and buildStarted/Finished events. 905 906 @type builderName: string 907 @type builder: L{buildbot.status.builder.BuilderStatus} 908 @rtype: implementor of L{IStatusReceiver} 909 """
910
911 - def builderChangedState(builderName, state):
912 """Builder 'builderName' has changed state. The possible values for 913 'state' are 'offline', 'idle', and 'building'."""
914
915 - def buildStarted(builderName, build):
916 """Builder 'builderName' has just started a build. The build is an 917 object which implements IBuildStatus, and can be queried for more 918 information. 919 920 This method may return an IStatusReceiver (it could even return 921 'self'). If it does so, stepStarted and stepFinished methods will be 922 invoked on the object for the steps of this one build. This is a 923 convenient way to subscribe to all build steps without missing any. 924 This receiver will automatically be unsubscribed when the build 925 finishes. 926 927 It can also return a tuple of (IStatusReceiver, interval), in which 928 case buildETAUpdate messages are sent ever 'interval' seconds, in 929 addition to the stepStarted and stepFinished messages."""
930
931 - def buildETAUpdate(build, ETA):
932 """This is a periodic update on the progress this Build has made 933 towards completion."""
934
935 - def stepStarted(build, step):
936 """A step has just started. 'step' is the IBuildStepStatus which 937 represents the step: it can be queried for more information. 938 939 This method may return an IStatusReceiver (it could even return 940 'self'). If it does so, logStarted and logFinished methods will be 941 invoked on the object for logs created by this one step. This 942 receiver will be automatically unsubscribed when the step finishes. 943 944 Alternatively, the method may return a tuple of an IStatusReceiver 945 and an integer named 'updateInterval'. In addition to 946 logStarted/logFinished messages, it will also receive stepETAUpdate 947 messages about every updateInterval seconds."""
948
949 - def stepTextChanged(build, step, text):
950 """The text for a step has been updated. 951 952 This is called when calling setText() on the step status, and 953 hands in the text list."""
954
955 - def stepText2Changed(build, step, text2):
956 """The text2 for a step has been updated. 957 958 This is called when calling setText2() on the step status, and 959 hands in text2 list."""
960
961 - def stepETAUpdate(build, step, ETA, expectations):
962 """This is a periodic update on the progress this Step has made 963 towards completion. It gets an ETA (in seconds from the present) of 964 when the step ought to be complete, and a list of expectation tuples 965 (as returned by IBuildStepStatus.getExpectations) with more detailed 966 information."""
967
968 - def logStarted(build, step, log):
969 """A new Log has been started, probably because a step has just 970 started running a shell command. 'log' is the IStatusLog object 971 which can be queried for more information. 972 973 This method may return an IStatusReceiver (such as 'self'), in which 974 case the target's logChunk method will be invoked as text is added to 975 the logfile. This receiver will automatically be unsubsribed when the 976 log finishes."""
977
978 - def logChunk(build, step, log, channel, text):
979 """Some text has been added to this log. 'channel' is one of 980 LOG_CHANNEL_STDOUT, LOG_CHANNEL_STDERR, or LOG_CHANNEL_HEADER, as 981 defined in IStatusLog.getChunks."""
982
983 - def logFinished(build, step, log):
984 """A Log has been closed."""
985
986 - def stepFinished(build, step, results):
987 """A step has just finished. 'results' is the result tuple described 988 in IBuildStepStatus.getResults."""
989
990 - def buildFinished(builderName, build, results):
991 """ 992 A build has just finished. 'results' is the result tuple described 993 in L{IBuildStatus.getResults}. 994 995 @type builderName: string 996 @type build: L{buildbot.status.builder.BuildStatus} 997 @type results: tuple 998 """
999
1000 - def builderRemoved(builderName):
1001 """The Builder has been removed."""
1002
1003 -class IControl(Interface):
1004 - def addChange(change):
1005 """Add a change to all builders. Each Builder will decide for 1006 themselves whether the change is interesting or not, and may initiate 1007 a build as a result."""
1008
1009 - def submitBuildSet(buildset):
1010 """Submit a BuildSet object, which will eventually be run on all of 1011 the builders listed therein."""
1012
1013 - def getBuilder(name):
1014 """Retrieve the IBuilderControl object for the given Builder."""
1015
1016 -class IBuilderControl(Interface):
1017 - def requestBuild(request):
1018 """Queue a L{buildbot.process.base.BuildRequest} object for later 1019 building."""
1020
1021 - def requestBuildSoon(request):
1022 """Submit a BuildRequest like requestBuild, but raise a 1023 L{buildbot.interfaces.NoSlaveError} if no slaves are currently 1024 available, so it cannot be used to queue a BuildRequest in the hopes 1025 that a slave will eventually connect. This method is appropriate for 1026 use by things like the web-page 'Force Build' button."""
1027
1028 - def resubmitBuild(buildStatus, reason="<rebuild, no reason given>"):
1029 """Rebuild something we've already built before. This submits a 1030 BuildRequest to our Builder using the same SourceStamp as the earlier 1031 build. This has no effect (but may eventually raise an exception) if 1032 this Build has not yet finished."""
1033
1034 - def getPendingBuilds():
1035 """Return a list of L{IBuildRequestControl} objects for this Builder. 1036 Each one corresponds to a pending build that has not yet started (due 1037 to a scarcity of build slaves). These upcoming builds can be canceled 1038 through the control object."""
1039
1040 - def getBuild(number):
1041 """Attempt to return an IBuildControl object for the given build. 1042 Returns None if no such object is available. This will only work for 1043 the build that is currently in progress: once the build finishes, 1044 there is nothing to control anymore."""
1045
1046 - def ping():
1047 """Attempt to contact the slave and see if it is still alive. This 1048 returns a Deferred which fires with either True (the slave is still 1049 alive) or False (the slave did not respond). As a side effect, adds an 1050 event to this builder's column in the waterfall display containing the 1051 results of the ping. Note that this may not fail for a long time, it is 1052 implemented in terms of the timeout on the underlying TCP connection."""
1053 # TODO: this ought to live in ISlaveControl, maybe with disconnect() 1054 # or something. However the event that is emitted is most useful in 1055 # the Builder column, so it kinda fits here too. 1056
1057 -class IBuildRequestControl(Interface):
1058 - def subscribe(observer):
1059 """Register a callable that will be invoked (with a single 1060 IBuildControl object) for each Build that is created to satisfy this 1061 request. There may be multiple Builds created in an attempt to handle 1062 the request: they may be interrupted by the user or abandoned due to 1063 a lost slave. The last Build (the one which actually gets to run to 1064 completion) is said to 'satisfy' the BuildRequest. The observer will 1065 be called once for each of these Builds, both old and new."""
1066 - def unsubscribe(observer):
1067 """Unregister the callable that was registered with subscribe()."""
1068 - def cancel():
1069 """Remove the build from the pending queue. Has no effect if the 1070 build has already been started."""
1071
1072 -class IBuildControl(Interface):
1073 - def getStatus():
1074 """Return an IBuildStatus object for the Build that I control."""
1075 - def stopBuild(reason="<no reason given>"):
1076 """Halt the build. This has no effect if the build has already 1077 finished."""
1078
1079 -class ILogFile(Interface):
1080 """This is the internal interface to a LogFile, used by the BuildStep to 1081 write data into the log. 1082 """
1083 - def addStdout(data):
1084 pass
1085 - def addStderr(data):
1086 pass
1087 - def addHeader(data):
1088 pass
1089 - def finish():
1090 """The process that is feeding the log file has finished, and no 1091 further data will be added. This closes the logfile."""
1092
1093 -class ILogObserver(Interface):
1094 """Objects which provide this interface can be used in a BuildStep to 1095 watch the output of a LogFile and parse it incrementally. 1096 """ 1097 1098 # internal methods
1099 - def setStep(step):
1100 pass
1101 - def setLog(log):
1102 pass
1103 1104 # methods called by the LogFile
1105 - def logChunk(build, step, log, channel, text):
1106 pass
1107
1108 -class IBuildSlave(Interface):
1109 # this is a marker interface for the BuildSlave class 1110 pass
1111
1112 -class ILatentBuildSlave(IBuildSlave):
1113 """A build slave that is not always running, but can run when requested. 1114 """ 1115 substantiated = Attribute('Substantiated', 1116 'Whether the latent build slave is currently ' 1117 'substantiated with a real instance.') 1118
1119 - def substantiate():
1120 """Request that the slave substantiate with a real instance. 1121 1122 Returns a deferred that will callback when a real instance has 1123 attached."""
1124 1125 # there is an insubstantiate too, but that is not used externally ATM. 1126
1127 - def buildStarted(sb):
1128 """Inform the latent build slave that a build has started. 1129 1130 ``sb`` is a LatentSlaveBuilder as defined in buildslave.py. The sb 1131 is the one for whom the build started. 1132 """
1133
1134 - def buildFinished(sb):
1135 """Inform the latent build slave that a build has finished. 1136 1137 ``sb`` is a LatentSlaveBuilder as defined in buildslave.py. The sb 1138 is the one for whom the build finished. 1139 """
1140