def get_annotation_data(self, context): add_stylesheet(context.req, 'bitten/bitten_coverage.css') resource = context.resource self.log.debug("Looking for coverage report for %s@%s..." % ( resource.id, str(resource.version))) builds = Build.select(self.env, rev=resource.version) reports = [] for build in builds: config = BuildConfig.fetch(self.env, build.config) if not resource.id.startswith(config.branch): continue reports = Report.select(self.env, build=build.id, category='coverage') branch_in_config = resource.id[len(config.branch):] for report in reports: for item in report.items: if item.get('file') == branch_in_config: coverage = item.get('line_hits', '').split() if coverage: # Return first result with line data self.log.debug( "Coverage annotate for %s@%s: %s" % \ (resource.id, resource.version, coverage)) return coverage return []
def get_annotation_data(self, context): """add annotation data for lint""" context.perm.require('BUILD_VIEW') add_stylesheet(context.req, 'bitten/bitten_coverage.css') add_stylesheet(context.req, 'bitten/bitten_lintannotator.css') resource = context.resource # attempt to use the version passed in with the request, # otherwise fall back to the latest version of this file. try: version = context.req.args['rev'] except (KeyError, TypeError): version = resource.version self.log.debug('no version passed to get_annotation_data') builds = Build.select(self.env, rev=version) self.log.debug("Looking for lint report for %s@%s [%s]..." % (resource.id, str(resource.version), version)) self.itemid = 0 data = {} reports = None for build in builds: config = BuildConfig.fetch(self.env, build.config) if not resource.id.lstrip('/').startswith(config.path.lstrip('/')): self.log.debug('Skip build %s' % build) continue path_in_config = resource.id[len(config.path) + 1:].lstrip('/') reports = Report.select(self.env, build=build.id, category='lint') for report in reports: for item in report.items: if item.get('file') == path_in_config: line = item.get('line') if line: problem = { 'category': item.get('category', ''), 'tag': item.get('tag', ''), 'bid': build.id, 'rbuild': report.build, 'rstep': report.step, 'rid': report.id } data.setdefault(int(line), []).append(problem) if data: self.log.debug("Lint annotate for %s@%s: %s results" % \ (resource.id, resource.version, len(data))) return data if not builds: self.log.debug("No builds found") elif not reports: self.log.debug("No reports found") else: self.log.debug("No item of any report matched (%s)" % reports) return None
def get_annotation_data(self, context): """add annotation data for lint""" context.perm.require('BUILD_VIEW') add_stylesheet(context.req, 'bitten/bitten_coverage.css') add_stylesheet(context.req, 'bitten/bitten_lintannotator.css') resource = context.resource # attempt to use the version passed in with the request, # otherwise fall back to the latest version of this file. try: version = context.req.args['rev'] except (KeyError, TypeError): version = resource.version self.log.debug('no version passed to get_annotation_data') builds = Build.select(self.env, rev=version) self.log.debug("Looking for lint report for %s@%s [%s]..." % ( resource.id, str(resource.version), version)) self.itemid = 0 data = {} reports = None for build in builds: config = BuildConfig.fetch(self.env, build.config) if not resource.id.lstrip('/').startswith(config.path.lstrip('/')): self.log.debug('Skip build %s' % build) continue path_in_config = resource.id[len(config.path)+1:].lstrip('/') reports = Report.select(self.env, build=build.id, category='lint') for report in reports: for item in report.items: if item.get('file') == path_in_config: line = item.get('line') if line: problem = {'category': item.get('category', ''), 'tag': item.get('tag', ''), 'bid': build.id, 'rbuild': report.build, 'rstep': report.step, 'rid': report.id} data.setdefault(int(line), []).append(problem) if data: self.log.debug("Lint annotate for %s@%s: %s results" % \ (resource.id, resource.version, len(data))) return data if not builds: self.log.debug("No builds found") elif not reports: self.log.debug("No reports found") else: self.log.debug("No item of any report matched (%s)" % reports) return None
def _render_reports(self, req, config, build, summarizers, step): reports = [] for report in Report.select(self.env, build=build.id, step=step.name): summarizer = summarizers.get(report.category) if summarizer: tmpl, data = summarizer.render_summary(req, config, build, step, report.category) else: tmpl = data = None reports.append({'category': report.category, 'template': tmpl, 'data': data}) return reports
def _render_reports(self, req, config, build, summarizers, step): reports = [] for report in Report.select(self.env, build=build.id, step=step.name): summarizer = summarizers.get(report.category) if summarizer: tmpl, data = summarizer.render_summary(req, config, build, step, report.category) reports.append({'category': report.category, 'template': tmpl, 'data': data}) else: tmpl = data = None return reports
def test_select(self): db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO bitten_report " "(build,step,category,generator) VALUES (%s,%s,%s,%s)", (1, 'test', 'test', 'unittest')) report1_id = db.get_last_id(cursor, 'bitten_report') cursor.execute( "INSERT INTO bitten_report " "(build,step,category,generator) VALUES (%s,%s,%s,%s)", (1, 'test', 'coverage', 'trace')) report2_id = db.get_last_id(cursor, 'bitten_report') cursor.executemany( "INSERT INTO bitten_report_item " "(report,item,name,value) VALUES (%s,%s,%s,%s)", [(report1_id, 0, 'file', 'tests/foo.c'), (report1_id, 0, 'result', 'failure'), (report1_id, 1, 'file', 'tests/bar.c'), (report1_id, 1, 'result', 'success'), (report2_id, 0, 'file', 'tests/foo.c'), (report2_id, 0, 'loc', '12'), (report2_id, 0, 'cov', '50'), (report2_id, 1, 'file', 'tests/bar.c'), (report2_id, 1, 'loc', '20'), (report2_id, 1, 'cov', '25')]) reports = Report.select(self.env, build=1, step='test') for idx, report in enumerate(reports): if report.id == report1_id: self.assertEquals('test', report.step) self.assertEquals('test', report.category) self.assertEquals('unittest', report.generator) self.assertEquals(2, len(report.items)) assert {'file': 'tests/foo.c', 'result': 'failure'} \ in report.items assert {'file': 'tests/bar.c', 'result': 'success'} \ in report.items elif report.id == report1_id: self.assertEquals('test', report.step) self.assertEquals('coverage', report.category) self.assertEquals('trace', report.generator) self.assertEquals(2, len(report.items)) assert {'file': 'tests/foo.c', 'loc': '12', 'cov': '50'} \ in report.items assert {'file': 'tests/bar.c', 'loc': '20', 'cov': '25'} \ in report.items self.assertEqual(1, idx)
def test_select(self): db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO bitten_report " "(build,step,category,generator) VALUES (%s,%s,%s,%s)", (1, 'test', 'test', 'unittest')) report1_id = db.get_last_id(cursor, 'bitten_report') cursor.execute("INSERT INTO bitten_report " "(build,step,category,generator) VALUES (%s,%s,%s,%s)", (1, 'test', 'coverage', 'trace')) report2_id = db.get_last_id(cursor, 'bitten_report') cursor.executemany("INSERT INTO bitten_report_item " "(report,item,name,value) VALUES (%s,%s,%s,%s)", [(report1_id, 0, 'file', 'tests/foo.c'), (report1_id, 0, 'result', 'failure'), (report1_id, 1, 'file', 'tests/bar.c'), (report1_id, 1, 'result', 'success'), (report2_id, 0, 'file', 'tests/foo.c'), (report2_id, 0, 'loc', '12'), (report2_id, 0, 'cov', '50'), (report2_id, 1, 'file', 'tests/bar.c'), (report2_id, 1, 'loc', '20'), (report2_id, 1, 'cov', '25')]) reports = Report.select(self.env, build=1, step='test') for idx, report in enumerate(reports): if report.id == report1_id: self.assertEquals('test', report.step) self.assertEquals('test', report.category) self.assertEquals('unittest', report.generator) self.assertEquals(2, len(report.items)) assert {'file': 'tests/foo.c', 'result': 'failure'} \ in report.items assert {'file': 'tests/bar.c', 'result': 'success'} \ in report.items elif report.id == report1_id: self.assertEquals('test', report.step) self.assertEquals('coverage', report.category) self.assertEquals('trace', report.generator) self.assertEquals(2, len(report.items)) assert {'file': 'tests/foo.c', 'loc': '12', 'cov': '50'} \ in report.items assert {'file': 'tests/bar.c', 'loc': '20', 'cov': '25'} \ in report.items self.assertEqual(1, idx)
def get_annotation_data(self, context): add_stylesheet(context.req, 'bitten/bitten_coverage.css') resource = context.resource builds = Build.select(self.env, rev=resource.version) reports = [] for build in builds: config = BuildConfig.fetch(self.env, build.config) if not resource.id.startswith(config.path): continue reports = Report.select(self.env, build=build.id, category='coverage') path_in_config = resource.id[len(config.path):].lstrip('/') for report in reports: for item in report.items: if item.get('file') == path_in_config: # TODO should aggregate coverage across builds return item.get('line_hits', '').split() return []
def test_process_build_step_success_with_report(self): recipe = """<build> <step id="foo"> </step> </build>""" BuildConfig(self.env, 'test', path='somepath', active=True, recipe=recipe).insert() build = Build(self.env, 'test', '123', 1, slave='hal', rev_time=42, started=42, status=Build.IN_PROGRESS) build.slave_info[Build.TOKEN] = '123'; build.insert() inbody = StringIO("""<result step="foo" status="success" time="2007-04-01T15:30:00.0000" duration="3.45"> <report category="test" generator="http://bitten.edgewall.org/tools/python#unittest"> <test fixture="my.Fixture" file="my/test/file.py"> <stdout>Doing my thing</stdout> </test> </report> </result>""") outheaders = {} outbody = StringIO() req = Mock(method='POST', base_path='', path_info='/builds/%d/steps/' % build.id, href=Href('/trac'), abs_href=Href('http://example.org/trac'), remote_addr='127.0.0.1', args={}, perm=PermissionCache(self.env, 'hal'), read=inbody.read, send_response=lambda x: outheaders.setdefault('Status', x), send_header=lambda x, y: outheaders.setdefault(x, y), write=outbody.write, incookie=Cookie('trac_auth=123')) module = BuildMaster(self.env) module._start_new_step(build, 'foo').insert() assert module.match_request(req) self.assertRaises(RequestDone, module.process_request, req) self.assertEqual(201, outheaders['Status']) self.assertEqual('20', outheaders['Content-Length']) self.assertEqual('text/plain', outheaders['Content-Type']) self.assertEqual('Build step processed', outbody.getvalue()) build = Build.fetch(self.env, build.id) self.assertEqual(Build.SUCCESS, build.status) assert build.stopped assert build.stopped > build.started steps = list(BuildStep.select(self.env, build.id)) self.assertEqual(1, len(steps)) self.assertEqual('foo', steps[0].name) self.assertEqual(BuildStep.SUCCESS, steps[0].status) reports = list(Report.select(self.env, build=build.id, step='foo')) self.assertEqual(1, len(reports)) self.assertEqual('test', reports[0].category) self.assertEqual('http://bitten.edgewall.org/tools/python#unittest', reports[0].generator) self.assertEqual(1, len(reports[0].items)) self.assertEqual({ 'fixture': 'my.Fixture', 'file': 'my/test/file.py', 'stdout': 'Doing my thing', 'type': 'test', }, reports[0].items[0])
def _render_config(self, req, config_name): db = self.env.get_db_cnx() config = BuildConfig.fetch(self.env, config_name, db=db) if not config: raise HTTPNotFound("Build configuration '%s' does not exist." \ % config_name) repos = self.env.get_repository(req.authname) repos.authz.assert_permission(config.branch) data = {'title': 'Build Configuration "%s"' \ % config.label or config.name, 'page_mode': 'view_config'} add_link(req, 'up', req.href.build(), 'Build Status') description = config.description if description: description = wiki_to_html(description, self.env, req) pending_builds = list( Build.select(self.env, config=config.name, status=Build.PENDING)) inprogress_builds = list( Build.select(self.env, config=config.name, status=Build.IN_PROGRESS)) rev = '' for b in repos.git.get_branches(): if b[0] == config.branch: rev = b[1] break data['config'] = { 'name': config.name, 'label': config.label, 'branch': config.branch, 'active': config.active, 'description': description, 'browser_href': req.href.browser(rev=rev), 'builds_pending': len(pending_builds), 'builds_inprogress': len(inprogress_builds) } context = Context.from_request(req, config.resource) data['context'] = context data['config']['attachments'] = AttachmentModule( self.env).attachment_data(context) platforms = list( TargetPlatform.select(self.env, config=config_name, db=db)) data['config']['platforms'] = [{ 'name': platform.name, 'id': platform.id, 'builds_pending': len( list( Build.select(self.env, config=config.name, status=Build.PENDING, platform=platform.id))), 'builds_inprogress': len( list( Build.select(self.env, config=config.name, status=Build.IN_PROGRESS, platform=platform.id))) } for platform in platforms] has_reports = False for report in Report.select(self.env, config=config.name, db=db): has_reports = True break if has_reports: chart_generators = [] for generator in ReportChartController(self.env).generators: for category in generator.get_supported_categories(): chart_generators.append({ 'href': req.href.build(config.name, 'chart/' + category) }) data['config']['charts'] = chart_generators charts_license = self.config.get('bitten', 'charts_license') if charts_license: data['config']['charts_license'] = charts_license page = max(1, int(req.args.get('page', 1))) more = False data['page_number'] = page repos = self.env.get_repository(req.authname) builds_per_page = 12 * len(platforms) idx = 0 builds = {} for platform, rev, build in collect_changes(repos, config): if idx >= page * builds_per_page: more = True break elif idx >= (page - 1) * builds_per_page: builds.setdefault(rev, {}) builds[rev].setdefault('href', req.href.changeset(rev)) if build and build.status != Build.PENDING: build_data = _get_build_data(self.env, req, build) build_data['steps'] = [] for step in BuildStep.select(self.env, build=build.id, db=db): build_data['steps'].append({ 'name': step.name, 'description': step.description, 'duration': to_datetime(step.stopped, utc) - \ to_datetime(step.started, utc), 'failed': not step.successful, 'errors': step.errors, 'href': build_data['href'] + '#step_' + step.name }) builds[rev][platform.id] = build_data idx += 1 data['config']['builds'] = builds if page > 1: if page == 2: prev_href = req.href.build(config.name) else: prev_href = req.href.build(config.name, page=page - 1) add_link(req, 'prev', prev_href, 'Previous Page') if more: next_href = req.href.build(config.name, page=page + 1) add_link(req, 'next', next_href, 'Next Page') prevnext_nav(req, 'Page') return data
def _render_config(self, req, config_name): db = self.env.get_db_cnx() config = BuildConfig.fetch(self.env, config_name, db=db) repos = self.env.get_repository(req.authname) if hasattr(repos, 'sync'): repos.sync() repos.authz.assert_permission(config.path) data = {'title': 'Build Configuration "%s"' \ % config.label or config.name, 'page_mode': 'view_config'} add_link(req, 'up', req.href.build(), 'Build Status') description = config.description if description: description = wiki_to_html(description, self.env, req) pending_builds = list(Build.select(self.env, config=config.name, status=Build.PENDING)) inprogress_builds = list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS)) data['config'] = { 'name': config.name, 'label': config.label, 'path': config.path, 'min_rev': config.min_rev, 'min_rev_href': req.href.changeset(config.min_rev), 'max_rev': config.max_rev, 'max_rev_href': req.href.changeset(config.max_rev), 'active': config.active, 'description': description, 'browser_href': req.href.browser(config.path), 'builds_pending' : len(pending_builds), 'builds_inprogress' : len(inprogress_builds) } platforms = list(TargetPlatform.select(self.env, config=config_name, db=db)) data['config']['platforms'] = [ { 'name': platform.name, 'id': platform.id, 'builds_pending': len(list(Build.select(self.env, config=config.name, status=Build.PENDING, platform=platform.id))), 'builds_inprogress': len(list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS, platform=platform.id))) } for platform in platforms ] has_reports = False for report in Report.select(self.env, config=config.name, db=db): has_reports = True break if has_reports: chart_generators = [] for generator in ReportChartController(self.env).generators: for category in generator.get_supported_categories(): chart_generators.append({ 'href': req.href.build(config.name, 'chart/' + category) }) data['config']['charts'] = chart_generators charts_license = self.config.get('bitten', 'charts_license') if charts_license: data['config']['charts_license'] = charts_license page = max(1, int(req.args.get('page', 1))) more = False data['page_number'] = page repos = self.env.get_repository(req.authname) if hasattr(repos, 'sync'): repos.sync() builds_per_page = 12 * len(platforms) idx = 0 builds = {} for platform, rev, build in collect_changes(repos, config): if idx >= page * builds_per_page: more = True break elif idx >= (page - 1) * builds_per_page: builds.setdefault(rev, {}) builds[rev].setdefault('href', req.href.changeset(rev)) if build and build.status != Build.PENDING: build_data = _get_build_data(self.env, req, build) build_data['steps'] = [] for step in BuildStep.select(self.env, build=build.id, db=db): build_data['steps'].append({ 'name': step.name, 'description': step.description, 'duration': datetime.fromtimestamp(step.stopped) - \ datetime.fromtimestamp(step.started), 'failed': not step.successful, 'errors': step.errors, 'href': build_data['href'] + '#step_' + step.name }) builds[rev][platform.id] = build_data idx += 1 data['config']['builds'] = builds if page > 1: if page == 2: prev_href = req.href.build(config.name) else: prev_href = req.href.build(config.name, page=page - 1) add_link(req, 'prev', prev_href, 'Previous Page') if more: next_href = req.href.build(config.name, page=page + 1) add_link(req, 'next', next_href, 'Next Page') prevnext_nav(req, 'Page') return data
def test_process_build_step_success_with_report(self): recipe = """<build> <step id="foo"> </step> </build>""" BuildConfig(self.env, 'test', path='somepath', active=True, recipe=recipe).insert() build = Build(self.env, 'test', '123', 1, slave='hal', rev_time=42, started=42, status=Build.IN_PROGRESS) build.slave_info[Build.TOKEN] = '123' build.insert() inbody = StringIO("""<result step="foo" status="success" time="2007-04-01T15:30:00.0000" duration="3.45"> <report category="test" generator="http://bitten.edgewall.org/tools/python#unittest"> <test fixture="my.Fixture" file="my/test/file.py"> <stdout>Doing my thing</stdout> </test> </report> </result>""") outheaders = {} outbody = StringIO() req = Mock(method='POST', base_path='', path_info='/builds/%d/steps/' % build.id, href=Href('/trac'), abs_href=Href('http://example.org/trac'), remote_addr='127.0.0.1', args={}, perm=PermissionCache(self.env, 'hal'), read=inbody.read, send_response=lambda x: outheaders.setdefault('Status', x), send_header=lambda x, y: outheaders.setdefault(x, y), write=outbody.write, incookie=Cookie('trac_auth=123')) module = BuildMaster(self.env) module._start_new_step(build, 'foo').insert() assert module.match_request(req) self.assertRaises(RequestDone, module.process_request, req) self.assertEqual(201, outheaders['Status']) self.assertEqual('20', outheaders['Content-Length']) self.assertEqual('text/plain', outheaders['Content-Type']) self.assertEqual('Build step processed', outbody.getvalue()) build = Build.fetch(self.env, build.id) self.assertEqual(Build.SUCCESS, build.status) assert build.stopped assert build.stopped > build.started steps = list(BuildStep.select(self.env, build.id)) self.assertEqual(1, len(steps)) self.assertEqual('foo', steps[0].name) self.assertEqual(BuildStep.SUCCESS, steps[0].status) reports = list(Report.select(self.env, build=build.id, step='foo')) self.assertEqual(1, len(reports)) self.assertEqual('test', reports[0].category) self.assertEqual('http://bitten.edgewall.org/tools/python#unittest', reports[0].generator) self.assertEqual(1, len(reports[0].items)) self.assertEqual( { 'fixture': 'my.Fixture', 'file': 'my/test/file.py', 'stdout': 'Doing my thing', 'type': 'test', }, reports[0].items[0])
def _render_config(self, req, config_name): db = self.env.get_db_cnx() config = BuildConfig.fetch(self.env, config_name, db=db) if not config: raise HTTPNotFound("Build configuration '%s' does not exist." \ % config_name) repos = self.env.get_repository(authname=req.authname) assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 'named "(default)" to Trac.' rev = config.max_rev or repos.youngest_rev try: _has_permission(req.perm, repos, config.path, rev=rev, raise_error=True) except NoSuchNode: raise TracError("Permission checking against repository path %s " "at revision %s failed." % (config.path, rev)) data = {'title': 'Build Configuration "%s"' \ % config.label or config.name, 'page_mode': 'view_config'} add_link(req, 'up', req.href.build(), 'Build Status') description = config.description if description: description = wiki_to_html(description, self.env, req) pending_builds = list(Build.select(self.env, config=config.name, status=Build.PENDING)) inprogress_builds = list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS)) data['config'] = { 'name': config.name, 'label': config.label, 'path': config.path, 'min_rev': config.min_rev, 'min_rev_href': req.href.changeset(config.min_rev), 'max_rev': config.max_rev, 'max_rev_href': req.href.changeset(config.max_rev), 'active': config.active, 'description': description, 'browser_href': req.href.browser(config.path), 'builds_pending' : len(pending_builds), 'builds_inprogress' : len(inprogress_builds) } context = Context.from_request(req, config.resource) data['context'] = context data['config']['attachments'] = AttachmentModule(self.env).attachment_data(context) platforms = list(TargetPlatform.select(self.env, config=config_name, db=db)) data['config']['platforms'] = [ { 'name': platform.name, 'id': platform.id, 'builds_pending': len(list(Build.select(self.env, config=config.name, status=Build.PENDING, platform=platform.id))), 'builds_inprogress': len(list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS, platform=platform.id))) } for platform in platforms ] has_reports = False for report in Report.select(self.env, config=config.name, db=db): has_reports = True break if has_reports: chart_generators = [] report_categories = list(self._report_categories_for_config(config)) for generator in ReportChartController(self.env).generators: for category in generator.get_supported_categories(): if category in report_categories: chart_generators.append({ 'href': req.href.build(config.name, 'chart/' + category), 'category': category, 'style': self.config.get('bitten', 'chart_style'), }) data['config']['charts'] = chart_generators page = max(1, int(req.args.get('page', 1))) more = False data['page_number'] = page repos = self.env.get_repository(authname=req.authname) assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 'named "(default)" to Trac.' builds_per_page = 12 * len(platforms) idx = 0 builds = {} revisions = [] for platform, rev, build in collect_changes(repos, config): if idx >= page * builds_per_page: more = True break elif idx >= (page - 1) * builds_per_page: if rev not in builds: revisions.append(rev) builds.setdefault(rev, {}) builds[rev].setdefault('href', req.href.changeset(rev)) builds[rev].setdefault('display_rev', repos.normalize_rev(rev)) if build and build.status != Build.PENDING: build_data = _get_build_data(self.env, req, build) build_data['steps'] = [] for step in BuildStep.select(self.env, build=build.id, db=db): build_data['steps'].append({ 'name': step.name, 'description': step.description, 'duration': to_datetime(step.stopped or int(time.time()), utc) - \ to_datetime(step.started, utc), 'status': _step_status_label[step.status], 'cls': _step_status_label[step.status].replace(' ', '-'), 'errors': step.errors, 'href': build_data['href'] + '#step_' + step.name }) builds[rev][platform.id] = build_data idx += 1 data['config']['builds'] = builds data['config']['revisions'] = revisions if page > 1: if page == 2: prev_href = req.href.build(config.name) else: prev_href = req.href.build(config.name, page=page - 1) add_link(req, 'prev', prev_href, 'Previous Page') if more: next_href = req.href.build(config.name, page=page + 1) add_link(req, 'next', next_href, 'Next Page') if arity(prevnext_nav) == 4: # Trac 0.12 compat, see #450 prevnext_nav(req, 'Previous Page', 'Next Page') else: prevnext_nav (req, 'Page') return data
def _render_config(self, req, config_name): db = self.env.get_db_cnx() config = BuildConfig.fetch(self.env, config_name, db=db) if not config: raise HTTPNotFound("Build configuration '%s' does not exist." \ % config_name) repos = self.env.get_repository(authname=req.authname) assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 'named "(default)" to Trac.' rev = config.max_rev or repos.youngest_rev try: _has_permission(req.perm, repos, config.path, rev=rev, raise_error=True) except NoSuchNode: raise TracError("Permission checking against repository path %s " "at revision %s failed." % (config.path, rev)) data = {'title': 'Build Configuration "%s"' \ % config.label or config.name, 'page_mode': 'view_config'} add_link(req, 'up', req.href.build(), 'Build Status') description = config.description if description: description = wiki_to_html(description, self.env, req) pending_builds = list( Build.select(self.env, config=config.name, status=Build.PENDING)) inprogress_builds = list( Build.select(self.env, config=config.name, status=Build.IN_PROGRESS)) data['config'] = { 'name': config.name, 'label': config.label, 'path': config.path, 'min_rev': config.min_rev, 'min_rev_href': req.href.changeset(config.min_rev), 'max_rev': config.max_rev, 'max_rev_href': req.href.changeset(config.max_rev), 'active': config.active, 'description': description, 'browser_href': req.href.browser(config.path), 'builds_pending': len(pending_builds), 'builds_inprogress': len(inprogress_builds) } context = Context.from_request(req, config.resource) data['context'] = context data['config']['attachments'] = AttachmentModule( self.env).attachment_data(context) platforms = list( TargetPlatform.select(self.env, config=config_name, db=db)) data['config']['platforms'] = [{ 'name': platform.name, 'id': platform.id, 'builds_pending': len( list( Build.select(self.env, config=config.name, status=Build.PENDING, platform=platform.id))), 'builds_inprogress': len( list( Build.select(self.env, config=config.name, status=Build.IN_PROGRESS, platform=platform.id))) } for platform in platforms] has_reports = False for report in Report.select(self.env, config=config.name, db=db): has_reports = True break if has_reports: chart_generators = [] report_categories = list( self._report_categories_for_config(config)) for generator in ReportChartController(self.env).generators: for category in generator.get_supported_categories(): if category in report_categories: chart_generators.append({ 'href': req.href.build(config.name, 'chart/' + category), 'category': category, 'style': self.config.get('bitten', 'chart_style'), }) data['config']['charts'] = chart_generators page = max(1, int(req.args.get('page', 1))) more = False data['page_number'] = page repos = self.env.get_repository(authname=req.authname) assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 'named "(default)" to Trac.' builds_per_page = 12 * len(platforms) idx = 0 builds = {} revisions = [] for platform, rev, build in collect_changes(repos, config): if idx >= page * builds_per_page: more = True break elif idx >= (page - 1) * builds_per_page: if rev not in builds: revisions.append(rev) builds.setdefault(rev, {}) builds[rev].setdefault('href', req.href.changeset(rev)) builds[rev].setdefault('display_rev', repos.normalize_rev(rev)) if build and build.status != Build.PENDING: build_data = _get_build_data(self.env, req, build) build_data['steps'] = [] for step in BuildStep.select(self.env, build=build.id, db=db): build_data['steps'].append({ 'name': step.name, 'description': step.description, 'duration': to_datetime(step.stopped or int(time.time()), utc) - \ to_datetime(step.started, utc), 'status': _step_status_label[step.status], 'cls': _step_status_label[step.status].replace(' ', '-'), 'errors': step.errors, 'href': build_data['href'] + '#step_' + step.name }) builds[rev][platform.id] = build_data idx += 1 data['config']['builds'] = builds data['config']['revisions'] = revisions if page > 1: if page == 2: prev_href = req.href.build(config.name) else: prev_href = req.href.build(config.name, page=page - 1) add_link(req, 'prev', prev_href, 'Previous Page') if more: next_href = req.href.build(config.name, page=page + 1) add_link(req, 'next', next_href, 'Next Page') if arity(prevnext_nav) == 4: # Trac 0.12 compat, see #450 prevnext_nav(req, 'Previous Page', 'Next Page') else: prevnext_nav(req, 'Page') return data