[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