def builder_row(self, bn, req, branches, num_builds): status = self.getStatus(req) builder = status.getBuilder(bn) state = builder.getState()[0] if state == 'building': state = 'idle' row = tags.tr() builderLink = path_to_builder(req, builder) row(tags.td(class_="box %s" % (state, ))(tags.a(href=builderLink)(bn))) builds = sorted([ build for build in builder.getCurrentBuilds() if set(map_branches(branches)) & builder._getBuildBranches(build) ], key=lambda build: build.getNumber(), reverse=True) builds.extend( builder.generateFinishedBuilds(map_branches(branches), num_builds=num_builds)) if builds: for b in builds: url = path_to_build(req, b) try: label = b.getProperty("got_revision") except KeyError: label = None # Label should never be "None", but sometimes # buildbot has disgusting bugs. if not label or label == "None" or len(str(label)) > 20: label = "#%d" % b.getNumber() if b.isFinished(): text = b.getText() else: when = b.getETA() if when: text = [ "%s" % (formatInterval(when), ), "%s" % (time.strftime( "%H:%M:%S", time.localtime(time.time() + when)), ) ] else: text = [] row( tags.td(align="center", bgcolor=_backgroundColors[b.getResults()], class_=("LastBuild box ", build_get_class(b)))([ (element, tags.br) for element in [tags.a(href=url)(label)] + text ])) else: row(tags.td(class_="LastBuild box")("no build")) return row
def builder_row(self, bn, req, branches, num_builds): status = self.getStatus(req) builder = status.getBuilder(bn) state = builder.getState()[0] if state == 'building': state = 'idle' row = tags.tr() builderLink = path_to_builder(req, builder) row(tags.td(class_="box %s" % (state,)) (tags.a(href=builderLink)(bn))) builds = sorted([ build for build in builder.getCurrentBuilds() if set(map_branches(branches)) & builder._getBuildBranches(build) ], key=lambda build: build.getNumber(), reverse=True) builds.extend(builder.generateFinishedBuilds( map_branches(branches), num_builds=num_builds)) if builds: for b in builds: url = path_to_build(req, b) try: label = b.getProperty("got_revision") except KeyError: label = None # Label should never be "None", but sometimes # buildbot has disgusting bugs. if not label or label == "None" or len(str(label)) > 20: label = "#%d" % b.getNumber() if b.isFinished(): text = b.getText() else: when = b.getETA() if when: text = [ "%s" % (formatInterval(when),), "%s" % (time.strftime( "%H:%M:%S", time.localtime(time.time() + when)),) ] else: text = [] row(tags.td( align="center", bgcolor=_backgroundColors[b.getResults()], class_=("LastBuild box ", build_get_class(b)))([ (element, tags.br) for element in [tags.a(href=url)(label)] + text])) else: row(tags.td(class_="LastBuild box")("no build")) return row
def body(self, req): status = self.getStatus(req) control = self.getControl(req) builders = req.args.get("builder", status.getBuilderNames()) branches = [b for b in req.args.get("branch", []) if b] data = "" data += "<h2>Latest builds: %s</h2>\n" % ", ".join(branches) data += "<table>\n" building = False online = 0 base_builders_url = self.path_to_root(req) + "builders/" for bn in builders: base_builder_url = base_builders_url + urllib.quote(bn, safe='') builder = status.getBuilder(bn) data += "<tr>\n" data += '<td class="box"><a href="%s">%s</a></td>\n' \ % (base_builder_url, html.escape(bn)) builds = list(builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if builds: b = builds[0] url = (base_builder_url + "/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() text = ['<a href="%s">%s</a>' % (url, label)] text.extend(b.getText()) box = Box(text, b.getColor(), class_="LastBuild box %s" % build_get_class(b)) data += box.td(align="center") else: data += '<td class="LastBuild box" >no build</td>\n' current_box = ICurrentBox(builder).getBox(status) data += current_box.td(align="center") builder_status = builder.getState()[0] if builder_status == "building": building = True online += 1 elif builder_status != "offline": online += 1 data += "</table>\n" if control is not None: if building: stopURL = "builders/_all/stop" data += make_stop_form(stopURL, True, "Builds") if online: forceURL = "builders/_all/force" data += make_force_build_form(forceURL, True) return data
def content(self, req, cxt): status = self.getStatus(req) now, max_limit = datetime.now(), 600 builders = req.args.get("builder", []) branches = [b for b in req.args.get("branch", []) if b] g = status.generateFinishedBuilds( builders, map_branches(branches), num_builds=max_limit, max_search=max_limit ) cxt['refresh'] = self.get_reload_time(req) cxt['num_builds'] = max_limit cxt['branches'] = branches cxt['builders'] = builders builds = cxt['builds'] = [] for build in g: if not build.getResults(): continue start, end = build.getTimes() if (now - datetime.fromtimestamp(start)).days > 7: continue builds.append(self.get_line_values(req, build)) cxt['authz'] = self.getAuthz(req) template = req.site.buildbot_service.templates.get_template('weekly_fails.html') return template.render(**cxt)
def content(self, req, cxt): status = self.getStatus(req) numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) builders = req.args.get("builder", []) branches = [b for b in req.args.get("branch", []) if b] g = status.generateFinishedBuilds(builders, map_branches(branches), numbuilds, max_search=numbuilds) cxt['refresh'] = self.get_reload_time(req) cxt['num_builds'] = numbuilds cxt['branches'] = branches cxt['builders'] = builders got = 0 building = 0 online = 0 builders = cxt['builds'] = [] for build in g: got += 1 builders.append(self.get_line_values(req, build)) builder_status = build.getBuilder().getState()[0] if builder_status == "building": building += 1 online += 1 elif builder_status != "offline": online += 1 cxt['authz'] = self.getAuthz(req) cxt['num_online'] = online cxt['num_building'] = building template = req.site.buildbot_service.templates.get_template('onelineperbuild.html') return template.render(**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) yield defer.gatherResults(brstatus_ds) 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()) label = b.getProperty("got_revision") 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 buildForceContext(cxt, req, self.getBuildmaster(req)) template = req.site.buildbot_service.templates.get_template("builders.html") defer.returnValue(template.render(**cxt))
def content(self, req, cxt): status = self.getStatus(req) control = self.getControl(req) builders = req.args.get("builder", status.getBuilderNames()) branches = [b for b in req.args.get("branch", []) if b] cxt['branches'] = branches bs = cxt['builders'] = [] building = False 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) bld['current_box'] = current_box.td() builder_status = builder.getState()[0] if builder_status == "building": building = True online += 1 elif builder_status != "offline": online += 1 if control is not None: cxt['use_user_passwd'] = self.isUsingUserPasswd(req) if building: cxt['stop_url'] = "builders/_all/stop" if online: cxt['force_url'] = "builders/_all/force" template = req.site.buildbot_service.templates.get_template("oneboxperbuilder.html") return template.render(**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] 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) 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") return template.render(**cxt)
def content(self, req, cxt): numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) branches = [b for b in req.args.get("branch", []) if b] # walk backwards through all builds of a single builder g = self.builder.generateFinishedBuilds(map_branches(branches), numbuilds) cxt["builds"] = map(lambda b: self.get_line_values(req, b), g) cxt.update(dict(num_builds=numbuilds, builder_name=self.builder_name, branches=branches)) template = req.site.buildbot_service.templates.get_template("onelineperbuildonebuilder.html") return template.render(**cxt)
def asDict(self, request, params=None): include_steps = True include_props = True # We pass params only if we are doing this directly and not from a user args = request.args if params is not None: args = params if "steps" in args: include_steps = True if "1" in args["steps"] else False if "props" in args: include_props = True if "1" in args["props"] else False results = getResultsArg(request) if self.builder_status is not None: codebases = {} getCodebasesArg(request=request, codebases=codebases) encoding = getRequestCharset(request) branches = [ b.decode(encoding) for b in request.args.get("branch", []) if b ] builds = yield self.builder_status.generateFinishedBuildsAsync( branches=map_branches(branches), codebases=codebases, results=results, num_builds=self.number) defer.returnValue([ b.asDict(request, include_artifacts=True, include_failure_url=True, include_steps=include_steps, include_properties=include_props) for b in builds ]) return if self.slave_status is not None: slavename = self.slave_status.getName() builds = yield self.status.generateFinishedBuildsAsync( num_builds=self.number, results=results, slavename=slavename) defer.returnValue([ rb.asDict(request=request, include_steps=False) for rb in builds ]) return
def content(self, req, cxt): numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) branches = [b for b in req.args.get("branch", []) if b] # walk backwards through all builds of a single builder g = self.builder.generateFinishedBuilds(map_branches(branches), numbuilds) cxt['builds'] = map(lambda b: self.get_line_values(req, b), g) cxt.update(dict(num_builds=numbuilds, builder_name=self.builder_name, branches=branches)) template = req.site.buildbot_service.templates.get_template('onelineperbuildonebuilder.html') return template.render(**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] 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) 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"] = online cxt["num_online"] = online template = req.site.buildbot_service.templates.get_template("builders.html") return template.render(**cxt)
def getBox(self, req): assert interfaces.IBuilderStatus(self.original) branches = [b for b in req.args.get("branch", []) if b] builder = self.original builds = list(builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if not builds: return Box(["none"], class_="LastBuild") b = builds[0] url = path_to_build(req, b) text = b.getText() tests_failed = b.getSummaryStatistic('tests-failed', operator.add, 0) if tests_failed: text.extend(["Failed tests: %d" % tests_failed]) # TODO: maybe add logs? class_ = build_get_class(b) return Box(text, urlbase=url, class_="LastBuild %s" % class_)
def body(self, req): status = self.getStatus(req) control = self.getControl(req) numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) builders = req.args.get("builder", []) branches = [b for b in req.args.get("branch", []) if b] g = status.generateFinishedBuilds(builders, map_branches(branches), numbuilds, max_search=numbuilds) data = "" # really this is "up to %d builds" html_branches = map(html.escape, branches) data += "<h1>Last %d finished builds: %s</h1>\n" % \ (numbuilds, ", ".join(html_branches)) if builders: html_builders = map(html.escape, builders) data += ("<p>of builders: %s</p>\n" % (", ".join(html_builders))) data += "<ul>\n" got = 0 building = False online = 0 for build in g: got += 1 data += " <li>" + self.make_line(req, build) + "</li>\n" builder_status = build.getBuilder().getState()[0] if builder_status == "building": building = True online += 1 elif builder_status != "offline": online += 1 if not got: data += " <li>No matching builds found</li>\n" data += "</ul>\n" if control is not None: if building: stopURL = "builders/_all/stop" data += make_stop_form(stopURL, self.isUsingUserPasswd(req), True, "Builds") if online: forceURL = "builders/_all/force" data += make_force_build_form(forceURL, self.isUsingUserPasswd(req), True) return data
def getBox(self, req): assert interfaces.IBuilderStatus(self.original) branches = [b for b in req.args.get("branch", []) if b] builder = self.original builds = list(builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if not builds: return Box(["none"], "white", class_="LastBuild") b = builds[0] name = b.getBuilder().getName() number = b.getNumber() url = path_to_build(req, b) text = b.getText() # TODO: maybe add logs? # TODO: add link to the per-build page at 'url' c = b.getColor() class_ = build_get_class(b) return Box(text, c, class_="LastBuild %s" % class_)
def getBox(self, req): assert interfaces.IBuilderStatus(self.original) branches = [b for b in req.args.get("branch", []) if b] builder = self.original builds = list( builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if not builds: return Box(["none"], "white", class_="LastBuild") b = builds[0] name = b.getBuilder().getName() number = b.getNumber() url = path_to_build(req, b) text = b.getText() # TODO: maybe add logs? # TODO: add link to the per-build page at 'url' c = b.getColor() class_ = build_get_class(b) return Box(text, c, class_="LastBuild %s" % class_)
def content(self, req, cxt): status = self.getStatus(req) try: numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) except ValueError: numbuilds = 10 builders = req.args.get("builder", []) branches = [b for b in req.args.get("branch", []) if b] g = status.generateFinishedBuilds(builders, map_branches(branches), numbuilds, max_search=numbuilds) cxt['refresh'] = self.get_reload_time(req) cxt['num_builds'] = numbuilds cxt['branches'] = branches cxt['builders'] = builders builds = cxt['builds'] = [] for build in g: builds.append(self.get_line_values(req, build)) cxt['authz'] = self.getAuthz(req) # get information on the builders - mostly just a count building = 0 online = 0 for bn in builders: builder = status.getBuilder(bn) builder_status = builder.getState()[0] if builder_status == "building": building += 1 online += 1 elif builder_status != "offline": online += 1 cxt['num_online'] = online cxt['num_building'] = building template = req.site.buildbot_service.templates.get_template( 'onelineperbuild.html') return template.render(**cxt)
def body(self, req): status = self.getStatus(req) numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) branches = [b for b in req.args.get("branch", []) if b] # walk backwards through all builds of a single builder g = self.builder.generateFinishedBuilds(map_branches(branches), numbuilds) data = "" data += "<h1>Last %d builds of builder %s: %s</h1>\n" % (numbuilds, self.builder_name, ", ".join(branches)) data += "<ul>\n" got = 0 for build in g: got += 1 data += " <li>" + self.make_line(req, build) + "</li>\n" if not got: data += " <li>No matching builds found</li>\n" data += "</ul>\n" return data
def builder_dict(self, builder, codebases, request, branches, base_build_dict, include_build_steps, include_build_props, include_pending_builds): d = yield builder.asDict_async(codebases, request, base_build_dict, include_build_steps, include_build_props, include_pending_builds) #Get latest build builds = yield builder.generateFinishedBuildsAsync( branches=map_branches(branches), codebases=codebases, num_builds=1, useCache=True) if len(builds) > 0: d['latestBuild'] = builds[0].asBaseDict(request, include_artifacts=True, include_failure_url=True) defer.returnValue(d)
def content(self, req, cxt): status = self.getStatus(req) try: numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) except ValueError: numbuilds = 10 builders = req.args.get("builder", []) branches = [b for b in req.args.get("branch", []) if b] g = status.generateFinishedBuilds(builders, map_branches(branches), numbuilds, max_search=numbuilds) cxt['refresh'] = self.get_reload_time(req) cxt['num_builds'] = numbuilds cxt['branches'] = branches cxt['builders'] = builders builds = cxt['builds'] = [] for build in g: builds.append(self.get_line_values(req, build)) cxt['authz'] = self.getAuthz(req) # get information on the builders - mostly just a count building = 0 online = 0 for bn in builders: builder = status.getBuilder(bn) builder_status = builder.getState()[0] if builder_status == "building": building += 1 online += 1 elif builder_status != "offline": online += 1 cxt['num_online'] = online cxt['num_building'] = building template = req.site.buildbot_service.templates.get_template('onelineperbuild.html') return template.render(**cxt)
def body(self, req): status = self.getStatus(req) numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) branches = [b for b in req.args.get("branch", []) if b] # walk backwards through all builds of a single builder g = self.builder.generateFinishedBuilds(map_branches(branches), numbuilds) data = "" data += ("<h1>Last %d builds of builder %s: %s</h1>\n" % (numbuilds, self.builder_name, ", ".join(branches))) data += "<ul>\n" got = 0 for build in g: got += 1 data += " <li>" + self.make_line(req, build) + "</li>\n" if not got: data += " <li>No matching builds found</li>\n" data += "</ul>\n" return data
def content(self, req, cxt): status = self.getStatus(req) control = self.getControl(req) numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) builders = req.args.get("builder", []) branches = [b for b in req.args.get("branch", []) if b] g = status.generateFinishedBuilds(builders, map_branches(branches), numbuilds, max_search=numbuilds) cxt['refresh'] = self.get_reload_time(req) cxt['num_builds'] = numbuilds cxt['branches'] = branches cxt['builders'] = builders got = 0 building = False online = cxt['online_count'] = 0 builders = cxt['builds'] = [] for build in g: got += 1 builders.append(self.get_line_values(req, build)) builder_status = build.getBuilder().getState()[0] if builder_status == "building": building = True online += 1 elif builder_status != "offline": online += 1 if control is not None: cxt['use_user_passwd'] = self.isUsingUserPasswd(req) if building: cxt['stop_url'] = "builders/_all/stop" if online: cxt['force_url'] = "builders/_all/force" template = req.site.buildbot_service.templates.get_template('onelineperbuild.html') return template.render(**cxt)
def content(self, req, cxt): status = self.getStatus(req) numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) builders = req.args.get("builder", []) branches = [b for b in req.args.get("branch", []) if b] g = status.generateFinishedBuilds(builders, map_branches(branches), numbuilds, max_search=numbuilds) cxt['refresh'] = self.get_reload_time(req) cxt['num_builds'] = numbuilds cxt['branches'] = branches cxt['builders'] = builders got = 0 building = 0 online = 0 builders = cxt['builds'] = [] for build in g: got += 1 builders.append(self.get_line_values(req, build)) builder_status = build.getBuilder().getState()[0] if builder_status == "building": building += 1 online += 1 elif builder_status != "offline": online += 1 cxt['authz'] = self.getAuthz(req) cxt['num_online'] = online cxt['num_building'] = building template = req.site.buildbot_service.templates.get_template( 'onelineperbuild.html') return template.render(**cxt)
def buildGrid(self, request, builders): debug = False # TODO: see if we can use a cached copy showEvents = False if request.args.get("show_events", ["false"])[0].lower() == "true": showEvents = True filterCategories = request.args.get('category', []) filterBranches = [b for b in request.args.get("branch", []) if b] filterBranches = map_branches(filterBranches) maxTime = int(request.args.get("last_time", [util.now()])[0]) if "show_time" in request.args: minTime = maxTime - int(request.args["show_time"][0]) elif "first_time" in request.args: minTime = int(request.args["first_time"][0]) else: minTime = None spanLength = 10 # ten-second chunks maxPageLen = int(request.args.get("num_events", [200])[0]) # first step is to walk backwards in time, asking each column # (commit, all builders) if they have any events there. Build up the # array of events, and stop when we have a reasonable number. commit_source = self.getChangemaster(request) lastEventTime = util.now() sources = [commit_source] + builders changeNames = ["changes"] builderNames = map(lambda builder: builder.getName(), builders) sourceNames = changeNames + builderNames sourceEvents = [] sourceGenerators = [] def get_event_from(g): try: while True: e = g.next() # e might be builder.BuildStepStatus, # builder.BuildStatus, builder.Event, # waterfall.Spacer(builder.Event), or changes.Change . # The showEvents=False flag means we should hide # builder.Event . if not showEvents and isinstance(e, builder.Event): continue break event = interfaces.IStatusEvent(e) if debug: log.msg("gen %s gave1 %s" % (g, event.getText())) except StopIteration: event = None return event for s in sources: gen = insertGaps(s.eventGenerator(filterBranches, filterCategories), showEvents, lastEventTime) sourceGenerators.append(gen) # get the first event sourceEvents.append(get_event_from(gen)) eventGrid = [] timestamps = [] lastEventTime = 0 for e in sourceEvents: if e and e.getTimes()[0] > lastEventTime: lastEventTime = e.getTimes()[0] if lastEventTime == 0: lastEventTime = util.now() spanStart = lastEventTime - spanLength debugGather = 0 while 1: if debugGather: log.msg("checking (%s,]" % spanStart) # the tableau of potential events is in sourceEvents[]. The # window crawls backwards, and we examine one source at a time. # If the source's top-most event is in the window, is it pushed # onto the events[] array and the tableau is refilled. This # continues until the tableau event is not in the window (or is # missing). spanEvents = [] # for all sources, in this span. row of eventGrid firstTimestamp = None # timestamp of first event in the span lastTimestamp = None # last pre-span event, for next span for c in range(len(sourceGenerators)): events = [] # for this source, in this span. cell of eventGrid event = sourceEvents[c] while event and spanStart < event.getTimes()[0]: # to look at windows that don't end with the present, # condition the .append on event.time <= spanFinish if not IBox(event, None): log.msg("BAD EVENT", event, event.getText()) assert 0 if debug: log.msg("pushing", event.getText(), event) events.append(event) starts, finishes = event.getTimes() firstTimestamp = util.earlier(firstTimestamp, starts) event = get_event_from(sourceGenerators[c]) if debug: log.msg("finished span") if event: # this is the last pre-span event for this source lastTimestamp = util.later(lastTimestamp, event.getTimes()[0]) if debugGather: log.msg(" got %s from %s" % (events, sourceNames[c])) sourceEvents[c] = event # refill the tableau spanEvents.append(events) # only show events older than maxTime. This makes it possible to # visit a page that shows what it would be like to scroll off the # bottom of this one. if firstTimestamp is not None and firstTimestamp <= maxTime: eventGrid.append(spanEvents) timestamps.append(firstTimestamp) if lastTimestamp: spanStart = lastTimestamp - spanLength else: # no more events break if minTime is not None and lastTimestamp < minTime: break if len(timestamps) > maxPageLen: break # now loop # loop is finished. now we have eventGrid[] and timestamps[] if debugGather: log.msg("finished loop") assert(len(timestamps) == len(eventGrid)) return (changeNames, builderNames, timestamps, eventGrid, sourceEvents)
def body(self, req): from twisted.web import html status = self.getStatus(req) control = self.getControl(req) builders = req.args.get("builder", status.getBuilderNames()) branches = [b for b in req.args.get("branch", []) if b] building = False online = 0 base_builders_url = self.path_to_root(req) + "builders/" all_builders = [html.escape(bn) for bn in builders] trunk_builders = [bn for bn in all_builders if bn.startswith('trunk')] stable_builders = [bn for bn in all_builders if bn.startswith('stable')] trunk_builders_link = 'waterfall?builder='+'&builder='.join(trunk_builders) stable_builders_link = 'waterfall?builder=' + '&builder='.join(stable_builders) tr_b = False st_b = False data = "" data += "<table class='grid' id='latest_builds'>" for bn in all_builders: if (bn.startswith('stable')) and (not st_b): st_b = True data += "<table class='grid' id='stable_builds'>\n" data += "<tr class='grid-header'><td class='grid-cell'><span>Latest Stable</span></td><td class='grid-cell'><a href=%s>Stable Tests</a></td><td class='grid-cell'><a href='Changelog/5.0'>Changelog</a></td></tr><\n>"[:-3]%(stable_builders_link) if (bn.startswith('trunk')) and (not tr_b): tr_b = True data += "<tr id='trunk_builds'><td colspan='3'></td>" data += "<tr class='grid-header'><td class='grid-cell'><span>Latest Trunk</span></td><td class='grid-cell'><a href='%s'>Trunk Tests</a></td><td class='grid-cell'><a href='Changelog/trunk'>Changelog</a></td></tr><\n>"[:-3]%(trunk_builders_link) base_builder_url = base_builders_url + urllib.quote(bn, safe='') builder = status.getBuilder(bn) data += "<tr class='grid-row'>\n" data += '<td class="grid-cell"><a href="%s">%s</a></td>\n' \ % (base_builder_url, html.escape(bn)) builds = list(builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if builds: b = builds[0] url = (base_builder_url + "/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() text = ['<a href="%s">%s</a>' % (url, label)] text.append(' '.join(b.getText())) box = Box(text, b.getColor(), class_="LastBuild box %s" % build_get_class(b)) data += box.td(class_="grid-cell",align="center") else: data += '<td class="grid-cell" align="center">no build</td>\n' current_box = ICurrentBox(builder).getBox(status) data += current_box.td(class_="grid-cell",align="center") data+='</tr>' builder_status = builder.getState()[0] if builder_status == "building": building = True online += 1 elif builder_status != "offline": online += 1 data += "</table></table>\n" if control is not None: if building: stopURL = "builders/_all/stop" data += make_stop_form(stopURL, True, "Builds") if online: forceURL = "builders/_all/force" data += make_force_build_form(forceURL, True) return data
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(**cxt)
def body(self, req): status = self.getStatus(req) authz = self.getAuthz(req) builders = req.args.get("builder", status.getBuilderNames(categories=self.categories)) branches = [b for b in req.args.get("branch", []) if b] if not branches: branches = ["trunk"] if branches and "trunk" not in branches: defaultCount = "1" else: defaultCount = "10" num_builds = int(req.args.get("num_builds", [defaultCount])[0]) tag = tags.div() tag(tags.script(src="txbuildbot.js")) tag(tags.h2(style="float:left; margin-top:0")("Latest builds: ", ", ".join(branches))) form = tags.form(method="get", action="", style="float:right", onsubmit="return checkBranch(branch.value)") form(tags.input(type="test", name="branch", placeholder=branches[0], size="40")) form(tags.input(type="submit", value="View")) if (yield authz.actionAllowed('forceAllBuilds', req)): # XXX: Unsafe interpolation form(tags.button(type="button", onclick="forceBranch(branch.value || %r, %r)" % (branches[0], self.categories,) )("Force")) tag(form) table = tags.table(style="clear:both") tag(table) for bn in builders: builder = status.getBuilder(bn) state = builder.getState()[0] if state == 'building': state = 'idle' row = tags.tr() table(row) builderLink = path_to_builder(req, builder) row(tags.td(class_="box %s" % (state,))(tags.a(href=builderLink)(bn))) builds = sorted([ build for build in builder.getCurrentBuilds() if build.getSourceStamps()[0].branch in map_branches(branches) ], key=lambda build: build.getNumber(), reverse=True) builds.extend(builder.generateFinishedBuilds(map_branches(branches), num_builds=num_builds)) if builds: for b in builds: url = path_to_build(req, b) try: label = b.getProperty("got_revision") except KeyError: label = None # Label should never be "None", but sometimes # buildbot has disgusting bugs. if not label or label == "None" or len(str(label)) > 20: label = "#%d" % b.getNumber() if b.isFinished(): text = b.getText() else: when = b.getETA() if when: text = [ "%s" % (formatInterval(when),), "%s" % (time.strftime("%H:%M:%S", time.localtime(time.time() + when)),) ] else: text = [] row(tags.td( align="center", bgcolor=_backgroundColors[b.getResults()], class_=("LastBuild box ", build_get_class(b)))([ (element, tags.br) for element in [tags.a(href=url)(label)] + text]) ) else: row(tags.td(class_="LastBuild box")("no build")) defer.returnValue((yield flattenString(req, tag)))
def body(self, req): status = self.getStatus(req) authz = self.getAuthz(req) builders = req.args.get( "builder", status.getBuilderNames(categories=self.categories)) branches = [b for b in req.args.get("branch", []) if b] if not branches: branches = ["trunk"] if branches and "trunk" not in branches: defaultCount = "1" else: defaultCount = "10" num_builds = int(req.args.get("num_builds", [defaultCount])[0]) tag = tags.div() tag(tags.script(src="txbuildbot.js")) tag( tags.h2(style="float:left; margin-top:0")("Latest builds: ", ", ".join(branches))) form = tags.form(method="get", action="", style="float:right", onsubmit="return checkBranch(branch.value)") form( tags.input(type="test", name="branch", placeholder=branches[0], size="40")) form(tags.input(type="submit", value="View")) if (yield authz.actionAllowed('forceAllBuilds', req)): # XXX: Unsafe interpolation form( tags.button(type="button", onclick="forceBranch(branch.value || %r, %r)" % ( branches[0], self.categories, ))("Force")) tag(form) table = tags.table(style="clear:both") tag(table) for bn in builders: builder = status.getBuilder(bn) state = builder.getState()[0] if state == 'building': state = 'idle' row = tags.tr() table(row) builderLink = path_to_builder(req, builder) row( tags.td(class_="box %s" % (state, ))( tags.a(href=builderLink)(bn))) builds = sorted([ build for build in builder.getCurrentBuilds() if build.getSourceStamp().branch in map_branches(branches) ], key=lambda build: build.getNumber(), reverse=True) builds.extend( builder.generateFinishedBuilds(map_branches(branches), num_builds=num_builds)) if builds: for b in builds: url = path_to_build(req, b) try: label = b.getProperty("got_revision") except KeyError: label = None # Label should never be "None", but sometimes # buildbot has disgusting bugs. if not label or label == "None" or len(str(label)) > 20: label = "#%d" % b.getNumber() if b.isFinished(): text = b.getText() else: when = b.getETA() if when: text = [ "%s" % (formatInterval(when), ), "%s" % (time.strftime( "%H:%M:%S", time.localtime(time.time() + when)), ) ] else: text = [] row( tags.td( align="center", bgcolor=_backgroundColors[b.getResults()], class_=("LastBuild box ", build_get_class(b)))([ (element, tags.br) for element in [tags.a(href=url)(label)] + text ])) else: row(tags.td(class_="LastBuild box")("no build")) defer.returnValue((yield flattenString(req, tag)))
def content(self, req, cxt): status = self.getStatus(req) # building = False # online = 0 req.setHeader("Cache-Control", "no-cache") # base_builders_url = "buildersresource/" base_builders_url = "builders/" cats = req.args.get("groups", False) if cats is not False: cats = cats.split(",") else: cats = None builders = req.args.get("builder", status.getBuilderNames(cats)) branches = [b for b in req.args.get("branch", []) if b] num_cols = get_args_int(req.args, "num", 5) cxt["num_cols"] = num_cols cxt["builders"] = [] builders_grouped = {} groups_seq = {} # sequence of groups for bn in builders: base_builder_url = base_builders_url + urllib.quote(bn, safe="") builder = status.getBuilder(bn) bld_props = status.botmaster.builders[bn].properties # hack into the structure categ = builder.category bname = bn if categ and bn.startswith(categ + "-"): bname = bname[len(categ) + 1 :] bname = html.escape(bname.replace("-", " ", 1)) bldr_cxt = {"name": bname, "url": base_builder_url, "builds": [], "sequence": bld_props.get("sequence", 10)} if categ: if bld_props.get("group_public", True): builders_grouped.setdefault(categ, []).append(bldr_cxt) if "group_seq" in bld_props: groups_seq[categ] = bld_props["group_seq"] else: cxt["builders"].append(bldr_cxt) # It is difficult to do paging here, because we are already iterating over the # builders, so won't have the same build names or rev-ids. builds = list(builder.generateFinishedBuilds(map_branches(branches), num_builds=num_cols)) # builds.reverse() bldr_cxt["builds"] = [] for build in builds[:num_cols]: url = base_builder_url + "/builds/%d" % build.getNumber() build_cxt = {"url": url} bldr_cxt["builds"].append(build_cxt) try: ss = build.getSourceStamp() commiter = "" if list(build.getResponsibleUsers()): for who in build.getResponsibleUsers(): commiter += "%s" % html.escape(reduce_eml(who)) else: commiter += "No Commiter Found !" if ss.revision: revision = ss.revision label = "%s-%s: %s" % (str(revision), commiter, "".join(build.text)) except Exception: label = None if not label: label = "#%d" % build.getNumber() tftime = time.strftime("%a %d, %H:%M:%S", time.localtime(build.getTimes()[1])) ttitle = "Test at: %s\n%s" % (ustr(tftime), html.escape(ustr(build.getReason()))) class_b = "build%s" % build_get_class(build) build_cxt.update( { "label": label, "commiter": commiter, "tftime": tftime, "ttitle": ttitle, "last_t": ustr(last_change(ss, True)), "class_b": class_b, } ) builder_status = builder.getState()[0] bldr_cxt["status"] = builder_status # Now, sort the builders and grouped: cxt["builders"].sort(key=lambda bld: bld["sequence"]) for bldrs in builders_grouped.values(): bldrs.sort(key=lambda bld: bld["sequence"]) cxt["builders_grouped"] = [] # will be list of tuples for gk, bldrs in builders_grouped.items(): cxt["builders_grouped"].append((groups_seq.get(gk, 10), gk, bldrs)) template = req.site.buildbot_service.templates.get_template(self.tpl_page) return template.render(**cxt)
def buildGrid(self, request, builders): debug = False # TODO: see if we can use a cached copy showEvents = False if request.args.get("show_events", ["true"])[0].lower() == "true": showEvents = True filterBranches = [b for b in request.args.get("branch", []) if b] filterBranches = map_branches(filterBranches) maxTime = int(request.args.get("last_time", [util.now()])[0]) if "show_time" in request.args: minTime = maxTime - int(request.args["show_time"][0]) elif "first_time" in request.args: minTime = int(request.args["first_time"][0]) else: minTime = None spanLength = 10 # ten-second chunks maxPageLen = int(request.args.get("num_events", [200])[0]) # first step is to walk backwards in time, asking each column # (commit, all builders) if they have any events there. Build up the # array of events, and stop when we have a reasonable number. commit_source = self.getChangemaster(request) lastEventTime = util.now() sources = [commit_source] + builders changeNames = ["changes"] builderNames = map(lambda builder: builder.getName(), builders) sourceNames = changeNames + builderNames sourceEvents = [] sourceGenerators = [] def get_event_from(g): try: while True: e = g.next() # e might be builder.BuildStepStatus, # builder.BuildStatus, builder.Event, # waterfall.Spacer(builder.Event), or changes.Change . # The showEvents=False flag means we should hide # builder.Event . if not showEvents and isinstance(e, builder.Event): continue break event = interfaces.IStatusEvent(e) if debug: log.msg("gen %s gave1 %s" % (g, event.getText())) except StopIteration: event = None return event for s in sources: gen = insertGaps(s.eventGenerator(filterBranches), lastEventTime) sourceGenerators.append(gen) # get the first event sourceEvents.append(get_event_from(gen)) eventGrid = [] timestamps = [] lastEventTime = 0 for e in sourceEvents: if e and e.getTimes()[0] > lastEventTime: lastEventTime = e.getTimes()[0] if lastEventTime == 0: lastEventTime = util.now() spanStart = lastEventTime - spanLength debugGather = 0 while 1: if debugGather: log.msg("checking (%s,]" % spanStart) # the tableau of potential events is in sourceEvents[]. The # window crawls backwards, and we examine one source at a time. # If the source's top-most event is in the window, is it pushed # onto the events[] array and the tableau is refilled. This # continues until the tableau event is not in the window (or is # missing). spanEvents = [] # for all sources, in this span. row of eventGrid firstTimestamp = None # timestamp of first event in the span lastTimestamp = None # last pre-span event, for next span for c in range(len(sourceGenerators)): events = [] # for this source, in this span. cell of eventGrid event = sourceEvents[c] while event and spanStart < event.getTimes()[0]: # to look at windows that don't end with the present, # condition the .append on event.time <= spanFinish if not IBox(event, None): log.msg("BAD EVENT", event, event.getText()) assert 0 if debug: log.msg("pushing", event.getText(), event) events.append(event) starts, finishes = event.getTimes() firstTimestamp = util.earlier(firstTimestamp, starts) event = get_event_from(sourceGenerators[c]) if debug: log.msg("finished span") if event: # this is the last pre-span event for this source lastTimestamp = util.later(lastTimestamp, event.getTimes()[0]) if debugGather: log.msg(" got %s from %s" % (events, sourceNames[c])) sourceEvents[c] = event # refill the tableau spanEvents.append(events) # only show events older than maxTime. This makes it possible to # visit a page that shows what it would be like to scroll off the # bottom of this one. if firstTimestamp is not None and firstTimestamp <= maxTime: eventGrid.append(spanEvents) timestamps.append(firstTimestamp) if lastTimestamp: spanStart = lastTimestamp - spanLength else: # no more events break if minTime is not None and lastTimestamp < minTime: break if len(timestamps) > maxPageLen: break # now loop # loop is finished. now we have eventGrid[] and timestamps[] if debugGather: log.msg("finished loop") assert (len(timestamps) == len(eventGrid)) return (changeNames, builderNames, timestamps, eventGrid, sourceEvents)
def content(self, req, cxt): status = self.getStatus(req) # building = False # online = 0 req.setHeader('Cache-Control', 'no-cache') # base_builders_url = "buildersresource/" base_builders_url = "builders/" cats = req.args.get('groups', False) if cats is not False: cats = cats.split(',') else: cats = None builders = req.args.get("builder", status.getBuilderNames(cats)) branches = [b for b in req.args.get("branch", []) if b] num_cols = get_args_int(req.args, 'num', 5) cxt['num_cols'] = num_cols cxt['builders'] = [] builders_grouped = {} groups_seq = {} # sequence of groups for bn in builders: base_builder_url = base_builders_url + urllib.quote(bn, safe='') builder = status.getBuilder(bn) bld_props = status.botmaster.builders[bn].properties # hack into the structure categ = builder.category bname = bn if categ and bn.startswith(categ + '-'): bname = bname[len(categ)+1:] bname = html.escape(bname.replace('-',' ', 1)) bldr_cxt = { 'name': bname , 'url': base_builder_url, 'builds': [], 'sequence': bld_props.get('sequence', 10) } if categ: if bld_props.get('group_public', True): builders_grouped.setdefault(categ, []).append(bldr_cxt) if 'group_seq' in bld_props: groups_seq[categ] = bld_props['group_seq'] else: cxt['builders'].append(bldr_cxt) # It is difficult to do paging here, because we are already iterating over the # builders, so won't have the same build names or rev-ids. builds = list(builder.generateFinishedBuilds(map_branches(branches), num_builds=num_cols)) # builds.reverse() bldr_cxt['builds'] = [] for build in builds[:num_cols]: url = (base_builder_url + "/builds/%d" % build.getNumber()) build_cxt = {'url': url} bldr_cxt['builds'].append(build_cxt) try: ss = build.getSourceStamp() commiter = "" if list(build.getResponsibleUsers()): for who in build.getResponsibleUsers(): commiter += "%s" % html.escape(reduce_eml(who)) else: commiter += "No Commiter Found !" if ss.revision: revision = ss.revision label = '%s-%s: %s' % (str(revision), commiter, ''.join(build.text)) except Exception: label = None if not label: label = "#%d" % build.getNumber() tftime = time.strftime('%a %d, %H:%M:%S', time.localtime(build.getTimes()[1])) ttitle = 'Test at: %s\n%s' %(ustr(tftime), html.escape(ustr(build.getReason()))) class_b = "build%s" % build_get_class(build) build_cxt.update({ 'label': label, 'commiter': commiter, 'tftime': tftime, 'ttitle': ttitle, 'last_t': ustr(last_change(ss, True)), 'class_b': class_b }) builder_status = builder.getState()[0] bldr_cxt['status'] = builder_status # Now, sort the builders and grouped: cxt['builders'].sort(key=lambda bld: bld['sequence']) for bldrs in builders_grouped.values(): bldrs.sort(key=lambda bld: bld['sequence']) cxt['builders_grouped'] = [] # will be list of tuples for gk, bldrs in builders_grouped.items(): cxt['builders_grouped'].append((groups_seq.get(gk,10), gk, bldrs)) template = req.site.buildbot_service.templates.get_template(self.tpl_page) return template.render(**cxt)
def content(self, req, cxt): status = self.getStatus(req) encoding = getRequestCharset(req) showTags = req.args.get("tag", []) if not showTags: showTags = req.args.get("category", []) if not showTags: showTags = None builders = req.args.get("builder", status.getBuilderNames(tags=showTags)) branches = [ b.decode(encoding) 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) yield defer.gatherResults(brstatus_ds) 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=''), 'tags': status.getBuilder(bn).tags, '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()) label = None all_got_revisions = b.getAllGotRevisions() # If len = 1 then try if revision can be used as label. if len(all_got_revisions) == 1: label = all_got_revisions[all_got_revisions.keys()[0]] 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 buildForceContext(cxt, req, self.getBuildmaster(req)) template = req.site.buildbot_service.templates.get_template( "builders.html") defer.returnValue(template.render(**cxt))
def body(self, req): status = self.getStatus(req) control = self.getControl(req) builders = req.args.get("builder", status.getBuilderNames()) branches = [b for b in req.args.get("branch", []) if b] data = "" data += "<h2>Latest builds: %s</h2>\n" % ", ".join(branches) data += "<table>\n" building = False online = 0 base_builders_url = self.path_to_root(req) + "builders/" for bn in builders: base_builder_url = base_builders_url + urllib.quote(bn, safe='') builder = status.getBuilder(bn) data += "<tr>\n" data += '<td class="box"><a href="%s">%s</a></td>\n' \ % (base_builder_url, html.escape(bn)) builds = list( builder.generateFinishedBuilds(map_branches(branches), num_builds=1)) if builds: b = builds[0] url = (base_builder_url + "/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() text = ['<a href="%s">%s</a>' % (url, label)] text.extend(b.getText()) box = Box(text, b.getColor(), class_="LastBuild box %s" % build_get_class(b)) data += box.td(align="center") else: data += '<td class="LastBuild box" >no build</td>\n' current_box = ICurrentBox(builder).getBox(status) data += current_box.td(align="center") builder_status = builder.getState()[0] if builder_status == "building": building = True online += 1 elif builder_status != "offline": online += 1 data += "</table>\n" if control is not None: if building: stopURL = "builders/_all/stop" data += make_stop_form(stopURL, True, "Builds") if online: forceURL = "builders/_all/force" data += make_force_build_form(forceURL, True) return data
def content(self, req, cxt): status = self.getStatus(req) encoding = getRequestCharset(req) builders = req.args.get("builder", status.getBuilderNames()) branches = [b.decode(encoding) 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) yield defer.gatherResults(brstatus_ds) 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() label = None all_got_revisions = b.getAllGotRevisions() # If len = 1 then try if revision can be used as label. if len(all_got_revisions) == 1: label = all_got_revisions[all_got_revisions.keys()[0]] 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 buildForceContext(cxt, req, self.getBuildmaster(req)) template = req.site.buildbot_service.templates.get_template("builders.html") defer.returnValue(template.render(**cxt))