Skip to content

Commit

Permalink
Initial file reorganization for TransposedGrid
Browse files Browse the repository at this point in the history
  • Loading branch information
jkugler committed Apr 28, 2009
1 parent 951a6e2 commit 8763836
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 35 deletions.
4 changes: 2 additions & 2 deletions buildbot/status/web/baseweb.py
Expand Up @@ -16,7 +16,7 @@
from buildbot.status.web.feeds import Rss20StatusResource, \
Atom10StatusResource
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.builder import BuildersResource
from buildbot.status.web.slaves import BuildSlavesResource
Expand Down Expand Up @@ -294,7 +294,7 @@ class WebStatus(service.MultiService):
query-arguments used by 'waterfall' can be added to
influence the feed output.
/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.
/builders/BUILDERNAME: a page summarizing the builder. This includes
references to the Schedulers that feed it,
Expand Down
161 changes: 128 additions & 33 deletions buildbot/status/web/grid.py
Expand Up @@ -22,18 +22,7 @@

class ANYBRANCH: pass # a flag value, used below

class GridStatusResource(HtmlResource):
# 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

class GridStatusMixin(object):
def getTitle(self, request):
status = self.getStatus(request)
p = status.getProjectName()
Expand Down Expand Up @@ -137,6 +126,52 @@ def stamp_td(self, stamp):
return '<td valign="bottom" class="sourcestamp">%s</td>\n' % \
"<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):
"This method builds the main waterfall display."

Expand Down Expand Up @@ -217,36 +252,96 @@ def body(self, request):
data += '</div>\n'
return data

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():
class TransposedGridStatusResource(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):
"This method builds the main waterfall display."

# get url parameters
numBuilds = int(request.args.get("width", [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'
for stamp in stamps:
data += self.stamp_td(stamp)
data += '</tr>\n'

sortedBuilderNames = status.getBuilderNames()[:]
sortedBuilderNames.sort()
for bn in sortedBuilderNames:
builds = [None] * len(stamps)

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

build = builder.getBuild(-1)
while build:
while build and None in builds:
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()

# skip un-started builds
if not start: continue
data += '<tr>\n'
data += self.builder_td(request, builder)
for build in builds:
data += self.build_td(request, build)
data += '</tr>\n'

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

sourcestamps[ss] = min(sourcestamps.get(ss, sys.maxint), start)
# TODO: this stuff should be generated by a template of some sort
data += '<hr /><div class="footer">\n'

# 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:]
welcomeurl = self.path_to_root(request) + "index.html"
data += '[<a href="%s">welcome</a>]\n' % welcomeurl
data += "<br />\n"

return sourcestamps
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

0 comments on commit 8763836

Please sign in to comment.