Navigation Menu

Skip to content

Commit

Permalink
Merge branch 'transposed_grid' of git://github.com/jkugler/buildbot
Browse files Browse the repository at this point in the history
  • Loading branch information
Dustin J. Mitchell committed May 6, 2009
2 parents 4056797 + d175036 commit 163a3fa
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 66 deletions.
7 changes: 5 additions & 2 deletions buildbot/status/web/baseweb.py
Expand Up @@ -16,7 +16,7 @@
from buildbot.status.web.feeds import Rss20StatusResource, \ from buildbot.status.web.feeds import Rss20StatusResource, \
Atom10StatusResource Atom10StatusResource
from buildbot.status.web.waterfall import WaterfallStatusResource from buildbot.status.web.waterfall import WaterfallStatusResource
from buildbot.status.web.grid import GridStatusResource from buildbot.status.web.grid import GridStatusResource, TransposedGridStatusResource
from buildbot.status.web.changes import ChangesResource from buildbot.status.web.changes import ChangesResource
from buildbot.status.web.builder import BuildersResource from buildbot.status.web.builder import BuildersResource
from buildbot.status.web.slaves import BuildSlavesResource from buildbot.status.web.slaves import BuildSlavesResource
Expand Down Expand Up @@ -299,8 +299,10 @@ class WebStatus(service.MultiService):
query-arguments used by 'waterfall' can be added to query-arguments used by 'waterfall' can be added to
influence the feed output. influence the feed output.
/grid : another summary display that shows a grid of builds, with /grid : another summary display that shows a grid of builds, with
sourcestamps on the x axis, and builders on the y. Query sourcestamps on the x axis, and builders on the y. Query
arguments similar to those for the waterfall can be added. arguments similar to those for the waterfall can be added.
/tgrid : similar to the grid display, but the commits are down the
left side, and the build hosts are across the top.
/builders/BUILDERNAME: a page summarizing the builder. This includes /builders/BUILDERNAME: a page summarizing the builder. This includes
references to the Schedulers that feed it, references to the Schedulers that feed it,
any builds currently in the queue, which any builds currently in the queue, which
Expand Down Expand Up @@ -490,6 +492,7 @@ def setupUsualPages(self, numbuilds):
#self.putChild("", IndexOrWaterfallRedirection()) #self.putChild("", IndexOrWaterfallRedirection())
self.putChild("waterfall", WaterfallStatusResource()) self.putChild("waterfall", WaterfallStatusResource())
self.putChild("grid", GridStatusResource()) self.putChild("grid", GridStatusResource())
self.putChild("tgrid", TransposedGridStatusResource())
self.putChild("builders", BuildersResource()) # has builds/steps/logs self.putChild("builders", BuildersResource()) # has builds/steps/logs
self.putChild("changes", ChangesResource()) self.putChild("changes", ChangesResource())
self.putChild("buildslaves", BuildSlavesResource()) self.putChild("buildslaves", BuildSlavesResource())
Expand Down
171 changes: 138 additions & 33 deletions buildbot/status/web/grid.py
Expand Up @@ -22,18 +22,7 @@


class ANYBRANCH: pass # a flag value, used below class ANYBRANCH: pass # a flag value, used below


class GridStatusResource(HtmlResource): class GridStatusMixin(object):
# TODO: docs
status = None
control = None
changemaster = None

def __init__(self, allowForce=True, css=None):
HtmlResource.__init__(self)

self.allowForce = allowForce
self.css = css or grid_css

def getTitle(self, request): def getTitle(self, request):
status = self.getStatus(request) status = self.getStatus(request)
p = status.getProjectName() p = status.getProjectName()
Expand Down Expand Up @@ -137,8 +126,56 @@ def stamp_td(self, stamp):
return '<td valign="bottom" class="sourcestamp">%s</td>\n' % \ return '<td valign="bottom" class="sourcestamp">%s</td>\n' % \
"<br />".join(text) "<br />".join(text)


def getRecentSourcestamps(self, status, numBuilds, categories, branch):
"""
get a list of the most recent NUMBUILDS SourceStamp tuples, sorted
by the earliest start we've seen for them
"""
# TODO: use baseweb's getLastNBuilds?
sourcestamps = { } # { ss-tuple : earliest time }
for bn in status.getBuilderNames():
builder = status.getBuilder(bn)
if categories and builder.category not in categories:
continue
build = builder.getBuild(-1)
while build:
ss = build.getSourceStamp(absolute=True)
start = build.getTimes()[0]
build = build.getPreviousBuild()

# skip un-started builds
if not start: continue

# skip non-matching branches
if branch != ANYBRANCH and ss.branch != branch: continue

sourcestamps[ss] = min(sourcestamps.get(ss, sys.maxint), start)

# now sort those and take the NUMBUILDS most recent
sourcestamps = sourcestamps.items()
sourcestamps.sort(lambda x, y: cmp(x[1], y[1]))
sourcestamps = map(lambda tup : tup[0], sourcestamps)
sourcestamps = sourcestamps[-numBuilds:]

return sourcestamps

class GridStatusResource(HtmlResource, GridStatusMixin):
# TODO: docs
status = None
control = None
changemaster = None

def __init__(self, allowForce=True, css=None):
HtmlResource.__init__(self)

