jhbuild r2271 - in trunk: buildbot/public_html jhbuild/buildbot jhbuild/buildbot/status/web



Author: fpeters
Date: Sun Aug 17 16:11:15 2008
New Revision: 2271
URL: http://svn.gnome.org/viewvc/jhbuild?rev=2271&view=rev

Log:
* buildbot/public_html/lgo.css,
jhbuild/buildbot/factory.py,
jhbuild/buildbot/status/web/__init__.py,
jhbuild/buildbot/status/web/build.py,
jhbuild/buildbot/status/web/builder.py,
jhbuild/buildbot/status/web/logs.py,
jhbuild/buildbot/status/web/step.py,
jhbuild/buildbot/status/web/waterfall.py,
jhbuild/buildbot/steps.py: customized most buildbot pages; include test
success details in waterfall views.



Added:
   trunk/jhbuild/buildbot/status/web/build.py
   trunk/jhbuild/buildbot/status/web/builder.py
   trunk/jhbuild/buildbot/status/web/logs.py
   trunk/jhbuild/buildbot/status/web/step.py
Modified:
   trunk/buildbot/public_html/lgo.css
   trunk/jhbuild/buildbot/factory.py
   trunk/jhbuild/buildbot/status/web/__init__.py
   trunk/jhbuild/buildbot/status/web/waterfall.py
   trunk/jhbuild/buildbot/steps.py

Modified: trunk/buildbot/public_html/lgo.css
==============================================================================
--- trunk/buildbot/public_html/lgo.css	(original)
+++ trunk/buildbot/public_html/lgo.css	Sun Aug 17 16:11:15 2008
@@ -245,11 +245,11 @@
 	color: #888;
 }
 
-td.success {
+.success {
 	background: #8f8;
 }
 
-td.failure {
+.failure {
 	background: #f88;
 }
 td.running,
@@ -331,3 +331,19 @@
 div.changeset ul ul {
 	padding-left: 1em;
 }
+
+ul#tests-summary {
+	margin: 1em;
+	padding: 0;
+	list-style: none;
+	-webkit-column-width: 15em;
+	-moz-column-width: 15em;
+	column-width: 15em;
+	-webkit-column-gap: 1em;
+	-moz-column-gap: 1em;
+	column-gap: 1em;
+}
+
+ul#tests-summary li {
+	margin-bottom: 1ex;
+}

Modified: trunk/jhbuild/buildbot/factory.py
==============================================================================
--- trunk/jhbuild/buildbot/factory.py	(original)
+++ trunk/jhbuild/buildbot/factory.py	Sun Aug 17 16:11:15 2008
@@ -18,7 +18,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
 from buildbot.process import factory
-from steps import JHBuildSource, JHBuildCommand, JHBuildModulePathTestCommand, JHBuildModulePathCommand
+from steps import JHBuildSource, JHBuildCommand, JHBuildModulePathCommand, JHBuildCheckCommand
 
 class JHBuildFactory(factory.BuildFactory):
     module = None
@@ -35,7 +35,7 @@
     def getSteps(self):
         self.addStep(JHBuildSource, moduleset=self.moduleset, module=self.module)
         self.addStep(JHBuildCommand, stage='build', moduleset=self.moduleset, module=self.module)
-        self.addStep(JHBuildCommand, stage='check', moduleset=self.moduleset, module=self.module)
+        self.addStep(JHBuildCheckCommand, moduleset=self.moduleset, module=self.module)
         #self.addStep(JHBuildModulePathTestCommand, moduleset=self.moduleset, module=self.module, action=['make-check.sh'], haltOnFailure = False)
         #self.addStep(JHBuildModulePathCommand, moduleset=self.moduleset, module=self.module, action=['module-reports.sh'], haltOnFailure = False)
 

Modified: trunk/jhbuild/buildbot/status/web/__init__.py
==============================================================================
--- trunk/jhbuild/buildbot/status/web/__init__.py	(original)
+++ trunk/jhbuild/buildbot/status/web/__init__.py	Sun Aug 17 16:11:15 2008
@@ -27,6 +27,7 @@
 
 from waterfall import JhWaterfallStatusResource
 from changes import  ChangesResource
