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

Source Code for Module buildbot.interfaces

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