[Buildbot-commits] buildbot/buildbot/status/web base.py, 1.7, 1.8 baseweb.py, 1.17, 1.18 waterfall.py, 1.12, 1.13
Brian Warner
warner at users.sourceforge.net
Mon Aug 13 08:20:53 UTC 2007
Update of /cvsroot/buildbot/buildbot/buildbot/status/web
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv13699/buildbot/status/web
Modified Files:
base.py baseweb.py waterfall.py
Log Message:
[project @ waterfall: add 'reload' query arg, add help page. Closes #69.]
Original author: warner at lothar.com
Date: 2007-08-13 08:16:33+00:00
Index: base.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/web/base.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- base.py 12 Aug 2007 22:23:07 -0000 1.7
+++ base.py 13 Aug 2007 08:20:51 -0000 1.8
@@ -188,6 +188,7 @@
data += "<head>\n"
for he in s.head_elements:
data += " " + self.fillTemplate(he, request) + "\n"
+ data += self.head(request)
data += "</head>\n\n"
data += '<body %s>\n' % " ".join(['%s="%s"' % (k,v)
@@ -197,6 +198,9 @@
data += self.fillTemplate(s.footer, request)
return data
+ def head(self, request):
+ return ""
+
def body(self, request):
return "Dummy\n"
Index: baseweb.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/web/baseweb.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- baseweb.py 12 Aug 2007 22:23:07 -0000 1.17
+++ baseweb.py 13 Aug 2007 08:20:51 -0000 1.18
@@ -126,7 +126,7 @@
status = self.getStatus(req)
numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0])
builders = req.args.get("builder", [])
- branches = req.args.get("branch", [])
+ branches = [b for b in req.args.get("branch", []) if b]
g = status.generateFinishedBuilds(builders, branches, numbuilds)
@@ -162,7 +162,7 @@
def body(self, req):
status = self.getStatus(req)
numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0])
- branches = req.args.get("branch", [])
+ branches = [b for b in req.args.get("branch", []) if b]
# walk backwards through all builds of a single builder
g = self.builder.generateFinishedBuilds(branches, numbuilds)
Index: waterfall.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/web/waterfall.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- waterfall.py 13 Aug 2007 06:33:47 -0000 1.12
+++ waterfall.py 13 Aug 2007 08:20:51 -0000 1.13
@@ -233,6 +233,167 @@
followingEventStarts = starts
if debug: log.msg(" fES1", starts)
+HELP = '''
+<form action="../waterfall" method="GET">
+
+<h1>The Waterfall Display</h1>
+
+<p>The Waterfall display can be controlled by adding query arguments to the
+URL. For example, if your Waterfall is accessed via the URL
+<tt>http://buildbot.example.org:8080</tt>, then you could add a
+<tt>branch=</tt> argument (described below) by going to
+<tt>http://buildbot.example.org:8080?branch=beta4</tt> instead. Remember that
+query arguments are separated from each other with ampersands, but they are
+separated from the main URL with a question mark, so to add a
+<tt>branch=</tt> and two <tt>builder=</tt> arguments, you would use
+<tt>http://buildbot.example.org:8080?branch=beta4&builder=unix&builder=macos</tt>.</p>
+
+<h2>Limiting the Displayed Interval</h2>
+
+<p>The <tt>last_time=</tt> argument is a unix timestamp (seconds since the
+start of 1970) that will be used as an upper bound on the interval of events
+displayed: nothing will be shown that is more recent than the given time.
+When no argument is provided, all events up to and including the most recent
+steps are included.</p>
+
+<p>The <tt>first_time=</tt> argument provides the lower bound. No events will
+be displayed that occurred <b>before</b> this timestamp. Instead of providing
+<tt>first_time=</tt>, you can provide <tt>show_time=</tt>: in this case,
+<tt>first_time</tt> will be set equal to <tt>last_time</tt> minus
+<tt>show_time</tt>. <tt>show_time</tt> overrides <tt>first_time</tt>.</p>
+
+<p>The display normally shows the latest 200 events that occurred in the
+given interval, where each timestamp on the left hand edge counts as a single
+event. You can add a <tt>num_events=</tt> argument to override this this.</p>
+
+<h2>Hiding non-Build events</h2>
+
+<p>By passing <tt>show_events=false</tt>, you can remove the "buildslave
+attached", "buildslave detached", and "builder reconfigured" events that
+appear in-between the actual builds.</p>
+
+%(show_events_input)s
+
+<h2>Showing only Certain Branches</h2>
+
+<p>If you provide one or more <tt>branch=</tt> arguments, the display will be
+limited to builds that used one of the given branches. If no <tt>branch=</tt>
+arguments are given, builds from all branches will be displayed.</p>
+
+Erase the text from these "Show Branch:" boxes to remove that branch filter.
+
+%(show_branches_input)s
+
+<h2>Limiting the Builders that are Displayed</h2>
+
+<p>By adding one or more <tt>builder=</tt> arguments, the display will be
+limited to showing builds that ran on the given builders. This serves to
+limit the display to the specific named columns. If no <tt>builder=</tt>
+arguments are provided, all Builders will be displayed.</p>
+
+<p>To view a Waterfall page with only a subset of Builders displayed, select
+the Builders you are interested in here.</p>
+
+%(show_builders_input)s
+
+
+<h2>Auto-reloading the Page</h2>
+
+<p>Adding a <tt>reload=</tt> argument will cause the page to automatically
+reload itself after that many seconds.</p>
+
+%(show_reload_input)s
+
+
+<input type="submit" value="View Waterfall" />
+</form>
+'''
+
+class WaterfallHelp(HtmlResource):
+ title = "Waterfall Help"
+
+ def __init__(self, categories=None):
+ HtmlResource.__init__(self)
+ self.categories = categories
+
+ def body(self, request):
+ data = ''
+ status = self.getStatus(request)
+
+ showEvents_checked = 'checked="checked"'
+ if request.args.get("show_events", ["true"])[0].lower() == "true":
+ showEvents_checked = ''
+ show_events_input = ('<p>'
+ '<input type="checkbox" name="show_events" '
+ 'value="false" %s>'
+ 'Hide non-Build events'
+ '</p>\n'
+ ) % showEvents_checked
+
+ branches = [b
+ for b in request.args.get("branch", [])
+ if b]
+ branches.append('')
+ show_branches_input = '<table>\n'
+ for b in branches:
+ show_branches_input += ('<tr>'
+ '<td>Show Branch: '
+ '<input type="text" name="branch" '
+ 'value="%s">'
+ '</td></tr>\n'
+ ) % (b,)
+ show_branches_input += '</table>\n'
+
+ # this has a set of toggle-buttons to let the user choose the
+ # builders
+ showBuilders = request.args.get("show", [])
+ showBuilders.extend(request.args.get("builder", []))
+ allBuilders = status.getBuilderNames(categories=self.categories)
+
+ show_builders_input = '<table>\n'
+ for bn in allBuilders:
+ checked = ""
+ if bn in showBuilders:
+ checked = 'checked="checked"'
+ show_builders_input += ('<tr>'
+ '<td><input type="checkbox"'
+ ' name="builder" '
+ 'value="%s" %s></td> '
+ '<td>%s</td></tr>\n'
+ ) % (bn, checked, bn)
+ show_builders_input += '</table>\n'
+
+ # a couple of radio-button selectors for refresh time will appear
+ # just after that text
+ show_reload_input = '<table>\n'
+ times = [("none", "None"),
+ ("30", "30 seconds"),
+ ("60", "60 seconds"),
+ ("300", "5 minutes"),
+ ]
+ current_reload_time = request.args.get("reload", ["none"])
+ if current_reload_time:
+ current_reload_time = current_reload_time[0]
+ if current_reload_time not in [t[0] for t in times]:
+ times.insert(0, (current_reload_time, current_reload_time) )
+ for value, name in times:
+ checked = ""
+ if value == current_reload_time:
+ checked = 'checked="checked"'
+ show_reload_input += ('<tr>'
+ '<td><input type="radio" name="reload" '
+ 'value="%s" %s></td> '
+ '<td>%s</td></tr>\n'
+ ) % (value, checked, name)
+ show_reload_input += '</table>\n'
+
+ fields = {"show_events_input": show_events_input,
+ "show_branches_input": show_branches_input,
+ "show_builders_input": show_builders_input,
+ "show_reload_input": show_reload_input,
+ }
+ data += HELP % fields
+ return data
class WaterfallStatusResource(HtmlResource):
"""This builds the main status page, with the waterfall display, and
@@ -241,6 +402,7 @@
def __init__(self, categories=None):
HtmlResource.__init__(self)
self.categories = categories
+ self.putChild("help", WaterfallHelp(categories))
def getTitle(self, request):
status = self.getStatus(request)
@@ -254,6 +416,23 @@
# TODO: this wants to go away, access it through IStatus
return request.site.buildbot_service.parent.change_svc
+ def get_reload_time(self, request):
+ if "reload" in request.args:
+ try:
+ reload_time = int(request.args["reload"][0])
+ if reload_time > 15:
+ return reload_time
+ except ValueError:
+ pass
+ return None
+
+ def head(self, request):
+ head = ''
+ reload_time = self.get_reload_time(request)
+ if reload_time is not None:
+ head += '<meta http-equiv="refresh" content="%d">\n' % reload_time
+ return head
+
def body(self, request):
"This method builds the main waterfall display."
@@ -266,7 +445,8 @@
phase = request.args.get("phase",["2"])
phase = int(phase[0])
- showBuilders = request.args.get("show", None)
+ showBuilders = request.args.get("show", [])
+ showBuilders.extend(request.args.get("builder", []))
allBuilders = status.getBuilderNames(categories=self.categories)
if showBuilders:
builderNames = []
@@ -335,19 +515,42 @@
data += "<hr />\n"
- if timestamps:
+ def with_args(req, remove_args=[], new_args=[], new_path=None):
# sigh, nevow makes this sort of manipulation easier
- bottom = timestamps[-1]
- newargs = request.args.copy()
- newargs["last_time"] = [str(int(bottom))]
+ newargs = req.args.copy()
+ for argname in remove_args:
+ newargs[argname] = []
+ newargs["branch"] = [b for b in newargs["branch"] if b]
+ for k,v in new_args:
+ if k in newargs:
+ newargs[k].append(v)
+ else:
+ newargs[k] = [v]
newquery = "&".join(["%s=%s" % (k, v)
for k in newargs
for v in newargs[k]
])
- nextpage = str(request.URLPath())
- if newquery:
- nextpage += "?" + newquery
+ new_url = req.URLPath()
+ if new_path:
+ new_url.path = new_path
+ new_url.query = newquery
+ #if newquery:
+ # new_url += "?" + newquery
+ return str(new_url)
+
+ if timestamps:
+ bottom = timestamps[-1]
+ nextpage = with_args(request, ["last_time"],
+ [("last_time", str(int(bottom)))])
data += '<a href="%s">next page</a>\n' % nextpage
+
+ helppage = with_args(request, new_path="waterfall/help")
+ data += '<a href="%s">help</a>\n' % helppage
+
+ if self.get_reload_time(request) is not None:
+ no_reload_page = with_args(request, remove_args=["reload"])
+ data += '<a href="%s">Stop Reloading</a>\n' % no_reload_page
+
data += "<br />\n"
@@ -421,7 +624,7 @@
showEvents = False
if request.args.get("show_events", ["true"])[0].lower() == "true":
showEvents = True
- filterBranches = request.args.get("branch", [])
+ filterBranches = [b for b in request.args.get("branch", []) if b]
maxTime = int(request.args.get("last_time", [util.now()])[0])
if "show_time" in request.args:
minTime = maxTime - int(request.args["show_time"][0])
More information about the Commits
mailing list