+from builder import JhBuildersResource
 
 
 def content(self, request):
@@ -112,21 +113,21 @@
                         lastbuild = bt
 
                 if lastbuild == 'successful':
-                    class_ = build_get_class(builder.getLastFinishedBuild())
-                    lastbuild_label = 'Success'
-                elif lastbuild == 'failed':
-                    lastbuild_label = 'Failed'
                     last_build = builder.getLastFinishedBuild()
                     class_ = build_get_class(last_build)
+                    lastbuild_label = 'Success'
                     if last_build:
-                        # use a different class/label if the failure is
-                        # 'make check'
+                        # use a different class/label if make check failed
                         steps = last_build.getSteps()
-                        if steps and steps[-1].results == FAILURE and \
-                                steps[-1].text[0].endswith(' check'):
+                        print 'XXX:', [x.__dict__ for x in steps]
+                        if steps and steps[-1].results == WARNINGS:
                             # make check failed
                             class_ = 'failedchecks'
                             lastbuild_label = 'Failed Checks'
+                elif lastbuild == 'failed':
+                    lastbuild_label = 'Failed'
+                    last_build = builder.getLastFinishedBuild()
+                    class_ = build_get_class(last_build)
                 else:
                     class_ = ''
                     lastbuild_label = lastbuild
@@ -173,6 +174,7 @@
 
         # set custom changes pages
         self.putChild('changes', ChangesResource())
+        self.putChild('builders', JhBuildersResource())
 
     def setupSite(self):
         WebStatus.setupSite(self)

