[Buildbot-commits] buildbot/buildbot/scripts runner.py,1.31,1.32 tryclient.py,1.2,1.3
Brian Warner
warner at users.sourceforge.net
Thu Aug 11 08:22:19 UTC 2005
Update of /cvsroot/buildbot/buildbot/buildbot/scripts
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1125/buildbot/scripts
Modified Files:
runner.py tryclient.py
Log Message:
Revision: arch at buildbot.sf.net--2004/buildbot--dev--0--patch-277
Creator: Brian Warner <warner at monolith.lothar.com>
make 'try' actually work, mostly
* docs/buildbot.texinfo (try): add --port argument to PB style
* buildbot/scripts/tryclient.py (SourceStampExtractor): return an
actual SourceStamp. Still need to extract a branch name, somehow.
(Try): finish implementing the try client side, still need a UI
for specifying which builders to use
(Try.getopt): factor our options/config-file reading
* buildbot/test/test_scheduler.py (Scheduling.testTryUserpass):
test it
* buildbot/test/test_vc.py: match SourceStampExtractor change
* buildbot/scripts/runner.py (Options.opt_verbose): --verbose
causes the twisted log to be sent to stderr
* buildbot/scheduler.py (Try_Userpass): implement the PB style
--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: runner.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/scripts/runner.py,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- runner.py 10 Aug 2005 08:15:44 -0000 1.31
+++ runner.py 11 Aug 2005 08:22:16 -0000 1.32
@@ -571,9 +571,9 @@
"the directory (on the tryhost) where tryjobs are deposited"],
["username", "u", None, "Username performing the trial build"],
# for PB, use --master, --username, and --passwd
- ["passwd", None, None, "password for PB authentication"],
["master", "m", None,
"Location of the buildmaster's PBListener (host:port)"],
+ ["passwd", None, None, "password for PB authentication"],
["vc", None, None,
"The VC system in use, one of: cvs,svn,tla,baz,darcs"],
@@ -588,7 +588,8 @@
def doTry(config):
from buildbot.scripts import tryclient
- tryclient.doTry(config)
+ t = tryclient.Try(config)
+ t.run()
class TryServerOptions(usage.Options):
optParameters = [
@@ -599,8 +600,8 @@
jobdir = os.path.expanduser(config["jobdir"])
job = sys.stdin.read()
# now do a 'safecat'-style write to jobdir/tmp, then move atomically to
- # jobdir/new . I'm just going to MD5 the contents and prepend a
- # timestamp.
+ # jobdir/new . Rather than come up with a unique name randomly, I'm just
+ # going to MD5 the contents and prepend a timestamp.
timestring = "%d" % time.time()
jobhash = md5.new(job).hexdigest()
fn = "%s-%s" % (timestring, jobhash)
@@ -650,6 +651,10 @@
print "Buildbot version: %s" % buildbot.version
usage.Options.opt_version(self)
+ def opt_verbose(self):
+ from twisted.python import log
+ log.startLogging(sys.stderr)
+
def postOptions(self):
if not hasattr(self, 'subOptions'):
raise usage.UsageError("must specify a command")
Index: tryclient.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/scripts/tryclient.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- tryclient.py 10 Aug 2005 08:15:44 -0000 1.2
+++ tryclient.py 11 Aug 2005 08:22:16 -0000 1.3
@@ -1,17 +1,23 @@
# -*- test-case-name: buildbot.test.test_scheduler,buildbot.test.test_vc -*-
import os, re
-from twisted.internet import utils, protocol, defer
+from twisted.internet import utils, protocol, defer, reactor
+from twisted.spread import pb
+from twisted.cred import credentials
+from twisted.python import log
+from buildbot.sourcestamp import SourceStamp
from buildbot.scripts import runner
class SourceStampExtractor:
+ branch = None
def __init__(self, treetop):
self.treetop = treetop
def do(self, cmd):
return utils.getProcessOutput(cmd[0], cmd[1:], env=os.environ,
path=self.treetop)
def get(self):
+ """Return a Deferred that fires with a SourceStamp instance."""
d = self.getBaseRevision()
d.addCallback(self.getPatch)
d.addCallback(self.done)
@@ -19,7 +25,9 @@
def readPatch(self, res, patchlevel):
self.patch = (patchlevel, res)
def done(self, res):
- return (self.baserev, self.patch)
+ # TODO: figure out the branch too
+ ss = SourceStamp(self.branch, self.baserev, self.patch)
+ return ss
class SVNExtractor(SourceStampExtractor):
patchlevel = 0
@@ -115,7 +123,7 @@
def ns(s):
return "%d:%s," % (len(s), s)
-def createJob(bsid, branch, baserev, patchlevel, diff, builderNames):
+def createJobfile(bsid, branch, baserev, patchlevel, diff, builderNames):
job = ""
job += ns("1")
job += ns(bsid)
@@ -147,54 +155,139 @@
self.d.callback((sig, rc))
class Try:
- def run(self, config):
- opts = runner.loadOptions()
+ buildsetStatus = None
+ quiet = False
+
+ def __init__(self, config):
+ self.config = config
+ self.opts = runner.loadOptions()
+ self.connect = self.getopt('connect', 'try_connect')
+ print "using '%s' connect method" % self.connect
+ self.builderNames = ["a", "b"] # TODO: add UI for this
+
+ def getopt(self, config_name, options_name, default=None):
+ value = self.config.get(config_name)
+ if value is None:
+ value = self.opts.get(options_name)
+ if value is None:
+ value = default
+ assert value is not None
+ return value
+
+ def createJob(self):
+ # returns a Deferred which fires when the job parameters have been
+ # created
+ config = self.config
+ opts = self.opts
+ self.bsid = "buildsetID" # TODO: generate a random (unique) string
+
# common options
- vc = config.get("vc", opts.get("try_vc"))
+ vc = self.getopt("vc", "try_vc")
if vc in ("cvs", "svn"):
# we need to find the tree-top
- topdir = config.get("try_topdir", opts.get("try_topdir"))
+ topdir = self.getopt("try_topdir", "try_topdir")
if topdir:
treedir = os.path.expanduser(topdir)
else:
- topfile = config.get("try-topfile", opts.get("try_topfile"))
+ topfile = self.getopt("try-topfile", "try_topfile")
treedir = getTopdir(topfile)
else:
treedir = os.getcwd()
- ss = getSourceStamp(vc, treedir)
- builderNames = [] # TODO??
-
- wait = bool(config.get("wait", opts.get("try_wait")))
- bsid = "buildsetID" # TODO: generate a random (unique) string
+ d = getSourceStamp(vc, treedir)
+ d.addCallback(self._createJob_1)
+ return d
+ def _createJob_1(self, ss):
+ self.sourcestamp = ss
+ if self.connect == "ssh":
+ patchlevel, diff = ss.patch
+ self.jobfile = createJobfile(bsid, ss.branch or "", ss.revision,
+ patchlevel, diff,
+ self.builderNames)
+ def deliverJob(self):
+ # returns a Deferred that fires when the job has been delivered
+ config = self.config
+ opts = self.opts
- connect = config.get('connect', opts.get('try_connect'))
- if connect == "ssh":
- tryhost = config.get("tryhost", opts.get("try_host"))
- tryuser = config.get("username", opts.get("try_username"))
- trydir = config.get("trydir", opts.get("try_dir"))
+ if self.connect == "ssh":
+ tryhost = self.getopt("tryhost", "try_host")
+ tryuser = self.getopt("username", "try_username")
+ trydir = self.getopt("trydir", "try_dir")
- patchlevel, diff = ss.patch
- job = createJob(bsid, ss.branch or "", ss.revision, patchlevel, diff,
- builderNames)
argv = ["ssh", "-l", tryuser, tryhost,
"buildbot", "tryserver", trydir]
# now run this command and feed the contents of 'job' into stdin
- pp = RemoteTryPP(job)
+ pp = RemoteTryPP(self.jobfile)
p = reactor.spawnProcess(pp, argv[0], argv, os.environ)
d = pp.d
return d
+ if self.connect == "pb":
+ user = self.getopt("username", "try_username")
+ passwd = self.getopt("passwd", "try_password")
+ master = self.getopt("master", "try_master")
+ tryhost, tryport = master.split(":")
+ tryport = int(tryport)
+ f = pb.PBClientFactory()
+ d = f.login(credentials.UsernamePassword(user, passwd))
+ reactor.connectTCP(tryhost, tryport, f)
+ d.addCallback(self._deliverJob_pb)
+ return d
+ raise RuntimeError("unknown connecttype '%s', should be 'ssh' or 'pb'"
+ % self.connect)
- def done(self, res):
- reactor.stop()
+ def _deliverJob_pb(self, remote):
+ ss = self.sourcestamp
+ d = remote.callRemote("try",
+ ss.branch, ss.revision, ss.patch,
+ self.builderNames)
+ d.addCallback(self._deliverJob_pb2)
+ return d
+ def _deliverJob_pb2(self, status):
+ self.buildsetStatus = status
+ return status
+ def getStatus(self):
+ # 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
+ pass
+
+ def announce(self, message):
+ if not self.quiet:
+ print message
+
+ def run(self):
+ # we can't do spawnProcess until we're inside reactor.run(), so get
+ # funky
+ 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()
+
+ def logErr(self, why):
+ log.err(why)
+ print "error during 'try' processing"
+ print why
+
+ def cleanup(self, res=None):
+ print "cleaning up"
+ if self.buildsetStatus:
+ self.buildsetStatus.broker.transport.loseConnection()
-def doTry(config):
- t = Try()
- d = t.run(config)
- d.addBoth(t.done)
- reactor.run()
More information about the Commits
mailing list