[Buildbot-commits] buildbot/buildbot/scripts tryclient.py,1.6,1.7
Brian Warner
warner at users.sourceforge.net
Thu Aug 18 08:30:04 UTC 2005
Update of /cvsroot/buildbot/buildbot/buildbot/scripts
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21002/buildbot/scripts
Modified Files:
tryclient.py
Log Message:
Revision: arch at buildbot.sf.net--2004/buildbot--dev--0--patch-297
Creator: Brian Warner <warner at lothar.com>
make 'try' status reporting actually work
* buildbot/scripts/tryclient.py (Try): make 'try' status reporting
actually work. It's functional but still kind of clunky. Also, it
only works with the pb-style.. needs to be made to work with the
jobdir-style too.
* buildbot/status/client.py (RemoteBuildSet): new class
(RemoteBuildRequest): same
(RemoteBuild.remote_waitUntilFinished): return the RemoteBuild
object, not the internal BuildStatus object.
(RemoteBuild.remote_subscribe): new method to subscribe to builds
outside of the usual buildStarted() return value.
(BuildSubscriber): support class for RemoteBuild.remote_subscribe
* buildbot/scheduler.py (Try_Jobdir): convey buildsetID properly
(Try_Userpass_Perspective.perspective_try): return a remotely
usable BuildSetStatus object
* buildbot/interfaces.py (IBuildStatus): remove obsolete
isStarted()/waitUntilStarted()
--This line, and those below, will be ignored--
Files to commit:
<can't compute list>
This list might be incomplete or outdated if editing the log
message was not invoked from an up-to-date changes buffer!
Index: tryclient.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/scripts/tryclient.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- tryclient.py 16 Aug 2005 00:23:52 -0000 1.6
+++ tryclient.py 18 Aug 2005 08:30:01 -0000 1.7
@@ -1,7 +1,7 @@
# -*- test-case-name: buildbot.test.test_scheduler,buildbot.test.test_vc -*-
-import os, re, time
-from twisted.internet import utils, protocol, defer, reactor
+import sys, os, re, time
+from twisted.internet import utils, protocol, defer, reactor, task
from twisted.spread import pb
from twisted.cred import credentials
from twisted.python import log
@@ -9,6 +9,7 @@
from buildbot.sourcestamp import SourceStamp
from buildbot.scripts import runner
from buildbot.util import now
+from buildbot.status import builder
class SourceStampExtractor:
@@ -191,7 +192,7 @@
rc = status_object.value.exitCode
self.d.callback((sig, rc))
-class Try:
+class Try(pb.Referenceable):
buildsetStatus = None
quiet = False
@@ -291,12 +292,147 @@
# returns a Deferred that fires when the builds have finished, and
# may emit status messages while we wait
wait = bool(self.getopt("wait", "try_wait", False))
- if not self.buildsetStatus:
- # contact the status port, acquire a remotereference to the
- # corresponding BuildSetStatus object.
- pass
+ if not wait:
+ # TODO: emit the URL where they can follow the builds
+ return
+ d = self.running = defer.Deferred()
+ if self.buildsetStatus:
+ self._getStatus_1()
+ # TODO: contact the status port, acquire a remotereference to the
+ # corresponding BuildSetStatus object.
+ return d
+
+ def _getStatus_1(self, res=None):
+ if res:
+ self.buildsetStatus = res
+ # gather the set of BuildRequests
+ d = self.buildsetStatus.callRemote("getBuildRequests")
+ d.addCallback(self._getStatus_2)
+
+ def _getStatus_2(self, brs):
+ self.builderNames = []
+ self.buildRequests = {}
+
+ # self.builds holds the current BuildStatus object for each one
+ self.builds = {}
+
+ # self.outstanding holds the list of builderNames which haven't
+ # finished yet
+ self.outstanding = []
+
+ # self.results holds the list of build results. It holds a tuple of
+ # (result, text)
+ self.results = {}
+
+ # self.currentStep holds the name of the Step that each build is
+ # currently running
+ self.currentStep = {}
+
+ # self.ETA holds the expected finishing time (absolute time since
+ # epoch)
+ self.ETA = {}
+
+ for n,br in brs:
+ self.builderNames.append(n)
+ self.buildRequests[n] = br
+ self.builds[n] = None
+ self.outstanding.append(n)
+ self.results[n] = [None,None]
+ self.currentStep[n] = None
+ self.ETA[n] = None
+ # get new Builds for this buildrequest. We follow each one until
+ # it finishes or is interrupted.
+ br.callRemote("subscribe", self)
+
+ # now that those queries are in transit, we can start the
+ # display-status-every-30-seconds loop
+ self.printloop = task.LoopingCall(self.printStatus)
+ self.printloop.start(3, now=False)
+
+
+ # these methods are invoked by the status objects we've subscribed to
+
+ def remote_newbuild(self, bs, builderName):
+ if self.builds[builderName]:
+ self.builds[builderName].callRemote("unsubscribe", self)
+ self.builds[builderName] = bs
+ bs.callRemote("subscribe", self, 20)
+ d = bs.callRemote("waitUntilFinished")
+ d.addCallback(self._build_finished, builderName)
+
+ def remote_stepStarted(self, buildername, build, stepname, step):
+ self.currentStep[buildername] = stepname
+
+ def remote_stepFinished(self, buildername, build, stepname, step, results):
pass
+ def remote_buildETAUpdate(self, buildername, build, eta):
+ self.ETA[buildername] = now() + eta
+
+ def _build_finished(self, bs, builderName):
+ # we need to collect status from the newly-finished build. We don't
+ # remove the build from self.outstanding until we've collected
+ # everything we want.
+ self.builds[builderName] = None
+ self.ETA[builderName] = None
+ self.currentStep[builderName] = "finished"
+ d = bs.callRemote("getResults")
+ d.addCallback(self._build_finished_2, bs, builderName)
+ return d
+ def _build_finished_2(self, results, bs, builderName):
+ self.results[builderName][0] = results
+ d = bs.callRemote("getText")
+ d.addCallback(self._build_finished_3, builderName)
+ return d
+ def _build_finished_3(self, text, builderName):
+ self.results[builderName][1] = text
+
+ self.outstanding.remove(builderName)
+ if not self.outstanding:
+ # all done
+ return self.statusDone()
+
+ def printStatus(self):
+ names = self.buildRequests.keys()
+ names.sort()
+ for n in names:
+ if n not in self.outstanding:
+ # the build is finished, and we have results
+ code,text = self.results[n]
+ t = builder.Results[code]
+ if text:
+ t += " (%s)" % " ".join(text)
+ elif self.builds[n]:
+ t = self.currentStep[n] or "building"
+ if self.ETA[n]:
+ t += " [ETA %ds]" % (self.ETA[n] - now())
+ else:
+ t = "no build"
+ self.announce("%s: %s" % (n, t))
+ self.announce("")
+
+ def statusDone(self):
+ self.printloop.stop()
+ print "All Builds Complete"
+ # TODO: include a URL for all failing builds
+ names = self.buildRequests.keys()
+ names.sort()
+ happy = True
+ for n in names:
+ code,text = self.results[n]
+ t = "%s: %s" % (n, builder.Results[code])
+ if text:
+ t += " (%s)" % " ".join(text)
+ print t
+ if self.results[n] != builder.SUCCESS:
+ happy = False
+
+ if happy:
+ self.exitcode = 0
+ else:
+ self.exitcode = 1
+ self.running.callback(self.exitcode)
+
def announce(self, message):
if not self.quiet:
print message
@@ -305,19 +441,20 @@
# we can't do spawnProcess until we're inside reactor.run(), so get
# funky
print "using '%s' connect method" % self.connect
+ self.exitcode = 0
d = defer.Deferred()
d.addCallback(lambda res: self.createJob())
d.addCallback(lambda res: self.announce("job created"))
d.addCallback(lambda res: self.deliverJob())
d.addCallback(lambda res: self.announce("job has been delivered"))
d.addCallback(lambda res: self.getStatus())
- d.addCallback(lambda res: self.announce("status object acquired"))
d.addErrback(log.err)
d.addCallback(self.cleanup)
d.addCallback(lambda res: reactor.stop())
reactor.callLater(0, d.callback, None)
reactor.run()
+ sys.exit(self.exitcode)
def logErr(self, why):
log.err(why)
@@ -325,7 +462,6 @@
print why
def cleanup(self, res=None):
- print "cleaning up"
if self.buildsetStatus:
self.buildsetStatus.broker.transport.loseConnection()
More information about the Commits
mailing list