[Buildbot-commits] buildbot/buildbot/status/web base.py, 1.5, 1.6 baseweb.py, 1.12, 1.13 build.py, 1.6, 1.7 builder.py, 1.5, 1.6
Brian Warner
warner at users.sourceforge.net
Sun Aug 12 07:44:08 UTC 2007
Update of /cvsroot/buildbot/buildbot/buildbot/status/web
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv28323/buildbot/status/web
Modified Files:
base.py baseweb.py build.py builder.py
Log Message:
[project @ web status: improve OneLinePerBuild, also builder and build pages]
Original author: warner at lothar.com
Date: 2007-08-12 07:38:33+00:00
Index: base.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/web/base.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- base.py 1 Aug 2007 22:09:19 -0000 1.5
+++ base.py 12 Aug 2007 07:44:05 -0000 1.6
@@ -2,7 +2,7 @@
from zope.interface import Interface
from twisted.web import html, resource
from buildbot.status import builder
-
+from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, EXCEPTION
class ITopBox(Interface):
@@ -21,11 +21,18 @@
class IHTMLLog(Interface):
pass
+css_classes = {SUCCESS: "success",
+ WARNINGS: "warnings",
+ FAILURE: "failure",
+ EXCEPTION: "exception",
+ }
+
ROW_TEMPLATE = '''
<div class="row">
<span class="label">%(label)s</span>
<span class="field">%(field)s</span>
-</div>'''
+</div>
+'''
def make_row(label, field):
"""Create a name/value row for the HTML.
Index: baseweb.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/web/baseweb.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- baseweb.py 2 Aug 2007 08:32:10 -0000 1.12
+++ baseweb.py 12 Aug 2007 07:44:06 -0000 1.13
@@ -9,9 +9,8 @@
from twisted.spread import pb
from buildbot.interfaces import IControl, IStatusReceiver
-from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, EXCEPTION
-from buildbot.status.web.base import HtmlResource
+from buildbot.status.web.base import HtmlResource, css_classes
from buildbot.status.web.waterfall import WaterfallStatusResource
from buildbot.status.web.changes import ChangesResource
from buildbot.status.web.builder import BuildersResource
@@ -63,21 +62,17 @@
class OneLineMixin:
- def make_line(self, req, status, build):
- css_classes = {SUCCESS: "success",
- WARNINGS: "warnings",
- FAILURE: "failure",
- EXCEPTION: "exception",
- }
-
+ def make_line(self, req, build):
builder_name = build.getBuilder().getName()
results = build.getResults()
try:
rev = build.getProperty("got_revision")
+ if rev is None:
+ rev = "??"
except KeyError:
rev = "??"
if len(rev) > 20:
- rev = "?too-long?"
+ rev = "version is too-long"
root = self.path_to_root(req)
values = {'class': css_classes[results],
'builder_name': builder_name,
@@ -86,16 +81,18 @@
'buildurl': (root +
"builders/%s/builds/%d" % (builder_name,
build.getNumber())),
+ 'builderurl': (root + "builders/%s" % builder_name),
'rev': rev,
- 'time': time.strftime("%H:%M:%S",
+ 'time': time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(build.getTimes()[0])),
}
fmt = ('<div>'
- '%(time)s: '
- '<a href="%(buildurl)s">Build #%(buildnum)d</a> of '
- '%(builder_name)s [%(rev)s]: '
- '<span class="%(class)s">%(results)s</span>'
+ '<font size="-1">(%(time)s)</font> '
+ '<a href="%(builderurl)s">%(builder_name)s</a> '
+ 'rev=[%(rev)s]: '
+ '<span class="%(class)s">%(results)s</span> '
+ '<a href="%(buildurl)s">#%(buildnum)d</a> '
'</div>\n')
data = fmt % values
return data
@@ -126,15 +123,21 @@
builders = req.args.get("builder", [])
branches = req.args.get("branch", [])
- builds = getLastNBuilds(status, numbuilds, builders, branches)
+ g = status.generateFinishedBuilds(builders, branches, numbuilds)
+
data = ""
- data += "<h1>Last %d builds</h1>" % min(self.numbuilds, len(builds))
+
+ # really this is "up to %d builds"
+ data += "<h1>Last %d finished builds</h1>\n" % numbuilds
if builders:
- data += ("<p>of builders: %s</p>" % (", ".join(builders)))
- for build in reversed(builds):
- data += self.make_line(req, status, build)
- if not builds:
- data += "<div>No matching builds found</div>"
+ data += ("<p>of builders: %s</p>\n" % (", ".join(builders)))
+
+ got = 0
+ for build in g:
+ got += 1
+ data += self.make_line(req, build)
+ if not got:
+ data += "<div>No matching builds found</div>\n"
return data
@@ -153,22 +156,19 @@
status = self.getStatus(req)
numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0])
branches = req.args.get("branch", [])
- # walk backwards through all builds of a single builder
- # islice is cool but not exactly what we need here
- #events = itertools.islice(b.eventGenerator(), self.numbuilds)
+ # walk backwards through all builds of a single builder
+ g = self.builder.generateFinishedBuilds(branches, numbuilds)
data = ""
- data += "<h1>Last %d builds of builder: %s</h1>" % (self.numbuilds,
- self.builder_name)
- i = 1
- while i < numbuilds:
- build = self.builder.getBuild(-i)
- if not build:
- break
- i += 1
-
- data += self.make_line(req, status, build)
+ data += ("<h1>Last %d builds of builder: %s</h1>\n" %
+ (numbuilds, self.builder_name))
+ got = 0
+ for build in g:
+ got += 1
+ data += self.make_line(req, build)
+ if not got:
+ data += "<div>No matching builds found</div>\n"
return data
Index: build.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/web/build.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- build.py 1 Aug 2007 23:30:13 -0000 1.6
+++ build.py 12 Aug 2007 07:44:06 -0000 1.7
@@ -3,9 +3,9 @@
from twisted.web.util import Redirect, DeferredResource
from twisted.internet import defer, reactor
-import urllib
+import urllib, time
from twisted.python import log
-from buildbot.status.web.base import HtmlResource, make_row
+from buildbot.status.web.base import HtmlResource, make_row, css_classes
from buildbot.status.web.tests import TestsResource
from buildbot.status.web.step import StepsResource
@@ -30,10 +30,40 @@
projectName)
# the color in the following line gives python-mode trouble
builder_name = b.getBuilder().getName()
- data += ("<h1><a href=\"../../%s\">Builder %s</a>: Build #%d</h1>\n"
- % (urllib.quote(builder_name), builder_name, b.getNumber()))
- data += "<h2>Buildslave:</h2>\n %s\n" % html.escape(b.getSlavename())
- data += "<h2>Reason:</h2>\n%s\n" % html.escape(b.getReason())
+ data += ("<h1><a href=\"../..\">Builder %s</a>: Build #%d</h1>\n"
+ % (builder_name, b.getNumber()))
+
+ if not b.isFinished():
+ data += "<h2>Build In Progress</h2>"
+ when = b.getETA()
+ if when is not None:
+ when_time = time.strftime("%H:%M:%S",
+ time.localtime(time.time() + when))
+ data += "<div>ETA %ds (%s)</div>\n" % (when, when_time)
+
+ if self.build_control is not None:
+ stopURL = urllib.quote(req.childLink("stop"))
+ data += """
+ <form action="%s" class='command stopbuild'>
+ <p>To stop this build, fill out the following fields and
+ push the 'Stop' button</p>\n""" % stopURL
+ data += make_row("Your name:",
+ "<input type='text' name='username' />")
+ data += make_row("Reason for stopping build:",
+ "<input type='text' name='comments' />")
+ data += """<input type="submit" value="Stop Builder" />
+ </form>
+ """
+
+ if b.isFinished():
+ results = b.getResults()
+ data += "<h2>Results:</h2>\n"
+ text = " ".join(b.getText())
+ data += '<span class="%s">%s</span>\n' % (css_classes[results],
+ text)
+ if b.getTestResults():
+ url = req.childLink("tests")
+ data += "<h3><a href=\"%s\">test results</a></h3>\n" % url
ss = b.getSourceStamp()
data += "<h2>SourceStamp:</h2>\n"
@@ -49,28 +79,61 @@
if (ss.branch is None and ss.revision is None and ss.patch is None
and not ss.changes):
data += " <li>build of most recent revision</li>\n"
+ got_revision = None
+ try:
+ got_revision = b.getProperty("got_revision")
+ except KeyError:
+ pass
+ if got_revision:
+ if len(got_revision) > 40:
+ got_revision = "[revision string too long]"
+ data += " <li>Got Revision: %s</li>\n" % got_revision
data += " </ul>\n"
- if b.isFinished():
- data += "<h2>Results:</h2>\n"
- data += " ".join(b.getText()) + "\n"
- if b.getTestResults():
- url = req.childLink("tests")
- data += "<h3><a href=\"%s\">test results</a></h3>\n" % url
+
+ # TODO: turn this into a table, or some other sort of definition-list
+ # that doesn't take up quite so much vertical space
+ data += "<h2>Buildslave:</h2>\n %s\n" % html.escape(b.getSlavename())
+ data += "<h2>Reason:</h2>\n%s\n" % html.escape(b.getReason())
+
+ data += "<h2>Steps and Logfiles:</h2>\n"
+ if b.getLogs():
+ data += "<ol>\n"
+ for s in b.getSteps():
+ name = s.getName()
+ data += (" <li><a href=\"%s\">%s</a> [%s]\n"
+ % (req.childLink("steps/%s" % urllib.quote(name)),
+ name,
+ " ".join(s.getText())))
+ if s.getLogs():
+ data += " <ol>\n"
+ for logfile in s.getLogs():
+ logname = logfile.getName()
+ logurl = req.childLink("steps/%s/logs/%s" %
+ (urllib.quote(name),
+ urllib.quote(logname)))
+ data += (" <li><a href=\"%s\">%s</a></li>\n" %
+ (logurl, logfile.getName()))
+ data += " </ol>\n"
+ data += " </li>\n"
+ data += "</ol>\n"
+
+ data += "<h2>Blamelist:</h2>\n"
+ if list(b.getResponsibleUsers()):
+ data += " <ol>\n"
+ for who in b.getResponsibleUsers():
+ data += " <li>%s</li>\n" % html.escape(who)
+ data += " </ol>\n"
else:
- data += "<h2>Build In Progress</h2>"
- if self.build_control is not None:
- stopURL = urllib.quote(req.childLink("stop"))
- data += """
- <form action="%s" class='command stopbuild'>
- <p>To stop this build, fill out the following fields and
- push the 'Stop' button</p>\n""" % stopURL
- data += make_row("Your name:",
- "<input type='text' name='username' />")
- data += make_row("Reason for stopping build:",
- "<input type='text' name='comments' />")
- data += """<input type="submit" value="Stop Builder" />
- </form>
- """
+ data += "<div>no responsible users</div>\n"
+
+ if ss.changes:
+ data += "<h2>All Changes</h2>\n"
+ data += "<ol>\n"
+ for c in ss.changes:
+ data += "<li>" + c.asHTML() + "</li>\n"
+ data += "</ol>\n"
+ #data += html.PRE(b.changesText()) # TODO
+
if b.isFinished() and self.builder_control is not None:
data += "<h3>Resubmit Build:</h3>\n"
@@ -98,41 +161,6 @@
data += '<input type="submit" value="Rebuild" />\n'
data += '</form>\n'
- data += "<h2>Steps and Logfiles:</h2>\n"
- if b.getLogs():
- data += "<ol>\n"
- for s in b.getSteps():
- name = s.getName()
- data += (" <li><a href=\"%s\">%s</a> [%s]\n"
- % (req.childLink("steps/%s" % urllib.quote(name)),
- name,
- " ".join(s.getText())))
- if s.getLogs():
- data += " <ol>\n"
- for logfile in s.getLogs():
- logname = logfile.getName()
- logurl = req.childLink("steps/%s/logs/%s" %
- (urllib.quote(name),
- urllib.quote(logname)))
- data += (" <li><a href=\"%s\">%s</a></li>\n" %
- (logurl, logfile.getName()))
- data += " </ol>\n"
- data += " </li>\n"
- data += "</ol>\n"
-
- data += ("<h2>Blamelist:</h2>\n"
- " <ol>\n")
- for who in b.getResponsibleUsers():
- data += " <li>%s</li>\n" % html.escape(who)
- data += (" </ol>\n"
- "<h2>All Changes</h2>\n")
- changes = ss.changes
- if changes:
- data += "<ol>\n"
- for c in changes:
- data += "<li>" + c.asHTML() + "</li>\n"
- data += "</ol>\n"
- #data += html.PRE(b.changesText()) # TODO
return data
def stop(self, req):
Index: builder.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/web/builder.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- builder.py 2 Aug 2007 00:27:04 -0000 1.5
+++ builder.py 12 Aug 2007 07:44:06 -0000 1.6
@@ -3,10 +3,10 @@
from twisted.web import html, static
from twisted.web.util import Redirect
-import re, urllib
+import re, urllib, time
from twisted.python import log
from buildbot import interfaces
-from buildbot.status.web.base import HtmlResource, make_row
+from buildbot.status.web.base import HtmlResource, make_row, css_classes
from buildbot.process.base import BuildRequest
from buildbot.sourcestamp import SourceStamp
@@ -21,6 +21,27 @@
self.builder_status = builder_status
self.builder_control = builder_control
+ def build_line(self, build, req):
+ buildnum = build.getNumber()
+ buildurl = "builds/%d" % buildnum
+ data = '<a href="%s">#%d</a> ' % (buildurl, buildnum)
+ when = build.getETA()
+ if when is not None:
+ when_time = time.strftime("%H:%M:%S",
+ time.localtime(time.time() + when))
+ data += "ETA %ds (%s) " % (when, when_time)
+ data += "[%s]" % build.getCurrentStep().getName()
+ return data
+
+ def build_finished_line(self, build, req):
+ buildnum = build.getNumber()
+ buildurl = "builds/%d" % buildnum
+ results = build.getResults()
+ text = " ".join(build.getText())
+ data = '<a href="%s">#%d</a> ' % (buildurl, buildnum)
+ data += '<span class="%s">%s</span>' % (css_classes[results], text)
+ return data
+
def body(self, req):
b = self.builder_status
control = self.builder_control
@@ -31,12 +52,37 @@
buildbotURL = status.getBuildbotURL()
projectName = status.getProjectName()
+
data = "<a href=\"%s\">%s</a>\n" % (buildbotURL, projectName)
- data += make_row("Builder:", html.escape(b.getName()))
- b1 = b.getBuild(-1)
- if b1 is not None:
- data += make_row("Current/last build:", str(b1.getNumber()))
- data += "\n<br />BUILDSLAVES<br />\n"
+
+ data += "<h1>Builder: %s</h1>\n" % html.escape(b.getName())
+
+ # the first section shows builds which are currently running, if any.
+
+ current = b.getCurrentBuilds()
+ if current:
+ data += "<h2>Currently Building:</h2>\n"
+ data += "<ul>\n"
+ for build in current:
+ data += " <li>" + self.build_line(build, req) + "</li>\n"
+ data += "</ul>\n"
+ else:
+ data += "<h2>no current builds</h2>\n"
+
+ # Then a section with the last 5 builds, with the most recent build
+ # distinguished from the rest.
+
+ data += "<h2>Recent Builds:</h2>\n"
+ data += "<ul>\n"
+ for i,build in enumerate(b.generateFinishedBuilds(num_builds=5)):
+ data += " <li>" + self.build_finished_line(build, req) + "</li>\n"
+ if i == 0:
+ data += "<br />\n" # separator
+ # TODO: or empty list?
+ data += "</ul>\n"
+
+
+ data += "<h2>Buildslaves:</h2>\n"
data += "<ol>\n"
for slave in slaves:
data += "<li><b>%s</b>: " % html.escape(slave.getName())
More information about the Commits
mailing list