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