def getBox(self, req): urlbase = path_to_step(req, self.original) text = self.original.getText() if text is None: log.msg("getText() gave None", urlbase) text = [] text = text[:] def native_link_fn(l): if l.hasContents(): url = urlbase + "/logs/%s" % urllib.quote(l.getName()) else: url = None return url logs, urls, _ = getStepLogsURLsAndAliases( self.original, False, native_link_fn, ) cxt = dict(text=text, logs=logs, urls=urls) template = req.site.buildbot_service.templates.get_template( "box_macros.html") text = template.module.step_box(**unicodify(cxt)) class_ = "BuildStep " + build_get_class(self.original) return Box(text, class_=class_, buildNumber=self.original.build_number, builder=self.original.builder.getName(), stepName=self.original.getName())
def content(self, request, ctx): s = self.getStatus(request) slave = s.getSlave(self.slavename) my_builders = [] for bname in s.getBuilderNames(): b = s.getBuilder(bname) for bs in b.getSlaves(): if bs.getName() == self.slavename: my_builders.append(b) # Current builds current_builds = [] for b in my_builders: for cb in b.getCurrentBuilds(): if cb.getSlavename() == self.slavename: current_builds.append(self.get_line_values(request, cb)) try: max_builds = int(request.args.get('numbuilds')[0]) except: max_builds = 10 recent_builds = [] n = 0 for rb in s.generateFinishedBuilds( builders=[b.getName() for b in my_builders]): if rb.getSlavename() == self.slavename: n += 1 recent_builds.append(self.get_line_values(request, rb)) if n > max_builds: break # connects over the last hour slave = s.getSlave(self.slavename) connect_count = slave.getConnectCount() ctx.update(dict(slave=slave, slavename=self.slavename, current=current_builds, recent=recent_builds, shutdown_url=request.childLink("shutdown"), authz=self.getAuthz(request), this_url="../../../" + path_to_slave(request, slave), access_uri=slave.getAccessURI()), admin=unicode(slave.getAdmin() or '', 'utf-8'), host=unicode(slave.getHost() or '', 'utf-8'), slave_version=slave.getVersion(), show_builder_column=True, connect_count=connect_count) template = request.site.buildbot_service.templates.get_template( "buildslave.html") data = template.render(**unicodify(ctx)) return data
def content(self, request, ctx): s = self.getStatus(request) #?no_builders=1 disables build column show_builder_column = not (request.args.get('no_builders', '0')[0]) == '1' ctx['show_builder_column'] = show_builder_column used_by_builder = {} for bname in s.getBuilderNames(): b = s.getBuilder(bname) for bs in b.getSlaves(): slavename = bs.getName() if slavename not in used_by_builder: used_by_builder[slavename] = [] used_by_builder[slavename].append(bname) slaves = ctx['slaves'] = [] for name in util.naturalSort(s.getSlaveNames()): info = {} slaves.append(info) slave = s.getSlave(name) slave_status = s.botmaster.slaves[name].slave_status info['running_builds'] = len(slave_status.getRunningBuilds()) info['link'] = request.childLink(urllib.quote(name, '')) info['name'] = name if show_builder_column: info['builders'] = [] for b in used_by_builder.get(name, []): info['builders'].append( dict(link=request.childLink("../builders/%s" % b), name=b)) info['version'] = slave.getVersion() info['connected'] = slave.isConnected() info['connectCount'] = slave.getConnectCount() info['admin'] = unicode(slave.getAdmin() or '', 'utf-8') last = slave.lastMessageReceived() if last: info['last_heard_from_age'] = abbreviate_age(time.time() - last) info['last_heard_from_time'] = time.strftime( "%Y-%b-%d %H:%M:%S", time.localtime(last)) template = request.site.buildbot_service.templates.get_template( "buildslaves.html") data = template.render(**unicodify(ctx)) return data
def content(self, request, cxt): status = self.getStatus(request) if request.path == '/shutdown': return redirectTo(path_to_authfail(request), request) elif request.path == '/cancel_shutdown': return redirectTo(path_to_authfail(request), request) cxt.update( shutting_down=status.shuttingDown, shutdown_url=request.childLink("shutdown"), cancel_shutdown_url=request.childLink("cancel_shutdown"), ) template = request.site.buildbot_service.templates.get_template( "root.html") return template.render(**unicodify(cxt))
def got_changes(allChanges): debugInfo["source_all"] = len(allChanges) revisions = list(self.filterRevisions(allChanges, max_revs=numRevs)) debugInfo["revision_final"] = len(revisions) # Fetch all the builds for all builders until we get the next build # after lastRevision. builderList = None allBuilds = None if revisions: lastRevision = revisions[len(revisions) - 1].revision debugInfo["last_revision"] = lastRevision (builderList, allBuilds) = self.getAllBuildsForRevision(status, request, lastRevision, numBuilds, categories, builders, debugInfo, revisions) debugInfo["added_blocks"] = 0 debugInfo["from_cache"] = 0 if request.args.get("display_cache", None): data = "" data += "\nGlobal Cache\n" data += self.cache.display() return data cxt.update(self.displayPage(request, status, builderList, allBuilds, revisions, categories, repository, branch, debugInfo)) templates = request.site.buildbot_service.templates template = templates.get_template("console.html") cxt['mastername'] = ( request.site.buildbot_service.master.properties['mastername']) data = template.render(unicodify(cxt)) # Clean up the cache. if debugInfo["added_blocks"]: self.cache.trim() return data
def content(self, request, ctx): """Display a build in the same format as the waterfall page. The HTTP GET parameters are the builder name and the build number.""" status = self.getStatus(request) request.setHeader('Cache-Control', 'no-cache') # Get the parameters. name = request.args.get("builder", [None])[0] number = request.args.get("number", [None])[0] if not name or not number: return "builder and number parameter missing" number = int(number) # Check if the builder in parameter exists. try: builder = status.getBuilder(name) except: return "unknown builder" # Check if the build in parameter exists. build = builder.getBuild(int(number)) if not build: return "unknown build %s" % number rows = ctx['rows'] = [] # Display each step, starting by the last one. for i in range(len(build.getSteps()) - 1, -1, -1): step = build.getSteps()[i] if step.isStarted() and step.getText(): rows.append(IBox(step).getBox(request).td(align="center")) # Display the bottom box with the build number in it. ctx['build'] = IBox(build).getBox(request).td(align="center") template = request.site.buildbot_service.templates.get_template( "buildstatus.html") data = template.render(**unicodify(ctx)) # We want all links to display in a new tab/window instead of in the # current one. # TODO: Move to template data = data.replace('<a ', '<a target="_blank"') return data
def getBox(self, req): b = self.original number = b.getNumber() url = path_to_build(req, b) reason = b.getReason() template = req.site.buildbot_service.templates.get_template( "box_macros.html") cxt = { 'reason': reason, 'url': url, 'number': number, } text = template.module.build_box(**unicodify(cxt)) class_ = "start" if b.isFinished() and not b.getSteps(): # the steps have been pruned, so there won't be any indication # of whether it succeeded or failed. class_ = build_get_class(b) return Box([text], class_="BuildStep " + class_)
def content(self, request, cxt): status = self.getStatus(request) cxt['show_events_checked'] = request.args.get( "show_events", ["false"])[0].lower() == "true" cxt['branches'] = [b for b in request.args.get("branch", []) if b] cxt['failures_only'] = request.args.get("failures_only", ["false"])[0].lower() == "true" cxt['committers'] = [c for c in request.args.get("committer", []) if c] # this has a set of toggle-buttons to let the user choose the # builders show_builders = request.args.get("show", []) show_builders.extend(request.args.get("builder", [])) cxt['show_builders'] = show_builders cxt['all_builders'] = status.getBuilderNames( categories=self.categories) # a couple of radio-button selectors for refresh time will appear # just after that text times = [ ("none", "None"), ("60", "60 seconds"), ("300", "5 minutes"), ("600", "10 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)) cxt['times'] = times cxt['current_reload_time'] = current_reload_time template = request.site.buildbot_service.templates.get_template( "waterfallhelp.html") return template.render(**unicodify(cxt))
def content(self, req, cxt): s = self.step_status b = s.getBuild() # 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. logs, _, _ = getStepLogsURLsAndAliases( s, True, lambda l: req.childLink("logs/%s" % urllib.quote(l.getName())), ) cxt['logs'] = logs start, end = s.getTimes() if start: cxt['start'] = ctime(start) if end: cxt['end'] = ctime(end) cxt['elapsed'] = util.formatInterval(end - start) else: cxt['end'] = "Not Finished" cxt['elapsed'] = util.formatInterval(util.now() - start) cxt.update( dict(builder_link=path_to_builder(req, b.getBuilder()), build_link=path_to_build(req, b), b=b, s=s, result_css=css_classes[s.getResults()[0]])) template = req.site.buildbot_service.templates.get_template( "buildstep.html") return template.render(**unicodify(cxt))
def content(self, req, cxt): b = self.build_status status = self.getStatus(req) req.setHeader('Cache-Control', 'no-cache') cxt['b'] = b cxt['path_to_builder'] = path_to_builder(req, b.getBuilder()) if not b.isFinished(): step = b.getCurrentStep() if not step: cxt['current_step'] = "[waiting for Lock]" else: if step.isWaitingForLocks(): cxt['current_step'] = "%s [waiting for Lock]" % step.getName( ) else: cxt['current_step'] = step.getName() when = b.getETA() if when is not None: cxt['when'] = util.formatInterval(when) cxt['when_time'] = time.strftime( "%H:%M:%S", time.localtime(time.time() + when)) else: cxt['result_css'] = css_classes[b.getResults()] if b.getTestResults(): cxt['tests_link'] = req.childLink("tests") ss = cxt['ss'] = b.getSourceStamp() if ss.branch is None and ss.revision is None and ss.patch is None and not ss.changes: cxt['most_recent_rev_build'] = True got_revision = None try: got_revision = b.getProperty("got_revision") except KeyError: pass if got_revision: cxt['got_revision'] = str(got_revision) try: cxt['slave_url'] = path_to_slave(req, status.getSlave(b.getSlavename())) except KeyError: pass cxt['steps'] = [] for s in b.getSteps(): step = {'name': s.getName()} if s.isHidden(): continue if s.isFinished(): step['css_class'] = css_classes[s.getResults()[0]] (start, end) = s.getTimes() step['time_to_run'] = util.formatInterval(end - start) elif s.isStarted(): if s.isWaitingForLocks(): step['css_class'] = "waiting" step['time_to_run'] = "waiting for locks" else: step['css_class'] = "running" step['time_to_run'] = "running" else: step['css_class'] = "not_started" step['time_to_run'] = "" cxt['steps'].append(step) step_logs, step_urls, step_aliases = getStepLogsURLsAndAliases( s, False, lambda l: req.childLink("steps/%s/logs/%s" % (urllib.quote(s.getName(), safe=''), urllib.quote(l.getName(), safe=''))), ) step['link'] = req.childLink("steps/%s" % urllib.quote(s.getName(), safe='')) step['text'] = " ".join(s.getText()) step['urls'] = step_urls step['nest_level'] = s.getNestLevel() step['logs'] = step_logs step['aliases'] = {} seen_aliases = set() for base, aliases in step_aliases.iteritems(): step['aliases'][base] = [{ 'text': a[0], 'url': a[1], } for a in aliases] seen_aliases.add(base) seen_aliases.difference_update(s['logname'] for s in step['urls']) seen_aliases.difference_update(s['name'] for s in step['logs']) # Append link-less log anchors for unbased aliases to attach to. # # We include an empty link so that custom templates that don't # support aliases don't crash when trying to render these anchors. # This will cause waterfalls that have alias data but haven't # updated their templates to render them to show blank links. This # is okay, since waterfalls that accept alias data should have # their templates updated to render this data. for base in sorted(seen_aliases): step['logs'].append({'name': base, 'link': ''}) ps = cxt['properties'] = [] for name, value, source in b.getProperties().asList(): value = str(value) p = {'name': name, 'value': value, 'source': source} if len(value) > 500: p['short_value'] = value[:500] ps.append(p) cxt['responsible_users'] = list(b.getResponsibleUsers()) (start, end) = b.getTimes() cxt['start'] = time.ctime(start) if end: cxt['end'] = time.ctime(end) cxt['elapsed'] = util.formatInterval(end - start) else: now = util.now() cxt['elapsed'] = util.formatInterval(now - start) cxt['exactly'] = (ss.revision is not None) or b.getChanges() cxt['build_url'] = path_to_build(req, b) cxt['authz'] = self.getAuthz(req) template = req.site.buildbot_service.templates.get_template( "build.html") return template.render(**unicodify(cxt))
def content(self, req, cxt): b = self.builder_status cxt['name'] = b.getName() req.setHeader('Cache-Control', 'no-cache') slaves = b.getSlaves() connected_slaves = [s for s in slaves if s.isConnected()] cxt['current'] = [self.builder(x, req) for x in b.getCurrentBuilds()] cxt['pending'] = [] wfd = defer.waitForDeferred(b.getPendingBuildRequestStatuses()) yield wfd statuses = wfd.getResult() for pb in statuses: changes = [] wfd = defer.waitForDeferred(pb.getSourceStamp()) yield wfd source = wfd.getResult() wfd = defer.waitForDeferred(pb.getSubmitTime()) yield wfd submitTime = wfd.getResult() if source.changes: for c in source.changes: changes.append({ 'url': path_to_change(req, c), 'who': c.who, 'revision': c.revision, 'repo': c.repository }) cxt['pending'].append({ 'when': time.strftime("%b %d %H:%M:%S", time.localtime(submitTime)), 'delay': util.formatInterval(util.now() - submitTime), 'id': pb.brid, 'changes': changes, 'num_changes': len(changes), }) numbuilds = int(req.args.get('numbuilds', ['20'])[0]) recent = cxt['recent'] = [] for build in b.generateFinishedBuilds(num_builds=int(numbuilds)): recent.append(self.get_line_values(req, build, False)) sl = cxt['slaves'] = [] connected_slaves = 0 for slave in slaves: s = {} sl.append(s) s['link'] = path_to_slave(req, slave) s['name'] = slave.getName() c = s['connected'] = slave.isConnected() if c: s['admin'] = unicode(slave.getAdmin() or '', 'utf-8') connected_slaves += 1 cxt['connected_slaves'] = connected_slaves cxt['authz'] = self.getAuthz(req) cxt['builder_url'] = path_to_builder(req, b) cxt['mastername'] = ( req.site.buildbot_service.master.properties['mastername']) template = req.site.buildbot_service.templates.get_template( "builder.html") yield template.render(**unicodify(cxt))
def content(self, req, cxt): status = self.getStatus(req) builders = req.args.get("builder", status.getBuilderNames()) branches = [b for b in req.args.get("branch", []) if b] # get counts of pending builds for each builder brstatus_ds = [] brcounts = {} def keep_count(statuses, builderName): brcounts[builderName] = len(statuses) for builderName in builders: builder_status = status.getBuilder(builderName) d = builder_status.getPendingBuildRequestStatuses() d.addCallback(keep_count, builderName) brstatus_ds.append(d) wfd = defer.waitForDeferred(defer.gatherResults(brstatus_ds)) yield wfd wfd.getResult() cxt['branches'] = branches bs = cxt['builders'] = [] building = 0 online = 0 base_builders_url = path_to_root(req) + "builders/" for bn in builders: bld = { 'link': base_builders_url + urllib.quote(bn, safe=''), 'name': bn } bs.append(bld) builder = status.getBuilder(bn) builds = list( builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if builds: b = builds[0] bld['build_url'] = (bld['link'] + "/builds/%d" % b.getNumber()) try: label = b.getProperty("got_revision") except KeyError: label = None if not label or len(str(label)) > 20: label = "#%d" % b.getNumber() bld['build_label'] = label bld['build_text'] = " ".join(b.getText()) bld['build_css_class'] = build_get_class(b) current_box = ICurrentBox(builder).getBox(status, brcounts) bld['current_box'] = current_box.td() builder_status = builder.getState()[0] if builder_status == "building": building += 1 online += 1 elif builder_status != "offline": online += 1 cxt['authz'] = self.getAuthz(req) cxt['num_building'] = building cxt['num_online'] = online template = req.site.buildbot_service.templates.get_template( "builders.html") yield template.render(**unicodify(cxt))
def content_with_db_data(self, changes, brcounts, request, ctx): status = self.getStatus(request) ctx['refresh'] = self.get_reload_time(request) # we start with all Builders available to this Waterfall: this is # limited by the config-file -time categories= argument, and defaults # to all defined Builders. allBuilderNames = status.getBuilderNames(categories=self.categories) builders = [status.getBuilder(name) for name in allBuilderNames] # but if the URL has one or more builder= arguments (or the old show= # argument, which is still accepted for backwards compatibility), we # use that set of builders instead. We still don't show anything # outside the config-file time set limited by categories=. showBuilders = request.args.get("show", []) showBuilders.extend(request.args.get("builder", [])) if showBuilders: builders = [b for b in builders if b.name in showBuilders] # now, if the URL has one or category= arguments, use them as a # filter: only show those builders which belong to one of the given # categories. showCategories = request.args.get("category", []) if showCategories: builders = [b for b in builders if b.category in showCategories] # If the URL has the failures_only=true argument, we remove all the # builders that are not currently red or won't be turning red at the end # of their current run. failuresOnly = request.args.get("failures_only", ["false"])[0] if failuresOnly.lower() == "true": builders = [b for b in builders if not self.isSuccess(b)] (changeNames, builderNames, timestamps, eventGrid, sourceEvents) = \ self.buildGrid(request, builders, changes) # start the table: top-header material locale_enc = locale.getdefaultlocale()[1] if locale_enc is not None: locale_tz = unicode(time.tzname[time.localtime()[-1]], locale_enc) else: locale_tz = unicode(time.tzname[time.localtime()[-1]]) ctx['tz'] = locale_tz ctx['changes_url'] = request.childLink("../changes") bn = ctx['builders'] = [] for name in builderNames: builder = status.getBuilder(name) top_box = ITopBox(builder).getBox(request) current_box = ICurrentBox(builder).getBox(status, brcounts) bn.append({ 'name': name, 'category': builder.category, 'url': request.childLink("../builders/%s" % urllib.quote(name, safe='')), 'top': top_box.text, 'top_class': top_box.class_, 'status': current_box.text, 'status_class': current_box.class_, }) ctx.update( self.phase2(request, changeNames + builderNames, timestamps, eventGrid, sourceEvents)) def with_args(req, remove_args=[], new_args=[], new_path=None): # sigh, nevow makes this sort of manipulation easier newargs = req.args.copy() for argname in remove_args: newargs[argname] = [] if "branch" in newargs: 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" % (urllib.quote(k), urllib.quote(v)) for k in newargs for v in newargs[k] ]) if new_path: new_url = new_path elif req.prepath: new_url = req.prepath[-1] else: new_url = '' if newquery: new_url += "?" + newquery return new_url if timestamps: bottom = timestamps[-1] ctx['nextpage'] = with_args(request, ["last_time"], [("last_time", str(int(bottom)))]) helpurl = path_to_root(request) + "waterfall/help" ctx['help_url'] = with_args(request, new_path=helpurl) if self.get_reload_time(request) is not None: ctx['no_reload_page'] = with_args(request, remove_args=["reload"]) template = request.site.buildbot_service.templates.get_template( "waterfall.html") ctx['mastername'] = ( request.site.buildbot_service.master.properties['mastername']) data = template.render(**unicodify(ctx)) return data