self.allowForce = allowForce
self.css = css or grid_css


def body(self, request): def body(self, request):
"This method builds the main waterfall display." """This method builds the regular grid display.
That is, build stamps across the top, build hosts down the left side
"""


# get url parameters # get url parameters
numBuilds = int(request.args.get("width", [5])[0]) numBuilds = int(request.args.get("width", [5])[0])
Expand Down Expand Up @@ -217,36 +254,104 @@ def body(self, request):
data += '</div>\n' data += '</div>\n'
return data return data


def getRecentSourcestamps(self, status, numBuilds, categories, branch): class TransposedGridStatusResource(HtmlResource, GridStatusMixin):
""" # TODO: docs
get a list of the most recent NUMBUILDS SourceStamp tuples, sorted status = None
by the earliest start we've seen for them control = None
changemaster = None

def __init__(self, allowForce=True, css=None):
HtmlResource.__init__(self)

self.allowForce = allowForce
self.css = css or grid_css


def body(self, request):
"""This method builds the transposed grid display.
That is, build hosts across the top, ebuild stamps down the left side
""" """
# TODO: use baseweb's getLastNBuilds?
sourcestamps = { } # { ss-tuple : earliest time } # get url parameters
for bn in status.getBuilderNames(): numBuilds = int(request.args.get("length", [5])[0])
categories = request.args.get("category", [])
branch = request.args.get("branch", [ANYBRANCH])[0]
if branch == 'trunk': branch = None

# and the data we want to render
status = self.getStatus(request)
stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch)

projectURL = status.getProjectURL()
projectName = status.getProjectName()

data = '<table class="Grid" border="0" cellspacing="0">\n'
data += '<tr>\n'
data += '<td class="title"><a href="%s">%s</a>' % (projectURL, projectName)
if categories:
if len(categories) > 1:
data += '\n<br /><b>Categories:</b><br/>%s' % ('<br/>'.join(categories))
else:
data += '\n<br /><b>Category:</b> %s' % categories[0]
if branch != ANYBRANCH:
data += '\n<br /><b>Branch:</b> %s' % (branch or 'trunk')
data += '</td>\n'

sortedBuilderNames = status.getBuilderNames()[:]
sortedBuilderNames.sort()

builder_builds = {}

for bn in sortedBuilderNames:
builds = [None] * len(stamps)

builder = status.getBuilder(bn) builder = status.getBuilder(bn)
if categories and builder.category not in categories: if categories and builder.category not in categories:
continue continue

build = builder.getBuild(-1) build = builder.getBuild(-1)
while build: while build and None in builds:
ss = build.getSourceStamp(absolute=True) ss = build.getSourceStamp(absolute=True)
start = build.getTimes()[0] for i in range(len(stamps)):
if ss == stamps[i] and builds[i] is None:
builds[i] = build
build = build.getPreviousBuild() build = build.getPreviousBuild()


# skip un-started builds data += self.builder_td(request, builder)
if not start: continue builder_builds[bn] = builds


# skip non-matching branches data += '</tr>\n'
if branch != ANYBRANCH and ss.branch != branch: continue


sourcestamps[ss] = min(sourcestamps.get(ss, sys.maxint), start) for i in range(len(stamps)):
data += '<tr>\n'
data += self.stamp_td(stamps[i])
for bn in sortedBuilderNames:
data += self.build_td(request, builder_builds[bn][i])
data += '</tr>\n'


# now sort those and take the NUMBUILDS most recent data += '</table>\n'
sourcestamps = sourcestamps.items()
sourcestamps.sort(lambda x, y: cmp(x[1], y[1]))
sourcestamps = map(lambda tup : tup[0], sourcestamps)
sourcestamps = sourcestamps[-numBuilds:]


return sourcestamps # TODO: this stuff should be generated by a template of some sort
data += '<hr /><div class="footer">\n'

welcomeurl = self.path_to_root(request) + "index.html"
data += '[<a href="%s">welcome</a>]\n' % welcomeurl
data += "<br />\n"

data += '<a href="http://buildbot.sourceforge.net/">Buildbot</a>'
data += "-%s " % version
if projectName:
data += "working for the "
if projectURL:
data += "<a href=\"%s\">%s</a> project." % (projectURL,
projectName)
else:
data += "%s project." % projectName
data += "<br />\n"
data += ("Page built: " +
time.strftime("%a %d %b %Y %H:%M:%S",
time.localtime(util.now()))
+ "\n")
data += '</div>\n'
return data


3 changes: 3 additions & 0 deletions buildbot/status/web/index.html
Expand Up @@ -15,6 +15,9 @@ <h1>Welcome to the Buildbot!</h1>
<li>the <a href="grid">Grid Display</a> will give you a <li>the <a href="grid">Grid Display</a> will give you a
developer-oriented summary of recent buildbot activity.</li> developer-oriented summary of recent buildbot activity.</li>


<li>the <a href="tgrid">Transposed Grid Display</a> presents
the same information as the grid, but lists the revisions down the side.</li>

<li>The <a href="one_box_per_builder">Latest Build</a> for each builder is <li>The <a href="one_box_per_builder">Latest Build</a> for each builder is
here.</li> here.</li>


Expand Down

0 comments on commit 163a3fa

Please sign in to comment.