Added: trunk/jhbuild/buildbot/status/web/build.py
==============================================================================
--- (empty file)
+++ trunk/jhbuild/buildbot/status/web/build.py	Sun Aug 17 16:11:15 2008
@@ -0,0 +1,204 @@
+# jhbuild - a build script for GNOME 1.x and 2.x
+# Copyright (C) 2008  Frederic Peters
+#
+#   build.py: custom build pages
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import urllib, time
+
+from twisted.web import html
+from twisted.web.util import Redirect
+
+from buildbot.status.web.build import BuildsResource, StatusResourceBuild
+from buildbot.status.web.base import HtmlResource, make_row, make_stop_form, css_classes
+
+from step import JhStepsResource
+
+
+class JhStatusResourceBuild(StatusResourceBuild):
+    def getTitle(self, request):
+        buildbot_service = request.site.buildbot_service
+        builder_name = self.build_status.getBuilder().getName()
+        for slave in buildbot_service.slaves:
+            if builder_name.endswith(slave):
+                slave_name = slave
+                module_name = builder_name[:-len(slave)-1]
+                break
+        else:
+            slave_name = None
+            module_name = None
+        status = self.getStatus(request)
+        p = status.getProjectName()
+        if slave_name:
+            return '%s - %s - build #%s @ %s' % (
+                    p, module_name, self.build_status.getNumber(), slave_name)
+        return '%s - %s' % (p, builder_name)
+
+    def body(self, req):
+        b = self.build_status
+        status = self.getStatus(req)
+        projectURL = status.getProjectURL()
+        projectName = status.getProjectName()
+        data = ''
+
+        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 += make_stop_form(stopURL)
+
+        if b.isFinished():
+            results = b.getResults()
+            data += "<h2>Results: "
+            text = " ".join(b.getText())
+            data += '<span class="%s">%s</span>' % (css_classes[results], text)
+            data += '</h2>\n'
+            if b.getTestResults():
+                url = req.childLink("tests")
+                data += "<h3><a href=\"%s\">test results</a></h3>\n" % url
+
+        data += '<ul>\n'
+        ss = b.getSourceStamp()
+        data += " <li>SourceStamp: "
+        data += " <ul>\n"
+        if ss.branch:
+            data += "  <li>Branch: %s</li>\n" % html.escape(ss.branch)
+        if ss.revision:
+            data += "  <li>Revision: %s</li>\n" % html.escape(str(ss.revision))
+        if ss.patch:
+            data += "  <li>Patch: YES</li>\n" # TODO: provide link to .diff
+        if ss.changes:
+            data += "  <li>Changes: see below</li>\n"
+        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:
+            got_revision = str(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"
+
+        data += "<li>Buildslave: %s</li>\n" % html.escape(b.getSlavename())
+        data += "<li>Reason: %s</li>\n" % html.escape(b.getReason())
+
+        if b.getLogs():
+            data += "<li>Steps and Logfiles:\n"
+            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 += "  <ul>\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 += "  </ul>\n"
+                data += " </li>\n"
+            data += "</ol>\n"
+            data += "</li>\n"
+
+        data += "<li>Blamelist: "
+        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 += "no responsible users\n"
+        data += '</li>'
+
+        if ss.changes:
+            data += "<li>All Changes<\n"
+            data += "<ol>\n"
+            for c in ss.changes:
+                data += "<li>" + c.asHTML() + "</li>\n"
+            data += "</ol></li>\n"
+
+        data += '</ul>'
+
+        if b.isFinished() and self.builder_control is not None:
+            data += "<h3>Resubmit Build:</h3>\n"
+            # can we rebuild it exactly?
+            exactly = (ss.revision is not None) or b.getChanges()
+            if exactly:
+                data += ("<p>This tree was built from a specific set of \n"
+                         "source files, and can be rebuilt exactly</p>\n")
+            else:
+                data += ("<p>This tree was built from the most recent "
+                         "revision")
+                if ss.branch:
+                    data += " (along some branch)"
+                data += (" and thus it might not be possible to rebuild it \n"
+                         "exactly. Any changes that have been committed \n"
+                         "after this build was started <b>will</b> be \n"
+                         "included in a rebuild.</p>\n")
+            rebuildURL = urllib.quote(req.childLink("rebuild"))
+            data += '<form action="%s" class="command rebuild">\n' % rebuildURL
+            data += '<label>Your name: <input type="text" name="username"/></label> '
+            data += '<label>Reason for re-running build: '\
+                    '<input size="50" type="text" name="comments"/></label> '
+            data += '<input type="submit" value="Rebuild" />\n'
+            data += '</form>\n'
+
+        data += '</div>\n'
+
+        return data
+
+    def getChild(self, path, req):
+        if path == 'steps':
+            return JhStepsResource(self.build_status)
+        return StatusResourceBuild.getChild(self, path, req)
+
+
+class JhBuildsResource(BuildsResource):
+    def getChild(self, path, req):
+        if path == '':
+            return Redirect('..')
+        try:
+            num = int(path)
+        except ValueError:
+            num = None
+        if num is not None:
+            build_status = self.builder_status.getBuild(num)
+            if build_status:
+                if self.builder_control:
+                    build_control = self.builder_control.getBuild(num)
+                else:
+                    build_control = None
+                return JhStatusResourceBuild(build_status, build_control,
+                                           self.builder_control)
+
+        return HtmlResource.getChild(self, path, req)
+

Added: trunk/jhbuild/buildbot/status/web/builder.py
==============================================================================
--- (empty file)
+++ trunk/jhbuild/buildbot/status/web/builder.py	Sun Aug 17 16:11:15 2008
@@ -0,0 +1,135 @@
+# jhbuild - a build script for GNOME 1.x and 2.x
+# Copyright (C) 2008  Frederic Peters
+#
+#   build.py: custom builder pages
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import urllib, time
+
+from twisted.web import html
+from twisted.web.util import Redirect
+
+from buildbot.status.web.builder import BuildersResource, StatusResourceBuilder
+from build import JhBuildsResource
+
+class JhStatusResourceBuilder(StatusResourceBuilder):
+    def getTitle(self, request):
+        buildbot_service = request.site.buildbot_service
+        builder_name = self.builder_status.getName()
+        for slave in buildbot_service.slaves:
+            if builder_name.endswith(slave):
+                slave_name = slave
+                module_name = builder_name[:-len(slave)-1]
+                break
+        else:
+            slave_name = None
+            module_name = None
+        status = self.getStatus(request)
+        p = status.getProjectName()
+        if slave_name:
+            return '%s - %s @ %s' % (
+                    p, module_name, slave_name)
+        return '%s - %s' % (p, builder_name)
+
+    def body(self, req):
+        b = self.builder_status
+        control = self.builder_control
+        status = self.getStatus(req)
+
+        slaves = b.getSlaves()
+        connected_slaves = [s for s in slaves if s.isConnected()]
+
+        projectName = status.getProjectName()
+
+        data = ''
+
+        # 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.make_line(req, build, False) + "</li>\n"
+        data += "</ul>\n"
+
+        data += "<h2>Buildslaves:</h2>\n"
+        data += "<ul>\n"
+        for slave in slaves:
+            data += "<li><b>%s</b>: " % html.escape(slave.getName())
+            if slave.isConnected():
+                data += "CONNECTED\n"
+                if slave.getAdmin():
+                    data += make_row("Admin:", html.escape(slave.getAdmin()))
+                if slave.getHost():
+                    data += "<span class='label'>Host info:</span>\n"
+                    data += html.PRE(slave.getHost())
+            else:
+                data += ("NOT CONNECTED\n")
+            data += "</li>\n"
+        data += "</ul>\n"
+
+        if control is not None and connected_slaves:
+            forceURL = urllib.quote(req.childLink("force"))
+            data += make_force_build_form(forceURL)
+        elif control is not None:
+            data += """
+            <p>All buildslaves appear to be offline, so it's not possible
+            to force this build to execute at this time.</p>
+            """
+
+        if control is not None:
+            pingURL = urllib.quote(req.childLink("ping"))
+            data += """
+            <form action="%s" class='command pingbuilder'>
+            <p>To ping the buildslave(s), push the 'Ping' button</p>
+
+            <input type="submit" value="Ping Builder" />
+            </form>
+            """ % pingURL
+
+        return data
+
+
+    def getChild(self, path, req):
+        if path == 'builds':
+            return JhBuildsResource(self.builder_status, self.builder_control)
+        return StatusResourceBuilder.getChild(self, path, req)
+
+
+class JhBuildersResource(BuildersResource):
+    def getChild(self, path, req):
+        if path == '':
+            return Redirect('..')
+        s = self.getStatus(req)
+        if path in s.getBuilderNames():
+            builder_status = s.getBuilder(path)
+            builder_control = None
+            c = self.getControl(req)
+            if c:
+                builder_control = c.getBuilder(path)
+            return JhStatusResourceBuilder(builder_status, builder_control)
+        return BuildersResource.getChild(self, path, req)

Added: trunk/jhbuild/buildbot/status/web/logs.py
==============================================================================
--- (empty file)
+++ trunk/jhbuild/buildbot/status/web/logs.py	Sun Aug 17 16:11:15 2008
@@ -0,0 +1,87 @@
+# jhbuild - a build script for GNOME 1.x and 2.x
+# Copyright (C) 2008  Frederic Peters
+#
+#   build.py: custom logs pages
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+try:
+    import html5lib
+except ImportError:
+    html5lib = None
+
+try:
+    import elementtree.ElementTree as ET
+except ImportError:
+    try:
+        import xml.etree.ElementTree as ET
+    except ImportError:
+        ET = None
+
+from buildbot.status.web.logs import LogsResource, HtmlResource, NoResource, IHTMLLog
+
+from zope.interface import implements
+from twisted.python import components
+
+
+from twisted.web.resource import Resource
+from twisted.web.error import NoResource
+
+from buildbot import interfaces
+from buildbot.status import builder
+from buildbot.status.web.base import IHTMLLog, HtmlResource
+from twisted.web.util import Redirect
+
+
+class HTMLLog(HtmlResource):
+    implements(IHTMLLog)
+
+    def __init__(self, original):
+        Resource.__init__(self)
+        self.original = original
+
+        parser = html5lib.HTMLParser()
+        c = parser.parse(self.original.html)
+        if c.childNodes[0].type == 3: # doctype
+            c = c.childNodes[1]
+        if c.attributes.get('xmlns'):
+            del c.attributes['xmlns']
+        self.x = ET.fromstring(c.toxml())
+
+    def getTitle(self, request):
+        status = self.getStatus(request)
+        p = status.getProjectName()
+        title = self.x.find('head/title')
+        if title is not None:
+            return '%s: %s' % (p, title.text)
+        return p
+
+    def body(self, request):
+        return '\n'.join([ET.tostring(x) for x in self.x.find('body').getchildren()])
+
+
+class JhLogsResource(LogsResource):
+    def getChild(self, path, req):
+        if path == '':
+            return Redirect('..')
+        for log in self.step_status.getLogs():
+            if path == log.getName():
+                if log.hasContents():
+                    if html5lib and ET and hasattr(log, 'html'):
+                        return HTMLLog(log)
+                    return IHTMLLog(interfaces.IStatusLog(log))
+                return NoResource("Empty Log '%s'" % path)
+        return HtmlResource.getChild(self, path, req)
+

Added: trunk/jhbuild/buildbot/status/web/step.py
==============================================================================
--- (empty file)
+++ trunk/jhbuild/buildbot/status/web/step.py	Sun Aug 17 16:11:15 2008
@@ -0,0 +1,114 @@
+# jhbuild - a build script for GNOME 1.x and 2.x
+# Copyright (C) 2008  Frederic Peters
+#
+#   step.py: custom step pages
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import urllib
+
+from twisted.web.util import Redirect
+from twisted.web import html
+
+from buildbot.status.web.base import HtmlResource
+from buildbot.status.web.step import StepsResource, StatusResourceBuildStep
+from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, EXCEPTION
+
+from logs import JhLogsResource
+
+class JhStatusResourceBuildStep(StatusResourceBuildStep):
+    def getTitle(self, request):
+        buildbot_service = request.site.buildbot_service
+        s = self.step_status
+        b = s.getBuild()
+        builder_name = b.getBuilder().getName()
+        for slave in buildbot_service.slaves:
+            if builder_name.endswith(slave):
+                slave_name = slave
+                module_name = builder_name[:-len(slave)-1]
+                break
+        else:
+            slave_name = None
+            module_name = None
+        status = self.getStatus(request)
+        p = status.getProjectName()
+        if slave_name:
+            return '%s - %s - build #%s @ %s' % (p, module_name, b.getNumber(), slave_name)
+        return '%s - %s' % (p, builder_name)
+
+    def body(self, req):
+        s = self.step_status
+        step_name = s.getName().split(' ')[-1]
+
+        data = ''
+        if not s.isFinished():
+            data += ('<h2>Not Finished</h2>\n'
+                     '<p>ETA %s seconds</p>\n' % s.getETA())
+        else:
+            r = s.getResults()
+            if r[0] in (SUCCESS, WARNINGS):
+                data += '<h2 class="success">Finished %s successfully</h2\n' % step_name
+            elif r[0] == FAILURE:
+                data += '<h2 class="failure">Finished %s unsuccessfully</h2\n' % step_name
+            elif r[0] == EXCEPTION:
+                data += '<h2 class="exception">Finished %s on an exception</h2\n' % step_name
+
+            if step_name == 'check' and len(s.getText()) > 1 and \
+                    s.getResults()[0] in (SUCCESS, WARNINGS):
+                data += '<ul>'
+                for x in s.getText()[1:]:
+                    data += '<li>%s</li>' % x
+                data += '</ul>'
+            else:
+                if len(s.getText()) > 1:
+                    data += '<p>%s</p>\n' % ' '.join(s.getText()[1:])
+
+        logs = s.getLogs()
+        if logs:
+            data += ("<h2>Logs</h2>\n"
+                     "<ul>\n")
+            for logfile in logs:
+                if logfile.hasContents():
+                    # FIXME: If the step name has a / in it, this is broken
+                    # either way.  If we quote it but say '/'s are safe,
+                    # it chops up the step name.  If we quote it and '/'s
+                    # are not safe, it escapes the / that separates the
+                    # step name from the log number.
+                    logname = logfile.getName()
+                    logurl = req.childLink("logs/%s" % urllib.quote(logname))
+                    data += ('<li><a href="%s">%s</a></li>\n' % 
+                             (logurl, html.escape(logname)))
+                else:
+                    data += '<li>%s</li>\n' % html.escape(logname)
+            data += "</ul>\n"
+
+        return data
+
+
+    def getChild(self, path, req):
+        if path == 'logs':
+            return JhLogsResource(self.step_status)
+        return HtmlResource.getChild(self, path, req)
+
+
+class JhStepsResource(StepsResource):
+    def getChild(self, path, req):
+        if path == '':
+            return Redirect('..')
+        for s in self.build_status.getSteps():
+            if s.getName() == path:
+                return JhStatusResourceBuildStep(self.build_status, s)
+        return HtmlResource.getChild(self, path, req)
+

Modified: trunk/jhbuild/buildbot/status/web/waterfall.py
==============================================================================
--- trunk/jhbuild/buildbot/status/web/waterfall.py	(original)
+++ trunk/jhbuild/buildbot/status/web/waterfall.py	Sun Aug 17 16:11:15 2008
@@ -204,7 +204,7 @@
                         text = t[0][len(self.module_name)+1:]
                         if text == 'updated':
                             text = 'update'
-                        event.setText([text])
+                        event.setText([text] + t[1:])
 
                     events.append(event)
                     starts, finishes = event.getTimes()

Modified: trunk/jhbuild/buildbot/steps.py
==============================================================================
--- trunk/jhbuild/buildbot/steps.py	(original)
+++ trunk/jhbuild/buildbot/steps.py	Sun Aug 17 16:11:15 2008
@@ -125,6 +125,88 @@
         text = self.describe(True)[:]
         return text
 
+
+class JHBuildCheckCommand(JHBuildCommand):
+    def __init__(self, **kwargs):
+        JHBuildCommand.__init__(self, stage='check', **kwargs)
+        self.failedTestsCount = 0
+        self.passedTestsCount = 0
+        self.testsResults = []
+        self.addLogObserver('stdio', UnitTestsObserver())
+
+    def evaluateCommand(self, cmd):
+        if self.failedTestsCount > 0:
+            return WARNINGS
+        else:
+            return SUCCESS
+
+    def getText(self, cmd, results):
+        text = JHBuildCommand.getText(self, cmd, results)
+        if self.failedTestsCount > 0 or self.passedTestsCount > 0:
+            text.append('failed: %s' % self.failedTestsCount)
+            text.append('passed: %s' % self.passedTestsCount)
+        return text
+
+    def createSummary(self, log):
+        if self.failedTestsCount > 0 or self.passedTestsCount > 0:
+            self.addHTMLLog('summary', self.createTestsSummary())
+
+    def createTestsSummary (self):
+        html = '<html>\n'
+        html += '<head>\n'
+        html += ' <title>Tests summary</title>\n'
+        html += ' <link rel="stylesheet" type="text/css" href="/lgo.css">\n'
+        html += ' <title>Tests summary</title>\n'
+        html += '</head>\n'
+        html += '<body>\n'
+
+        # Show summary
+        has_details = False
+        html += '<ul id="tests-summary">\n'
+        for t in self.testsResults:
+            if t[1]:
+                ttdclass = "success"
+            else:
+                ttdclass = "failure"
+            if len(t[2]) > 0:
+                html += '<li class="%s"><a href="#%s">%s</a></li>\n' % (ttdclass, t[0], t[0])
+                has_details = True
+            else:
+                html += '<li class="%s">%s</a></li>\n' % (ttdclass, t[0])
+        html += '</ul>\n'
+
+        if has_details:
+            # Show details
+            html += '<dl id="test-details">\n'
+            for t in self.testsResults:
+                if len(t[2]) == 0:
+                    continue
+                if t[1]:
+                    ttdclass = "success"
+                else:
+                    ttdclass = "failure"
+                html += '<dt class="%s">%s</dt>\n' % (ttdclass, t[0])
+                html += '<dd><ul>\n'
+
+                for ut in t[2]:
+                    if ut[1]:
+                        uttdclass = "success"
+                    else:
+                        uttdclass = "failure"
+                    html += '<li class="%s">' % uttdclass
+                    html += ut[0]
+                    if ut[1] == False:
+                        html += ' ' + ut[2]
+                    html += '</li>'
+                html += '</ul></dd>\n'
+            html += '</dl\n'
+
+        html += '</body>\n'
+        html += '</html>\n'
+
+        return html
+
+
 class JHBuildModulePathCommand(steps.shell.ShellCommand):
     name = "jhbuild_stage"
     haltOnFailure = 1
@@ -167,91 +249,3 @@
         text = self.describe(True)[:]
         return text
 
-class JHBuildModulePathTestCommand(JHBuildModulePathCommand):
-
-    def __init__(self, module=None, moduleset=None, action=[], **kwargs):
-        JHBuildModulePathCommand.__init__(self, module, moduleset, action, **kwargs)
-        self.failedTestsCount = 0
-        self.passedTestsCount = 0
-        self.testsResults = []
-        testFailuresObserver = UnitTestsObserver ()
-        self.addLogObserver('stdio', testFailuresObserver)
-
-    def createSummary(self, log):
-        if self.failedTestsCount > 0 or self.passedTestsCount > 0:
-            self.addHTMLLog ('tests summary', self.createTestsSummary())
-
-    def getText(self, cmd, results):
-        text = JHBuildModulePathCommand.getText(self, cmd, results)
-        if self.failedTestsCount > 0 or self.passedTestsCount > 0:
-            text.append("tests failed: " + str(self.failedTestsCount))
-            text.append("tests passed: " + str(self.passedTestsCount))
-        return text
-
-    def evaluateCommand(self, cmd):
-        if self.failedTestsCount > 0:
-            return WARNINGS
-        else:
-            return SUCCESS
-
-    def createTestsSummary (self):
-        html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
-        html += '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>\n'
-        html += '<html xmlns="http://www.w3.org/1999/xhtml"; lang="en" xml:lang="en">\n'
-        html += '<head>\n'
-        html += ' <title>BuildBot: tests summary</title>\n'
-        html += '<link href="/buildbot.css" rel="stylesheet" type="text/css"/>\n'
-        html += '</head>\n'
-        html += '<body vlink="#800080">\n'
-
-        # Show summary
-        html += '<table width="720" class="TestsSummary" cellspacing="0" cellpadding="4" align="center">\n'
-        col = 0
-        maxcolumns = 5
-
-        for t in self.testsResults:
-            if col == 0:
-                html += '<tr>\n'
-            if t[1]:
-                ttdclass = "success"
-            else:
-                ttdclass = "failure"
-            html += '<td width="20%" class="TestsSummary '+ ttdclass + '"><a href="#' + t[0] + '">' + t[0] + '</a></td>\n'
-            col += 1
-            if col >= maxcolumns:
-                col = 0
-                html += '</tr>\n'
-        html += '</table>\n'
-
-        html += '<br><hr>\n'
-
-        # Show details
-        for t in self.testsResults:
-            html += '<br><br>\n'
-            html += '<table align="center" width="720" class="TestsDetail" cellspacing="0" cellpadding="4">\n'
-            if t[1]:
-                ttdclass = "success"
-            else:
-                ttdclass = "failure"
-            html += '<tr><td colspan="2" class="TestsDetailHeader ' + ttdclass + '"><a name="' + t[0]+ '"></a>' + t[0] + '</td></tr>\n'
-
-            if len(t[2]) > 0:
-                for ut in t[2]:
-                    if ut[1]:
-                        uttdclass = "success"
-                    else:
-                        uttdclass = "failure"
-                    html += '<tr><td width="15" class="TestsDetail ' + uttdclass+ '">&nbsp;</td>\n'
-                    html += '<td class="TestsDetail">' + ut[0]
-                    if ut[1] == False:
-                        html += '<br><span class="text' + uttdclass+ '">' + ut[2] + '</span>'
-                    html += '</td></tr>'
-            else:
-                html += '<tr><td colspan="2" class="TestDetail">No unit tests found.</td></tr>\n'
-            html += '</table>\n'
-
-        html += '</body>\n'
-        html += '</html>\n'
-
-        return html
-



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]