def __init__(self, reason, source, builderName=None): # TODO: remove the =None on builderName, it is there so I don't have # to change a lot of tests that create BuildRequest objects assert interfaces.ISourceStamp(source, None) self.reason = reason self.source = source self.start_watchers = [] self.finish_watchers = [] self.status = BuildRequestStatus(source, builderName)
def __init__(self, reason, source, builderName, properties=None): assert interfaces.ISourceStamp(source, None) self.reason = reason self.source = source self.properties = Properties() if properties: self.properties.updateFromProperties(properties) self.start_watchers = [] self.finish_watchers = [] self.status = BuildRequestStatus(source, builderName)
class BuildRequest: """I represent a request to a specific Builder to run a single build. I have a SourceStamp which specifies what sources I will build. This may specify a specific revision of the source tree (so source.branch, source.revision, and source.patch are used). The .patch attribute is either None or a tuple of (patchlevel, diff), consisting of a number to use in 'patch -pN', and a unified-format context diff. Alternatively, the SourceStamp may specify a set of Changes to be built, contained in source.changes. In this case, I may be mergeable with other BuildRequests on the same branch. I may be part of a BuildSet, in which case I will report status results to it. I am paired with a BuildRequestStatus object, to which I feed status information. @type source: a L{buildbot.sourcestamp.SourceStamp} instance. @ivar source: the source code that this BuildRequest use @type reason: string @ivar reason: the reason this Build is being requested. Schedulers provide this, but for forced builds the user requesting the build will provide a string. @type properties: Properties object @ivar properties: properties that should be applied to this build 'owner' property is used by Build objects to collect the list returned by getInterestedUsers @ivar status: the IBuildStatus object which tracks our status @ivar submittedAt: a timestamp (seconds since epoch) when this request was submitted to the Builder. This is used by the CVS step to compute a checkout timestamp, as well as the master to prioritize build requests from oldest to newest. """ source = None builder = None startCount = 0 # how many times we have tried to start this build submittedAt = None implements(interfaces.IBuildRequestControl) def __init__(self, reason, source, builderName, properties=None): assert interfaces.ISourceStamp(source, None) self.reason = reason self.source = source self.properties = Properties() if properties: self.properties.updateFromProperties(properties) self.start_watchers = [] self.finish_watchers = [] self.status = BuildRequestStatus(source, builderName) def canBeMergedWith(self, other): return self.source.canBeMergedWith(other.source) def mergeWith(self, others): return self.source.mergeWith([o.source for o in others]) def mergeReasons(self, others): """Return a reason for the merged build request.""" reasons = [] for req in [self] + others: if req.reason and req.reason not in reasons: reasons.append(req.reason) return ", ".join(reasons) def waitUntilFinished(self): """Get a Deferred that will fire (with a L{buildbot.interfaces.IBuildStatus} instance when the build finishes.""" d = defer.Deferred() self.finish_watchers.append(d) return d # these are called by the Builder def requestSubmitted(self, builder): # the request has been placed on the queue self.builder = builder def buildStarted(self, build, buildstatus): """This is called by the Builder when a Build has been started in the hopes of satifying this BuildRequest. It may be called multiple times, since interrupted builds and lost buildslaves may force multiple Builds to be run until the fate of the BuildRequest is known for certain.""" for o in self.start_watchers[:]: # these observers get the IBuildControl o(build) # while these get the IBuildStatus self.status.buildStarted(buildstatus) def finished(self, buildstatus): """This is called by the Builder when the BuildRequest has been retired. This happens when its Build has either succeeded (yay!) or failed (boo!). TODO: If it is halted due to an exception (oops!), or some other retryable error, C{finished} will not be called yet.""" for w in self.finish_watchers: w.callback(buildstatus) self.finish_watchers = [] # IBuildRequestControl def subscribe(self, observer): self.start_watchers.append(observer) def unsubscribe(self, observer): self.start_watchers.remove(observer) def cancel(self): """Cancel this request. This can only be successful if the Build has not yet been started. @return: a boolean indicating if the cancel was successful.""" if self.builder: return self.builder.cancelBuildRequest(self) return False def setSubmitTime(self, t): self.submittedAt = t self.status.setSubmitTime(t) def getSubmitTime(self): return self.submittedAt
class BuildRequest: """I represent a request to a specific Builder to run a single build. I have a SourceStamp which specifies what sources I will build. This may specify a specific revision of the source tree (so source.branch, source.revision, and source.patch are used). The .patch attribute is either None or a tuple of (patchlevel, diff), consisting of a number to use in 'patch -pN', and a unified-format context diff. Alternatively, the SourceStamp may specify a set of Changes to be built, contained in source.changes. In this case, I may be mergeable with other BuildRequests on the same branch. I may be part of a BuildSet, in which case I will report status results to it. I am paired with a BuildRequestStatus object, to which I feed status information. @type source: a L{buildbot.sourcestamp.SourceStamp} instance. @ivar source: the source code that this BuildRequest use @type reason: string @ivar reason: the reason this Build is being requested. Schedulers provide this, but for forced builds the user requesting the build will provide a string. @ivar status: the IBuildStatus object which tracks our status @ivar submittedAt: a timestamp (seconds since epoch) when this request was submitted to the Builder. This is used by the CVS step to compute a checkout timestamp. """ source = None builder = None startCount = 0 # how many times we have tried to start this build implements(interfaces.IBuildRequestControl) def __init__(self, reason, source, builderName=None): # TODO: remove the =None on builderName, it is there so I don't have # to change a lot of tests that create BuildRequest objects assert interfaces.ISourceStamp(source, None) self.reason = reason self.source = source self.start_watchers = [] self.finish_watchers = [] self.status = BuildRequestStatus(source, builderName) def canBeMergedWith(self, other): return self.source.canBeMergedWith(other.source) def mergeWith(self, others): return self.source.mergeWith([o.source for o in others]) def mergeReasons(self, others): """Return a reason for the merged build request.""" reasons = [] for req in [self] + others: if req.reason and req.reason not in reasons: reasons.append(req.reason) return ", ".join(reasons) def waitUntilFinished(self): """Get a Deferred that will fire (with a L{buildbot.interfaces.IBuildStatus} instance when the build finishes.""" d = defer.Deferred() self.finish_watchers.append(d) return d # these are called by the Builder def requestSubmitted(self, builder): # the request has been placed on the queue self.builder = builder def buildStarted(self, build, buildstatus): """This is called by the Builder when a Build has been started in the hopes of satifying this BuildRequest. It may be called multiple times, since interrupted builds and lost buildslaves may force multiple Builds to be run until the fate of the BuildRequest is known for certain.""" for o in self.start_watchers[:]: # these observers get the IBuildControl o(build) # while these get the IBuildStatus self.status.buildStarted(buildstatus) def finished(self, buildstatus): """This is called by the Builder when the BuildRequest has been retired. This happens when its Build has either succeeded (yay!) or failed (boo!). TODO: If it is halted due to an exception (oops!), or some other retryable error, C{finished} will not be called yet.""" for w in self.finish_watchers: w.callback(buildstatus) self.finish_watchers = [] # IBuildRequestControl def subscribe(self, observer): self.start_watchers.append(observer) def unsubscribe(self, observer): self.start_watchers.remove(observer) def cancel(self): """Cancel this request. This can only be successful if the Build has not yet been started. @return: a boolean indicating if the cancel was successful.""" if self.builder: return self.builder.cancelBuildRequest(self) return False