def builder(self, build, req): b = {} b['num'] = build.getNumber() b['link'] = path_to_build(req, build) when = build.getETA() if when is not None: b['when'] = util.formatInterval(when) b['when_time'] = time.strftime("%H:%M:%S", time.localtime(time.time() + when)) if build.started: b['delay'] = util.formatInterval(time.time() - build.started) step = build.getCurrentStep() # TODO: is this necessarily the case? if not step: b['current_step'] = "[waiting for Lock]" else: if step.isWaitingForLocks(): b['current_step'] = "%s [waiting for Lock]" % step.getName() else: b['current_step'] = step.getName() b['stop_url'] = path_to_build(req, build) + '/stop' return b
def content(self, req, cxt): s = self.step_status b = s.getBuild() 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())) }) 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(**cxt)
def getCommonBuildInfo(self, req, b): cxt = {} cxt['number'] = b.getNumber() 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)) cxt['result_css'] = "building" else: cxt['result_css'] = css_classes[b.getResults()] (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) return cxt
def body(self, req): s = self.step_status b = s.getBuild() builder_name = b.getBuilder().getName() build_num = b.getNumber() data = "" data += '<h1>BuildStep <a href="%s">%s</a>:' % (path_to_builder(req, b.getBuilder()), builder_name) data += '<a href="%s">#%d</a>' % (path_to_build(req, b), build_num) data += ":%s</h1>\n" % s.getName() if s.isFinished(): data += "<h2>Finished</h2>\n" "<p>%s</p>\n" % html.escape("%s" % s.getText()) else: data += "<h2>Not Finished</h2>\n" "<p>ETA %s seconds</p>\n" % s.getETA() exp = s.getExpectations() if exp: data += "<h2>Expectations</h2>\n" "<ul>\n" for e in exp: data += "<li>%s: current=%s, target=%s</li>\n" % (html.escape(e[0]), e[1], e[2]) data += "</ul>\n" (start, end) = s.getTimes() if not start: start_text = end_text = elapsed = "Not Started" else: start_text = ctime(start) if end: end_text = ctime(end) elapsed = util.formatInterval(end - start) else: end_text = "Not Finished" elapsed = util.formatInterval(util.now() - start) data += "<h2>Timing</h2>\n" data += "<table>\n" data += "<tr><td>Start</td><td>%s</td></tr>\n" % start_text data += "<tr><td>End</td><td>%s</td></tr>\n" % end_text data += "<tr><td>Elapsed</td><td>%s</td></tr>\n" % elapsed data += "</table>\n" logs = s.getLogs() if logs: data += "<h2>Logs</h2>\n" "<ul>\n" for logfile in logs: if logfile.hasContents(): # 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. logname = logfile.getName() logurl = req.childLink("logs/%s" % urllib.quote(logname)) data += '<li><a href="%s">%s</a></li>\n' % (logurl, html.escape(logname)) else: data += "<li>%s</li>\n" % html.escape(logname) data += "</ul>\n" return data
def finishStep(self, section, status=None): """Mark the specified step as 'finished.'""" # Update status if set as an argument. if status is not None: section['status'] = status self.ensureStepIsStarted(section) # Final update of text. updateText(section) # Add timing info. section['ended'] = section.get('ended', util.now()) started = section['started'] ended = section['ended'] msg = '\n\n' + '-' * 80 + '\n' msg += '\n'.join([ 'started: %s' % time.ctime(started), 'ended: %s' % time.ctime(ended), 'duration: %s' % util.formatInterval(ended - started), '', # So we get a final \n ]) section['log'].addHeader(msg) # Change status (unless handling the preamble). if len(self.sections) != 1: section['step'].stepFinished(section['status']) # Finish log. section['log'].finish()
def fixupLast(self, status=None): # Potentially start initial section here, as initial section might have # no output at all. self.initialSection() last = self.sections[-1] # Update status if set as an argument. if status is not None: last['status'] = status # Final update of text. self.updateText() # Add timing info. (start, end) = self.command.step_status.getTimes() msg = '\n\n' + '-' * 80 + '\n' if start is None: msg += 'Not Started\n' else: if end is None: end = util.now() msg += '\n'.join([ 'started: %s' % time.ctime(start), 'ended: %s' % time.ctime(end), 'duration: %s' % util.formatInterval(end - start), '', # So we get a final \n ]) last['log'].addStdout(msg) # Change status (unless handling the preamble). if len(self.sections) != 1: last['step'].stepFinished(last['status']) # Finish log. last['log'].finish()
def formatSteps(logFile, build): """ Writes the steps of build to the logfile """ # Steps total_master_lag = 0.0 for step in build.getSteps(): times = step.getTimes() if not times or not times[0]: elapsed = "not started" elif not times[1]: elapsed = "not finished" else: elapsed = util.formatInterval(times[1] - times[0]) results = step.getResults()[0] if results == (None, []): results = "not started" shortText = ' '.join(step.getText( )) + ' (results: %s, elapsed: %s)' % (results, elapsed) if times and times[0]: logFile.write("========= Started %s (at %s) =========\n" % (shortText, datetime.fromtimestamp(times[0]))) else: logFile.write("========= Skipped %s =========\n" % shortText) continue slave_time = None for log in step.getLogs(): data = log.getTextWithHeaders() logFile.write(data) if not data.endswith("\n"): logFile.write("\n") # Look for if the slave reported its elapsedTime m = re.search("^elapsedTime=([.0-9]+)$", data, re.M) if m: try: slave_time = float(m.group(1)) except ValueError: pass if times and times[0] and times[1] and slave_time: master_lag = times[1] - times[0] - slave_time total_master_lag += master_lag logFile.write("========= master_lag: %.2f =========\n" % master_lag) if STATSD: # statsd expects milliseconds STATSD.timing('master_lag', master_lag * 1000.0) if times and times[1]: logFile.write("========= Finished %s (at %s) =========\n\n" % (shortText, datetime.fromtimestamp(times[1]))) else: logFile.write("========= Finished %s =========\n\n" % shortText) if STATSD: STATSD.timing('total_master_lag', total_master_lag * 1000.0) logFile.write("========= Total master_lag: %.2f =========\n\n" % total_master_lag)
def request_line(self, build_request, req): when = time.strftime("%b %d %H:%M:%S", time.localtime(build_request.getSubmitTime())) delay = util.formatInterval(util.now() - build_request.getSubmitTime()) changes = build_request.source.changes if changes: change_strings = [] for c in changes: change_strings.append("<a href=\"%s\">%s</a>" % (path_to_change(req, c), c.who)) if len(change_strings) == 1: reason = "change by %s" % change_strings[0] else: reason = "changes by %s" % ", ".join(change_strings) elif build_request.source.revision: reason = build_request.source.revision else: reason = "no changes specified" if self.builder_control is not None: cancelURL = path_to_builder(req, self.builder_status) + '/cancelbuild' cancelButton = ''' <form action="%s" class="command cancelbuild" style="display:inline" method="post"> <input type="hidden" name="id" value="%s" /> <input type="submit" value="Cancel Build" /> </form>''' % (cancelURL, id(build_request)) else: cancelButton = "" return "<font size=\"-1\">(%s, waiting %s)</font>%s%s" % (when, delay, cancelButton, reason)
def content(self, req, cxt): b = self.builder_status cxt['name'] = b.getName() 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'] = [] for pb in b.getPendingBuilds(): source = pb.getSourceStamp() changes = [] if source.changes: for c in source.changes: changes.append({ 'url' : path_to_change(req, c), 'who' : c.who}) if source.revision: reason = source.revision else: reason = "no changes specified" cxt['pending'].append({ 'when': time.strftime("%b %d %H:%M:%S", time.localtime(pb.getSubmitTime())), 'delay': util.formatInterval(util.now() - pb.getSubmitTime()), 'reason': reason, 'id': pb.brid, 'changes' : changes }) numbuilds = int(req.args.get('numbuilds', ['5'])[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'] = slave.getAdmin() connected_slaves += 1 cxt['connected_slaves'] = connected_slaves cxt['authz'] = self.getAuthz(req) cxt['builder_url'] = path_to_builder(req, b) template = req.site.buildbot_service.templates.get_template("builder.html") return template.render(**cxt)
def content(self, req, cxt): b = self.builder_status cxt["name"] = b.getName() 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"] = [] for pb in b.getPendingBuilds(): changes = [] if pb.source.changes: for c in pb.source.changes: changes.append({"url": path_to_change(req, c), "who": c.who}) if pb.source.revision: reason = pb.source.revision else: reason = "no changes specified" cxt["pending"].append( { "when": time.strftime("%b %d %H:%M:%S", time.localtime(pb.getSubmitTime())), "delay": util.formatInterval(util.now() - pb.getSubmitTime()), "reason": reason, "id": id(pb), "changes": changes, } ) numbuilds = int(req.args.get("numbuilds", ["5"])[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"] = slave.getAdmin() connected_slaves += 1 cxt["connected_slaves"] = connected_slaves cxt["authz"] = self.getAuthz(req) cxt["builder_url"] = path_to_builder(req, b) template = req.site.buildbot_service.templates.get_template("builder.html") return template.render(**cxt)
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 finishStep(self, section, status=None, reason=None): """Mark the specified step as 'finished.'""" # The initial section will be closed by self.finished when runCommand # completes, so finishStep should not close it. assert not self.sectionIsPreamble(section), ('The initial section cannot ' 'be finalized at annotator ' 'level.') status_map = { builder.SUCCESS: 'SUCCESS', builder.WARNINGS: 'WARNINGS', builder.FAILURE: 'FAILURE', builder.EXCEPTION: 'EXCEPTION', builder.RETRY: 'RETRY', builder.SKIPPED: 'SKIPPED', } # Update status if set as an argument. if status is not None: section['status'] = status else: # Wasn't set as an argument, so we know it came from annotations. if not reason: if section['status'] == builder.SUCCESS: reason = 'step finished normally.' else: reason = 'parsed annotations marked step as %s.' % status_map[ section['status']] self.ensureStepIsStarted(section) # Final update of text. updateText(section) # Add timing info. section['ended'] = section.get('ended', util.now()) started = section['started'] ended = section['ended'] msg = '\n\n' + '-' * 80 + '\n' msg += '\n'.join([ 'started: %s' % time.ctime(started), 'ended: %s' % time.ctime(ended), 'duration: %s' % util.formatInterval(ended - started), 'status: %s' % status_map[section['status']], 'status reason: %s' % reason, '', # So we get a final \n ]) section['log'].addHeader(msg) # Change status (unless handling the preamble). if len(self.sections) != 1: section['step'].stepFinished(section['status']) # Finish log. section['log'].finish()
def getChildBuild(self, req, b): cxt = self.getCommonBuildInfo(req, b) env = cxt['environment'] = {} for name, value, source in b.getProperties().asList(): if source != ".travis.yml": continue env[name] = value 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) link = step['link'] = path_to_build(req, b) + "/steps/%s" % urllib.quote(s.getName(), safe='') step['text'] = " ".join(s.getText()) step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items()) step['logs']= [] for l in s.getLogs(): logname = l.getName() step['logs'].append(dict( link = link + "/logs/%s" % urllib.quote(logname, safe=''), name = logname, )) return cxt
def builder(self, build, req): b = {} b["num"] = build.getNumber() b["link"] = path_to_build(req, build) when = build.getETA() if when is not None: b["when"] = util.formatInterval(when) b["when_time"] = time.strftime("%H:%M:%S", time.localtime(time.time() + when)) step = build.getCurrentStep() if step: b["current_step"] = step.getName() else: b["current_step"] = "[waiting for Lock]" # TODO: is this necessarily the case? b["stop_url"] = path_to_build(req, build) + "/stop" return b
def getPending(self, request): nr = self.build_status.getNumber() status = self.getStatus(request) job = status.getBuilder(self.build_status.getBuilder().getName() + "-job") builds = [] pending = yield job.getPendingBuildRequestStatuses() for b in pending: source = yield b.getSourceStamp() submitTime = yield b.getSubmitTime() bsid = yield b.getBsid() properties = yield \ b.master.db.buildsets.getBuildsetProperties(bsid) if properties["spawned_by"][0] != nr: continue info = {} info['number'] = "?" env = info['environment'] = {} for name, value in properties.items(): value, source = value if source != ".travis.yml": continue env[name] = value # How long has it been pending? info['start'] = time.strftime("%b %d %H:%M:%S", time.localtime(submitTime)) info['elapsed'] = util.formatInterval(util.now() - submitTime) info['result_css'] = "pending" builds.append(info) defer.returnValue(builds)
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 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") ssList = b.getSourceStamps() sourcestamps = cxt['sourcestamps'] = ssList all_got_revisions = b.getAllGotRevisions() cxt['got_revisions'] = all_got_revisions 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.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'] = req.childLink("steps/%s" % urllib.quote(s.getName(), safe='')) step['text'] = " ".join([str(txt) for txt in s.getText()]) step['urls'] = map(lambda x: dict(url=x[1], logname=x[0]), s.getURLs().items()) step['logs'] = [] for l in s.getLogs(): logname = l.getName() step['logs'].append({'link': req.childLink("steps/%s/logs/%s" % (urllib.quote(s.getName(), safe=''), urllib.quote(logname, safe=''))), '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 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) 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) has_changes = False for ss in sourcestamps: has_changes = has_changes or ss.changes cxt['has_changes'] = has_changes 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(**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()} cxt['steps'].append(step) 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'] = "" step['link'] = req.childLink("steps/%s" % urllib.quote(s.getName())) step['text'] = " ".join(s.getText()) step['urls'] = map(lambda x: dict(url=x[1], logname=x[0]), s.getURLs().items()) step['logs'] = [] for l in s.getLogs(): logname = l.getName() step['logs'].append({ 'link': req.childLink( "steps/%s/logs/%s" % (urllib.quote(s.getName()), urllib.quote(logname))), 'name': logname }) 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(**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 content(self, req, cxt): b = self.builder_status cxt['name'] = b.getName() 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'] = [] for pb in b.getPendingBuilds(): source = pb.getSourceStamp() changes = [] if source.changes: for c in source.changes: changes.append({ 'url': path_to_change(req, c), 'who': c.who }) if source.revision: reason = source.revision else: reason = "no changes specified" cxt['pending'].append({ 'when': time.strftime("%b %d %H:%M:%S", time.localtime(pb.getSubmitTime())), 'delay': util.formatInterval(util.now() - pb.getSubmitTime()), 'reason': reason, 'id': pb.brid, 'changes': changes }) numbuilds = int(req.args.get('numbuilds', ['5'])[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'] = slave.getAdmin() connected_slaves += 1 cxt['connected_slaves'] = connected_slaves cxt['authz'] = self.getAuthz(req) cxt['builder_url'] = path_to_builder(req, b) template = req.site.buildbot_service.templates.get_template( "builder.html") return template.render(**cxt)
def test_seconds_singular(self): self.assertEqual(util.formatInterval(1), "1 secs")
def test_minutes(self): self.assertEqual(util.formatInterval(300), "5 mins, 0 secs")
def test_hours_over_one_sec(self): self.assertEqual(util.formatInterval(3601), "1 hrs, 1 secs")
def test_minutes_one(self): self.assertEqual(util.formatInterval(60), "60 secs")
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") ssList = b.getSourceStamps() sourcestamps = cxt['sourcestamps'] = ssList all_got_revisions = b.getAllGotRevisions() cxt['got_revisions'] = all_got_revisions 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.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'] = req.childLink("steps/%s" % urllib.quote(s.getName(), safe='')) step['text'] = " ".join(s.getText()) step['urls'] = map(lambda x: dict(url=x[1], logname=x[0]), s.getURLs().items()) step['logs'] = [] for l in s.getLogs(): logname = l.getName() step['logs'].append({'link': req.childLink("steps/%s/logs/%s" % (urllib.quote(s.getName(), safe=''), urllib.quote(logname, safe=''))), '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 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) 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) has_changes = False for ss in sourcestamps: has_changes = has_changes or ss.changes cxt['has_changes'] = has_changes 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(**cxt)
def test_seconds(self): self.assertEqual(util.formatInterval(7), "7 secs")
def content(self, req, cxt): b = self.builder_status # 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 cxt['name'] = b.getName() cxt['description'] = b.getDescription() 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() if prop_match(x.getProperties())] cxt['pending'] = [] statuses = yield b.getPendingBuildRequestStatuses() for pb in statuses: changes = [] source = yield pb.getSourceStamp() submitTime = yield pb.getSubmitTime() bsid = yield pb.getBsid() properties = yield \ pb.master.db.buildsets.getBuildsetProperties(bsid) if not prop_match(properties): continue 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), 'properties' : properties, }) numbuilds = cxt['numbuilds'] = int(req.args.get('numbuilds', [self.numbuilds])[0]) maxsearch = int(req.args.get('maxsearch', [200])[0]) recent = cxt['recent'] = [] for build in b.generateFinishedBuilds( num_builds=int(numbuilds), max_search=maxsearch, filter_fn=lambda b: prop_match(b.getProperties())): 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() s['paused'] = slave.isPaused() s['admin'] = slave.getAdmin() or u'' if c: connected_slaves += 1 cxt['connected_slaves'] = connected_slaves cxt['authz'] = self.getAuthz(req) cxt['builder_url'] = path_to_builder(req, b) buildForceContext(cxt, req, self.getBuildmaster(req), b.getName()) template = req.site.buildbot_service.templates.get_template("builder.html") defer.returnValue(template.render(**cxt))
def test_hours(self): self.assertEqual(util.formatInterval(7200), "2 hrs, 0 secs")
def body(self, req): b = self.build_status status = self.getStatus(req) projectURL = status.getProjectURL() projectName = status.getProjectName() data = ('<div class="title"><a href="%s">%s</a></div>\n' % (self.path_to_root(req), projectName)) # the color in the following line gives python-mode trouble builder_name = b.getBuilder().getName() data += ("<h1><a href=\"%s\">Builder %s</a>: Build #%d</h1>\n" % (path_to_builder( req, b.getBuilder()), builder_name, b.getNumber())) if not b.isFinished(): data += "<h2>Build In Progress</h2>" when = b.getETA() if when is not None: when_time = time.strftime("%H:%M:%S", time.localtime(time.time() + when)) data += "<div>ETA %ds (%s)</div>\n" % (when, when_time) if self.build_control is not None: stopURL = urllib.quote(req.childLink("stop")) data += make_stop_form(stopURL) if b.isFinished(): results = b.getResults() data += "<h2>Results:</h2>\n" text = " ".join(b.getText()) data += '<span class="%s">%s</span>\n' % (css_classes[results], text) if b.getTestResults(): url = req.childLink("tests") data += "<h3><a href=\"%s\">test results</a></h3>\n" % url ss = b.getSourceStamp() data += "<h2>SourceStamp:</h2>\n" data += " <ul>\n" if ss.branch: data += " <li>Branch: %s</li>\n" % html.escape(ss.branch) if ss.revision: data += " <li>Revision: %s</li>\n" % html.escape(str(ss.revision)) if ss.patch: data += " <li>Patch: YES</li>\n" # TODO: provide link to .diff if ss.changes: data += " <li>Changes: see below</li>\n" if (ss.branch is None and ss.revision is None and ss.patch is None and not ss.changes): data += " <li>build of most recent revision</li>\n" got_revision = None try: got_revision = b.getProperty("got_revision") except KeyError: pass if got_revision: got_revision = str(got_revision) if len(got_revision) > 40: got_revision = "[revision string too long]" data += " <li>Got Revision: %s</li>\n" % got_revision data += " </ul>\n" # TODO: turn this into a table, or some other sort of definition-list # that doesn't take up quite so much vertical space try: slaveurl = path_to_slave(req, status.getSlave(b.getSlavename())) data += "<h2>Buildslave:</h2>\n <a href=\"%s\">%s</a>\n" % ( html.escape(slaveurl), html.escape(b.getSlavename())) except KeyError: data += "<h2>Buildslave:</h2>\n %s\n" % html.escape( b.getSlavename()) data += "<h2>Reason:</h2>\n%s\n" % html.escape(b.getReason()) data += "<h2>Steps and Logfiles:</h2>\n" # TODO: # urls = self.original.getURLs() # ex_url_class = "BuildStep external" # for name, target in urls.items(): # text.append('[<a href="%s" class="%s">%s</a>]' % # (target, ex_url_class, html.escape(name))) if b.getLogs(): data += "<ol>\n" for s in b.getSteps(): name = s.getName() data += (" <li><a href=\"%s\">%s</a> [%s]\n" % (req.childLink("steps/%s" % urllib.quote(name)), name, " ".join(s.getText()))) if s.getLogs(): data += " <ol>\n" for logfile in s.getLogs(): logname = logfile.getName() logurl = req.childLink( "steps/%s/logs/%s" % (urllib.quote(name), urllib.quote(logname))) data += (" <li><a href=\"%s\">%s</a></li>\n" % (logurl, logfile.getName())) data += " </ol>\n" data += " </li>\n" data += "</ol>\n" data += "<h2>Build Properties:</h2>\n" data += "<table><tr><th valign=\"left\">Name</th><th valign=\"left\">Value</th><th valign=\"left\">Source</th></tr>\n" for name, value, source in b.getProperties().asList(): value = str(value) if len(value) > 500: value = value[:500] + " .. [property value too long]" data += "<tr>" data += "<td>%s</td>" % html.escape(name) data += "<td>%s</td>" % html.escape(value) data += "<td>%s</td>" % html.escape(source) data += "</tr>\n" data += "</table>" data += "<h2>Blamelist:</h2>\n" if list(b.getResponsibleUsers()): data += " <ol>\n" for who in b.getResponsibleUsers(): data += " <li>%s</li>\n" % html.escape(who) data += " </ol>\n" else: data += "<div>no responsible users</div>\n" (start, end) = b.getTimes() data += "<h2>Timing</h2>\n" data += "<table>\n" data += "<tr><td>Start</td><td>%s</td></tr>\n" % time.ctime(start) if end: data += "<tr><td>End</td><td>%s</td></tr>\n" % time.ctime(end) data += "<tr><td>Elapsed</td><td>%s</td></tr>\n" % util.formatInterval( end - start) data += "</table>\n" if ss.changes: data += "<h2>All Changes</h2>\n" data += "<ol>\n" for c in ss.changes: data += "<li>" + c.asHTML() + "</li>\n" data += "</ol>\n" #data += html.PRE(b.changesText()) # TODO if b.isFinished() and self.builder_control is not None: data += "<h3>Resubmit Build:</h3>\n" # can we rebuild it exactly? exactly = (ss.revision is not None) or b.getChanges() if exactly: data += ("<p>This tree was built from a specific set of \n" "source files, and can be rebuilt exactly</p>\n") else: data += ("<p>This tree was built from the most recent " "revision") if ss.branch: data += " (along some branch)" data += (" and thus it might not be possible to rebuild it \n" "exactly. Any changes that have been committed \n" "after this build was started <b>will</b> be \n" "included in a rebuild.</p>\n") rebuildURL = urllib.quote(req.childLink("rebuild")) data += ('<form action="%s" class="command rebuild">\n' % rebuildURL) data += make_row("Your name:", "<input type='text' name='username' />") data += make_row("Reason for re-running build:", "<input type='text' name='comments' />") data += '<input type="submit" value="Rebuild" />\n' data += '</form>\n' # TODO: this stuff should be generated by a template of some sort data += '<hr /><div class="footer">\n' welcomeurl = self.path_to_root(req) + "index.html" data += '[<a href="%s">welcome</a>]\n' % welcomeurl data += "<br />\n" data += '<a href="http://buildbot.sourceforge.net/">Buildbot</a>' data += "-%s " % version if projectName: data += "working for the " if projectURL: data += "<a href=\"%s\">%s</a> project." % (projectURL, projectName) else: data += "%s project." % projectName data += "<br />\n" data += ("Page built: " + time.strftime( "%a %d %b %Y %H:%M:%S", time.localtime(util.now())) + "\n") data += '</div>\n' return data
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() } cxt['steps'].append(step) 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'] = "" step['link'] = req.childLink("steps/%s" % urllib.quote(s.getName())) step['text'] = " ".join(s.getText()) step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items()) step['logs']= [] for l in s.getLogs(): logname = l.getName() step['logs'].append({ 'link': req.childLink("steps/%s/logs/%s" % (urllib.quote(s.getName()), urllib.quote(logname))), 'name': logname }) 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(**cxt)
def test_minutes_over_one(self): self.assertEqual(util.formatInterval(61), "1 mins, 1 secs")
def test_zero(self): self.assertEqual(util.formatInterval(0), "0 secs")
def test_hours_one(self): self.assertEqual(util.formatInterval(3600), "60 mins, 0 secs")
def test_hours_over_one_min(self): self.assertEqual(util.formatInterval(3660), "1 hrs, 60 secs")
def formatLog(tmpdir, build, builder_suffix=''): """ Returns a filename with the contents of the build log written to it. """ builder_name = build.builder.name build_name = "%s%s-build%s.txt.gz" % (builder_name, builder_suffix, build_number) logFile = gzip.GzipFile(os.path.join(tmpdir, build_name), "w") # Header information logFile.write("builder: %s\n" % builder_name) logFile.write("slave: %s\n" % build.getSlavename()) logFile.write("starttime: %s\n" % build.started) results = build.getResults() try: results_str = Results[results] except: results_str = "Unknown" logFile.write("results: %s (%s)\n" % (results_str, results)) props = build.getProperties() if props.getProperty('buildid') is not None: logFile.write("buildid: %s\n" % props['buildid']) if props.getProperty('builduid') is not None: logFile.write("builduid: %s\n" % props['builduid']) if props.getProperty('got_revision') is not None: logFile.write("revision: %s\n" % props['got_revision']) elif props.getProperty('revision') is not None: logFile.write("revision: %s\n" % props['revision']) logFile.write("\n") # Steps for step in build.getSteps(): times = step.getTimes() if not times or not times[0]: elapsed = "not started" elif not times[1]: elapsed = "not started" else: elapsed = util.formatInterval(times[1] - times[0]) results = step.getResults()[0] if results == (None, []): results = "not started" shortText = ' '.join(step.getText()) + ' (results: %s, elapsed: %s)' % (results, elapsed) logFile.write("========= Started %s ==========\n" % shortText) for log in step.getLogs(): data = log.getTextWithHeaders() logFile.write(data) if not data.endswith("\n"): logFile.write("\n") logFile.write("======== Finished %s ========\n\n" % shortText) logFile.close() return os.path.join(tmpdir, build_name)
def test_mixed(self): self.assertEqual(util.formatInterval(7392), "2 hrs, 3 mins, 12 secs")
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() wfd = defer.waitForDeferred(pb.getBsid()) yield wfd bsid = wfd.getResult() wfd = defer.waitForDeferred( pb.master.db.buildsets.getBuildsetProperties(bsid)) yield wfd properties = 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), 'properties': properties, }) numbuilds = int(req.args.get('numbuilds', ['5'])[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) buildForceContext(cxt, req, self.getBuildmaster(req), b.getName()) template = req.site.buildbot_service.templates.get_template( "builder.html") yield template.render(**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['link'] = req.childLink("steps/%s" % urllib.quote(s.getName(), safe='')) step['text'] = " ".join(s.getText()) step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items()) step['nest_level'] = s.getNestLevel() step['logs']= [] for l in s.getLogs(): logname = l.getName() step['logs'].append({ 'link': req.childLink("steps/%s/logs/%s" % (urllib.quote(s.getName(), safe=''), urllib.quote(logname, safe=''))), 'name': logname }) step['aliases'] = {} seen_aliases = set() for base, aliases in s.getAliases().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(**cxt)
def content(self, req, cxt): b = self.builder_status cxt['name'] = b.getName() cxt['description'] = b.getDescription() 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'] = [] statuses = yield b.getPendingBuildRequestStatuses() for pb in statuses: changes = [] source = yield pb.getSourceStamp() submitTime = yield pb.getSubmitTime() bsid = yield pb.getBsid() properties = yield \ pb.master.db.buildsets.getBuildsetProperties(bsid) 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), 'properties' : properties, }) numbuilds = int(req.args.get('numbuilds', [self.numbuilds])[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) buildForceContext(cxt, req, self.getBuildmaster(req), b.getName()) template = req.site.buildbot_service.templates.get_template("builder.html") defer.returnValue(template.render(**cxt))