class ForceAction(ActionResource): @defer.inlineCallbacks def force(self, req, builderNames): master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] if schedulername == "<unknown>": try: for scheduler in master.allSchedulers(): if isinstance( scheduler, ForceScheduler ) and builderNames[0] in scheduler.builderNames: schedulername = scheduler.name break else: raise RuntimeError("Could not find force scheduler") except: defer.returnValue((path_to_builder( req, self.builder_status ), "forcescheduler arg not found, and could not find a default force scheduler for builderName" )) return args = {} # decode all of the args encoding = getRequestCharset(req) for name, argl in req.args.iteritems(): if name == "checkbox": # damn html's ungeneric checkbox implementation... for cb in argl: args[cb.decode(encoding)] = True else: args[name] = [arg.decode(encoding) for arg in argl] for scheduler in master.allSchedulers(): if schedulername == scheduler.name: try: yield scheduler.force(owner, builderNames, **args) msg = "" except ValidationError, e: msg = html.escape(e.message.encode('ascii', 'ignore')) break # send the user back to the proper page returnpage = args.get("returnpage", None) if "builders" in returnpage: defer.returnValue( (path_to_builders(req, self.builder_status.getProject()))) elif "builders_json" in returnpage: s = self.getStatus(req) defer.returnValue( (s.getBuildbotURL() + path_to_json_builders(req, self.builder_status.getProject()))) elif "pending_json" in returnpage and builderNames > 0: s = self.getStatus(req) defer.returnValue((s.getBuildbotURL() + path_to_json_pending(req, builderNames[0]))) defer.returnValue((path_to_builder(req, self.builder_status)))
def content(self, req, cxt): s = self.step_status b = s.getBuild() builderstatus = b.getBuilder() project = builderstatus.getProject() cxt['name'] = builderstatus.getFriendlyName() cxt['path_to_builder'] = path_to_builder(req, builderstatus) cxt['path_to_builders'] = path_to_builders(req, project) cxt['path_to_codebases'] = path_to_codebases(req, project) cxt['path_to_build'] = path_to_build(req, b) cxt['build_number'] = b.getNumber() cxt['step_name'] = s.getName() cxt['selectedproject'] = project logs = cxt['logs'] = [] for l in s.getLogs(): # 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.append({ 'has_contents': l.hasContents(), 'name': l.getName(), 'link': req.childLink("logs/%s" % urllib.quote(l.getName())) }) stepStatistics = s.getStatistics() statistics = cxt['statistics'] = [] for stat in stepStatistics: statistics.append({'name': stat, 'value': stepStatistics[stat]}) 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(b=b, s=s, result_css=css_classes[s.getResults()[0]])) template = req.site.buildbot_service.templates.get_template( "buildstep.html") return template.render(**cxt)
def performAction(self, req): try: request_id = req.args.get("id", [None])[0] if request_id == "all": cancel_all = True else: cancel_all = False request_id = int(request_id) except: request_id = None authz = self.getAuthz(req) if request_id: c = interfaces.IControl(self.getBuildmaster(req)) builder_control = c.getBuilder(self.builder_status.getName()) brcontrols = yield builder_control.getPendingBuildRequestControls() for build_req in brcontrols: if cancel_all or (build_req.brid == request_id): log.msg("Cancelling %s" % build_req) res = yield authz.actionAllowed('cancelPendingBuild', req, build_req) if res: yield build_req.cancel() else: defer.returnValue(path_to_authzfail(req)) return if not cancel_all: break args = req.args.copy() returnpage = args.get("returnpage", None) if returnpage is None: defer.returnValue((path_to_builder(req, self.builder_status))) elif "builders" in returnpage: defer.returnValue( (path_to_builders(req, self.builder_status.getProject()))) elif "buildqueue" in returnpage: defer.returnValue(path_to_buildqueue(req)) elif "builders_json": s = self.getStatus(req) defer.returnValue( (s.getBuildbotURL() + path_to_json_builders(req, self.builder_status.getProject())))
def force(self, req, builderNames): master = self.getBuildmaster(req) owner = self.getAuthz(req).getUsernameFull(req) scheduler_name = req.args.get("forcescheduler", ["<unknown>"])[0] args = self.decode_request_arguments(req) if scheduler_name == "<unknown>": scheduler = master.scheduler_manager.findSchedulerByBuilderName( builderNames[0], scheduler_type=ForceScheduler, ) else: scheduler = master.scheduler_manager.findSchedulerByName( name=scheduler_name) try: yield scheduler.force(owner, builderNames, **args) except ValidationError: pass except AttributeError: if scheduler_name == '<unknown>': defer.returnValue(( path_to_builder(req, self.builder_status), 'forcescheduler arg not found, and could not find a default force scheduler for builderName', ), ) # send the user back to the proper page returnpage = args.get("returnpage", {}) if "builders" in returnpage: defer.returnValue( (path_to_builders(req, self.builder_status.getProject()))) elif "builders_json" in returnpage: s = self.getStatus(req) defer.returnValue( (s.getBuildbotURL() + path_to_json_builders(req, self.builder_status.getProject()))) elif "pending_json" in returnpage and builderNames > 0: s = self.getStatus(req) defer.returnValue((s.getBuildbotURL() + path_to_json_pending(req, builderNames[0]))) defer.returnValue((path_to_builder(req, self.builder_status)))
def content(self, req, cxt): b = self.builder_status master = self.getBuildmaster(req) # Grab all the parameters which are prefixed with 'property.'. # We'll use these to filter the builds and build requests we # show below. props = {} prop_prefix = 'property.' for arg, val in req.args.iteritems(): if arg.startswith(prop_prefix): props[arg[len(prop_prefix):]] = val[0] def prop_match(oprops): for key, val in props.iteritems(): if key not in oprops or val != str(oprops[key]): return False return True project = cxt['selectedproject'] = b.getProject() cxt['name'] = b.getName() cxt['friendly_name'] = b.getFriendlyName() cxt['description'] = b.getDescription() req.setHeader('Cache-Control', 'no-cache') codebases = {} getCodebasesArg(request=req, codebases=codebases) num_builds = int(req.args.get('numbuilds', [self.numbuilds])[0]) cxt['builder_url'] = path_to_builder(req, b, codebases=True) cxt['path_to_codebases'] = path_to_codebases(req, project) cxt['path_to_builders'] = path_to_builders(req, project) cxt['builder_name'] = b.getName() cxt['rt_update'] = req.args filters = { "project": self.builder_status.project, "builderName": b.getName(), "sources": codebases } project_params = { "build_steps": ["0"], "build_props": ["0"] } project_json = SingleProjectBuilderJsonResource(self.status, self.builder_status, latest_rev=True) project_dict = yield project_json.asDict(req, params=project_params) url = self.status.getBuildbotURL() + path_to_json_project_builder(req, project, self.builder_status.name) filtered_tags = filter_tags_by_codebases(project_dict['tags'], codebases, master.config.tag_as_branch_regex, master.config.regex_branches) cxt['instant_json']['project'] = {"url": url, "data": json.dumps(project_dict, separators=(',', ':')), "tags": filtered_tags, "waitForPush": self.status.master.config.autobahn_push, "pushFilters": { "buildStarted": filters, "buildFinished": filters, "stepStarted": filters, "stepFinished": filters, }} pending_json = SinglePendingBuildsJsonResource(self.status, self.builder_status) pending_dict = yield pending_json.asDict(req) pending_url = self.status.getBuildbotURL() + path_to_json_pending(req, self.builder_status.name) cxt['instant_json']['pending_builds'] = {"url": pending_url, "data": json.dumps(pending_dict, separators=(',', ':')), "waitForPush": self.status.master.config.autobahn_push, "pushFilters": { "buildStarted": filters, "requestSubmitted": filters, "requestCancelled": filters, }} builds_params = { "steps": ["0"], } builds_json = PastBuildsJsonResource(self.status, num_builds, builder_status=self.builder_status) builds_dict = yield builds_json.asDict(req, params=builds_params) builds_url = self.status.getBuildbotURL() + path_to_json_past_builds(req, self.builder_status.name, num_builds, filter_data=True) cxt['instant_json']['builds'] = {"url": builds_url, "data": json.dumps(builds_dict, separators=(',', ':')), "waitForPush": self.status.master.config.autobahn_push, "pushFilters": { "buildFinished": filters }} slave_params = { "build_steps": ["0"], "build_props": ["0"], "builders": ["0"] } slaves = b.getSlaves() slaves_array = [SlaveJsonResource(self.status, ss).asDict(req, params=slave_params) for ss in slaves] slaves_dict = FilterOut(slaves_array) url = self.status.getBuildbotURL() + path_to_json_builder_slaves(self.builder_status.getName()) cxt['instant_json']["slaves"] = self.getSlavesJsonResource(filters, url, slaves_dict) startslaves = BuilderStartSlavesJsonResources(self.status, self.builder_status) startslaves_dict = yield startslaves.asDict(req) url = self.status.getBuildbotURL() + \ path_to_json_builder_startslaves(self.builder_status.getName()) + "?filter=1" cxt['instant_json']["start_slaves"] = self.getSlavesJsonResource(filters, url, startslaves_dict) cxt['numbuilds'] = int(req.args.get('numbuilds', [self.numbuilds])[0]) buildForceContext(cxt, req, self.getBuildmaster(req), b.getName()) template = req.site.buildbot_service.templates.get_template("builder.html") defer.returnValue(template.render(**cxt))
def __prepare_context(self, request, cxt=None): """ This method prepares context for templates :param request: http request object :param cxt: default context variable :type cxt: dictionary :return: dictionary with variables for template """ if not cxt: context = {} else: context = cxt.copy() builder = self.build_status.getBuilder() context['builder_name'] = builder.name context['builder_friendly_name'] = builder.getFriendlyName() context['selected_project'] = builder.getProject() context['build_number'] = self.build_status.getNumber() context['custom_build_urls'] = self.build_status.getCustomUrls() context['source_stamps'] = self.build_status.getSourceStamps() context['got_revisions'] = self.build_status.getAllGotRevisions() context['slave_friendly_name'] = self.build_status.getSlavename() context['build_reason'] = self.build_status.getReason() context['build_is_resuming'] = self.build_status.isResuming() context['build_is_finished'] = self.build_status.isFinished() context['path_to_builder'] = path_to_builder( request, self.build_status.getBuilder()) context['path_to_builders'] = path_to_builders(request, builder.getProject()) context['path_to_codebases'] = path_to_codebases( request, builder.getProject()) context['build_url'] = path_to_build(request, self.build_status, False) context['slave_debug_url'] = self.getBuildmaster( request).config.slave_debug_url context['codebases_arg'] = getCodebasesArg(request=request) context['parent_build_url'] = None context['top_build_url'] = None start, end = self.build_status.getTimes() context['start'] = time.ctime(start) context['end'] = time.ctime(end) if end else None context['elapsed'] = None if not end: end = util.now() if start: context['elapsed'] = util.formatInterval(end - start) context['authz'] = self.getAuthz(request) context['has_changes'] = False context['tests_link'] = None context['resume'] = None context['top_build_name'] = None context['parent_build_name'] = None context['result_css'] = "" context['slave_url'] = "" context['steps'] = [] context['properties'] = [] return context
def content(self, req, cxt): s = self.step_status b = s.getBuild() builder_status = b.getBuilder() project = builder_status.getProject() cxt['builder_name'] = builder_status.getFriendlyName() cxt['path_to_builder'] = path_to_builder(req, builder_status) cxt['path_to_builders'] = path_to_builders(req, project) cxt['path_to_codebases'] = path_to_codebases(req, project) cxt['path_to_build'] = path_to_build(req, b) cxt['build_number'] = b.getNumber() cxt['path_to_artifacts'] = self.get_artifact_path(b) cxt['join'] = join cxt['basename'] = basename cxt['splitext'] = splitext cxt['selectedproject'] = project cxt['removeTestFilter'] = removeTestFilter cxt['results'] = { 0: 'Inconclusive', 1: 'NotRunnable', 2: 'Skipped', 3: 'Ignored', 4: 'Success', 5: 'Failed', 6: 'Error', 7: 'Cancelled' } json_data = None error_message = None try: json_data = json.loads(self.log.getText()) if json_data is not None: if 'summary' in json_data: success_count = json_data['summary']['successCount'] total_count = json_data['summary']['testsCount'] if success_count != 0 and total_count != 0: success_per = (float(success_count) / float(total_count)) * 100.0 json_data['summary']['success_rate'] = success_per json_data['filters'] = { 'Inconclusive': True, 'Skipped': False, 'Ignored': False, 'Success': False, 'Failed': True, 'Error': True, 'Cancelled': True } cxt['data'] = json_data else: error_message = "[{0}] Error occurred while parsing JSON test report data" \ .format(self.__class__.__name__) except KeyError as e: error_message = "[{0}] Key error in json: {1}".format( self.__class__.__name__, e) except Exception: import sys import traceback extype, ex, tb = sys.exc_info() formatted = traceback.format_exception_only(extype, ex)[-1] error_message = "[{0}] Unexpected exception caught while loading JSON test report data: {1}"\ .format(self.__class__.__name__, '\n\t'.join(formatted.splitlines())) log.msg( Failure(), "Unexpected exception caught while loading JSON test report data" ) if error_message is not None: cxt['data_error'] = error_message template = req.site.buildbot_service.templates.get_template( "jsontestresults.html") return template.render(**cxt)
def content(self, req, cxt): s = self.step_status b = s.getBuild() builder_status = b.getBuilder() project = builder_status.getProject() cxt['builder_name'] = b.getBuilder().getFriendlyName() cxt['path_to_builder'] = path_to_builder(req, builder_status) cxt['path_to_builders'] = path_to_builders(req, project) cxt['path_to_codebases'] = path_to_codebases(req, project) cxt['path_to_build'] = path_to_build(req, b) cxt['build_number'] = b.getNumber() cxt['selectedproject'] = project xml_type = NUNIT try: html = self.log.getText() if "nosetests" in html: xml_type = NOSE elif "<testsuites>" and "testsuite" in html: xml_type = JUNIT if "utf-16" in html: html = html.replace("utf-16", "utf-8") root = ElementTree.fromstring(html) root_dict = self.etree_to_dict(root) xpath = ".//test-suite/results/test-case/../.." if xml_type is NOSE or xml_type is JUNIT: xpath = ".//testcase" test_suites_dict = [ self.etree_to_dict(r) for r in root.findall(xpath) ] if xml_type is JUNIT: root_dict = root_dict["testsuites"][0] def parseTest(test, xml_type): total = 0 time_count = 0 test_parent = self.test_dict() def updateTime(result_object): t = 0 if result_object.has_key('time'): t = result_object['time'] test_parent['time'] += t return t if test.has_key("name"): test_parent["name"] = test["name"] if xml_type is NUNIT and 'results' in test: test_parent['tests_length'] = len(test['results']) for r in tso['results']: result_object = self.test_result_xml_to_dict( r, xml_type) test_parent['results'].append(result_object) total += 1 time_count += updateTime(result_object) test_parent[self.test_result_to_status( r, xml_type)[0]] += 1 elif xml_type is NOSE: result_object = self.test_result_xml_to_dict( test, xml_type) test_parent['results'].append(result_object) total += 1 time_count += updateTime(result_object) test_parent[self.test_result_to_status(test, xml_type)[0]] += 1 elif xml_type is JUNIT: result_object = self.test_result_xml_to_dict( test, xml_type) test_parent["results"].append(result_object) total += 1 time_count += updateTime(result_object) test_parent[self.test_result_to_status(test, xml_type)[0]] += 1 return test_parent, total, time_count # Collect summary information for each test suite time_count = 0 total = 0 output_tests = [] if xml_type is NUNIT: for ts in test_suites_dict: tests = ts['test-suite'] for tso in tests: o, c, t = parseTest(tso, xml_type) o["name"] = ts["name"] output_tests.append(o) total += c time_count += t elif xml_type is NOSE: classes = {} for tso in test_suites_dict: class_name = tso["classname"] o, c, t = parseTest(tso, xml_type) if class_name not in classes: classes[class_name] = self.test_dict() classes[class_name]["name"] = class_name classes[class_name]["results"].append(o["results"][0]) classes[class_name]["passed"] += o["passed"] classes[class_name]["failed"] += o["failed"] classes[class_name]["time"] += t classes[class_name]["tests"] += c total += c time_count += t output_tests = classes.values() elif xml_type is JUNIT: classes = {} for tso in test_suites_dict: o, c, t = parseTest(tso, xml_type) class_name = tso["classname"] if class_name not in classes: classes[class_name] = self.test_dict() classes[class_name]["name"] = class_name classes[class_name]["results"].append(o["results"][0]) classes[class_name]["passed"] += o["passed"] classes[class_name]["failed"] += o["failed"] classes[class_name]["time"] += t classes[class_name]["tests"] += c total += c time_count += t output_tests = classes.values() cxt['data'] = {} cxt['data']['test_suites'] = output_tests failed = int(0 if ( 'failures' not in root_dict) else root_dict['failures']) error = int(0 if ( 'errors' not in root_dict) else root_dict['errors']) ignored = int(0 if ( 'ignored' not in root_dict) else root_dict['ignored']) skipped = int(0 if ( 'skipped' not in root_dict) else root_dict['skipped']) inconclusive = int(0 if ('inconclusive' not in root_dict ) else root_dict['inconclusive']) if skipped == 0 and 'skipped' not in root_dict: skipped = int(0 if ( 'not-run' not in root_dict) else root_dict['not-run']) success = (total - failed - inconclusive - skipped - ignored) success_per = 0 if success != 0 and total != 0: success_per = (float(success) / float(total)) * 100.0 cxt['data']['summary'] = { 'testsCount': total, 'passedCount': success, 'success_rate': success_per, 'failedCount': failed, 'ignoredCount': ignored, 'skippedCount': skipped, 'errorCount': error, 'inconclusiveCount': inconclusive, 'time': time_count } cxt['data']['filters'] = { 'Failed': True, 'Passed': False, 'Ignored': False, 'Inconclusive': False, 'Skipped': False } except ElementTree.ParseError as e: log.msg("Error with parsing XML: {0}".format(e)) template = req.site.buildbot_service.templates.get_template( "xmltestresults.html") return template.render(**cxt)
def content(self, req, cxt): b = self.build_status status = self.getStatus(req) req.setHeader('Cache-Control', 'no-cache') builder = self.build_status.getBuilder() cxt['builder'] = builder cxt['builder_name'] = builder.getFriendlyName() cxt['build_number'] = b.getNumber() cxt['builder_name_link'] = urllib.quote( self.build_status.getBuilder().getName(), safe='') cxt['b'] = b project = cxt['selectedproject'] = builder.getProject() cxt['path_to_builder'] = path_to_builder(req, b.getBuilder()) cxt['path_to_builders'] = path_to_builders(req, project) cxt['path_to_codebases'] = path_to_codebases(req, project) cxt['build_url'] = path_to_build(req, b, False) cxt['slave_debug_url'] = self.getBuildmaster( req).config.slave_debug_url cxt['customBuildUrls'] = b.getCustomUrls() codebases_arg = cxt['codebases_arg'] = getCodebasesArg(request=req) cxt['build_chain_top_build_url'] = yield b.getTopBuildUrl( codebases_arg) if not b.isFinished(): cxt['stop_build_chain'] = False step = b.getCurrentStep() if not step: cxt['current_step'] = "[waiting for build slave]" else: if step.isWaitingForLocks(): cxt['current_step'] = "%s [waiting for build slave]" % 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") ssList = b.getSourceStamps() sourcestamps = cxt['sourcestamps'] = ssList all_got_revisions = b.getAllGotRevisions() cxt['got_revisions'] = all_got_revisions try: slave_obj = status.getSlave(b.getSlavename()) if slave_obj is not None: cxt['slave_friendly_name'] = slave_obj.getFriendlyName() cxt['slave_url'] = path_to_slave(req, slave_obj) else: cxt['slave_friendly_name'] = b.getSlavename() cxt['slave_url'] = "" except KeyError: pass if b.resume: cxt['resume'] = b.resume cxt['steps'] = [] for s in b.getSteps(): step = {'name': s.getName()} if s.isFinished(): if s.isHidden(): continue 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['link'] = path_to_step(req, s) step['text'] = " ".join(s.getText()) urls = [] getUrls = s.getURLs().items() for k, v in s.getURLs().items(): if isinstance(v, dict): if 'results' in v.keys() and v['results'] in css_classes: url_dict = dict(logname=k, url=v['url'] + codebases_arg, results=css_classes[v['results']]) else: url_dict = dict(logname=k, url=v['url'] + codebases_arg) else: url_dict = dict(logname=k, url=v + codebases_arg) urls.append(url_dict) step['urls'] = urls step['logs'] = [] for l in s.getLogs(): logname = l.getName() step['logs'].append({ 'link': req.childLink( "steps/%s/logs/%s%s" % (urllib.quote(s.getName(), safe=''), urllib.quote(logname, safe=''), codebases_arg)), 'name': logname }) scheduler = b.getProperty("scheduler", None) parameters = {} master = self.getBuildmaster(req) for sch in master.allSchedulers(): if isinstance(sch, ForceScheduler) and scheduler == sch.name: for p in sch.all_fields: parameters[p.name] = p ps = cxt['properties'] = [] for name, value, source in b.getProperties().asList(): if not isinstance(value, dict): cxt_value = unicode(value) else: cxt_value = value if name == 'submittedTime': cxt_value = time.ctime(value) p = {'name': name, 'value': cxt_value, 'source': source} if len(cxt_value) > 500: p['short_value'] = cxt_value[:500] if name in parameters: param = parameters[name] if isinstance(param, TextParameter): p['text'] = param.value_to_text(value) p['cols'] = param.cols p['rows'] = param.rows p['label'] = param.label ps.append(p) (start, end) = b.getTimes() cxt['start'] = time.ctime(start) cxt['elapsed'] = None if end and start: cxt['end'] = time.ctime(end) cxt['elapsed'] = util.formatInterval(end - start) elif start: now = util.now() cxt['elapsed'] = util.formatInterval(now - start) has_changes = False for ss in sourcestamps: has_changes = has_changes or ss.changes cxt['has_changes'] = has_changes cxt['authz'] = self.getAuthz(req) filters = {"number": b.getNumber()} build_json = BuildJsonResource(status, b) build_dict = yield build_json.asDict(req) cxt['instant_json']['build'] = { "url": path_to_json_build(status, req, builder.name, b.getNumber()), "data": json.dumps(build_dict, separators=(',', ':')), "waitForPush": status.master.config.autobahn_push, "pushFilters": { "buildStarted": filters, "buildFinished": filters, "stepStarted": filters, "stepFinished": filters, } } template = req.site.buildbot_service.templates.get_template( "build.html") defer.returnValue(template.render(**cxt))
def render_GET(self, req): self._setContentType(req) self.req = req if self.original.isFinished(): req.setHeader("Cache-Control", "max-age=604800") else: req.setHeader("Cache-Control", "no-cache") # If plaintext is requested just return the content of the logfile if self.asDownload: with_headers = "_with_headers" if self.withHeaders else "" base_name = self.original.step.getName( ) + "_" + self.original.getName() + with_headers base_name = re.sub(r'[\W]', '_', base_name) + ".log" req.setHeader("Content-Disposition", "attachment; filename =\"" + base_name + "\"") return self.original.getTextWithHeaders( ) if self.withHeaders else self.original.getText() # Or open in new window if self.newWindow: req.setHeader("Content-Disposition", "inline") return self.original.getTextWithHeaders( ) if self.withHeaders else self.original.getText() # Else render the logs template self.template = req.site.buildbot_service.templates.get_template( "logs.html") self.chunk_template = req.site.buildbot_service.templates.get_template( "log_chunk.html") builder = self.original.step.build.builder build_id = self.original.step.build.number url_dict = self.original.master.status.getURLForBuild( builder.getName(), build_id) if self.iFrame: data = self.chunk_template.module.page_header(version) data = data.encode('utf-8') req.write(data) self.original.subscribeConsumer(ChunkConsumer(req, self)) return server.NOT_DONE_YET cxt = self.getContext(req) build = self.original.step.build builder_status = build.builder project = builder_status.getProject() cxt["pageTitle"] = "Log File Contents" cxt["new_window_url"] = req.path + "/plaintext" cxt["new_window_with_headers_url"] = req.path + "/plaintext_with_headers" cxt["download_url"] = req.path + "/download" cxt["download_with_headers_url"] = req.path + "/download_with_headers" cxt["iframe_url"] = req.path + "/iframe" cxt["builder_name"] = builder.getFriendlyName() cxt['path_to_builder'] = path_to_builder(req, builder_status) cxt['path_to_builders'] = path_to_builders(req, project) cxt["builder_url"] = url_dict['path'] + getCodebasesArg(request=req) cxt['path_to_codebases'] = path_to_codebases(req, project) cxt['path_to_build'] = path_to_build(req, build) cxt['build_number'] = build.getNumber() cxt['selectedproject'] = project data = self.template.render(**cxt) data = data.encode('utf-8') req.write(data) return ""