def process_request(self,req): options = get_options(self.config) build_type_match = re.match('/builds/history/(bt\d+)?$',req.path_info) if build_type_match is None: query_string = "&".join(['buildTypeId=%s' % id for id in options['builds']]) else: build_type_id = build_type_match.groups()[0] query_string = 'buildTypeId=%s' % build_type_id add_stylesheet(req, 'teamcity/css/teamcity.css') query_string += '&sinceDate=-%d' % options['limit'] feed_url = "%s/feed.html?%s" % (options['base_url'], query_string) tc = TeamCityQuery(self.options) feed = TeamCityQuery.xml_query(feed_url) if feed is None: raise HTTPNotFound("Can't load feed") data = {'entries': []} for entry in feed.iterfind('{http://www.w3.org/2005/Atom}entry'): title = entry.find('{http://www.w3.org/2005/Atom}title').text link = entry.find('{http://www.w3.org/2005/Atom}link').attrib['href'] date = entry.find('{http://www.w3.org/2005/Atom}published').text date = datetime.strptime(date, '%Y-%m-%dT%H:%M:%SZ') summary = entry.find('{http://www.w3.org/2005/Atom}summary').text summary = summary.split('<a href')[0] build_id_match = re.search('buildId=(\d+)', link) if build_id_match: summary += "<br/><a href='%s'>Build Log</a>" % \ req.href.builds('download', build_id_match.groups()[0]) data['entries'].append({ 'title': title, 'link': link, 'date': date, 'summary': summary, }) return 'teamcity_status.html', data, None
def get_timeline_events(self, req, start, stop, filters): """Returns a list of events in the time range given by the `start` and `stop` parameters. Full description here http://trac.edgewall.org/browser/trunk/trac/timeline/api.py """ if 'build' not in filters: return # exit if there is not any buildType in options if not self.options.get('builds', True): return # get rss feed query_string = "&".join( ['buildTypeId=%s' % id for id in self.options['builds']]) query_string += '&sinceDate=-%d' % self.options['limit'] feed_url = "%s/httpAuth/feed.html?%s" % (self.options['base_url'], query_string) tc = TeamCityQuery(self.options) try: feed = tc.xml_query(feed_url) except TeamCityError as e: self.log.error("Error while proceed TeamCity events: %s" % e) return if feed is None: self.log.error("Can't get teamcity feed") return add_stylesheet(req, 'teamcity/css/teamcity.css') add_javascript(req, 'teamcity/js/loadlog.js') # iterate over resulted xml feed for entry in feed.iterfind('{http://www.w3.org/2005/Atom}entry'): event_date = entry.find( '{http://www.w3.org/2005/Atom}published').text event_date = datetime.strptime(event_date, '%Y-%m-%dT%H:%M:%SZ') event_date = event_date.replace(tzinfo=GMT0()) if (event_date < start) or (event_date > stop): continue event_title = entry.find('{http://www.w3.org/2005/Atom}title').text event_status = entry.find( '{http://purl.org/dc/elements/1.1/}creator').text event_status = event_status.lower().replace(' ', '_') # get build id build_url = entry.find( '{http://www.w3.org/2005/Atom}link').attrib['href'] build_id, build_type = get_build_ids(build_url) # get build message if event_status == 'successful_build': msg = 'Build was successful' else: msg = 'Build failed' data = { 'date': event_date, 'status': event_status, 'title': event_title, 'build_url': build_url, 'build_type': build_type, 'build_id': build_id, 'message': msg, } yield event_status, event_date, 'ci server', data
def process_request(self,req): try: path = req.path_info.split('/builds/proxy/')[1] except IndexError: # no trailing slash ex. raise HTTPNotFound("Invalid proxy url, no trailing slash") t_url = "%s/httpAuth/%s?%s" % (self.options['base_url'], path,req.environ['QUERY_STRING']) tc = TeamCityQuery(self.options) try: response = tc.http_query(t_url) except TeamCityError, e: raise HTTPBadGateway('An error occured during proxy request to %s: %s' % (t_url, e))
def get_timeline_events(self, req, start, stop, filters): """Returns a list of events in the time range given by the `start` and `stop` parameters. Full description here http://trac.edgewall.org/browser/trunk/trac/timeline/api.py """ if 'build' not in filters: return # exit if there is not any buildType in options if not self.options.get('builds',True): return # get rss feed query_string = "&".join(['buildTypeId=%s' % id for id in self.options['builds']]) query_string += '&sinceDate=-%d' % self.options['limit'] feed_url = "%s/httpAuth/feed.html?%s" % (self.options['base_url'], query_string) tc = TeamCityQuery(self.options) try: feed = tc.xml_query(feed_url) except TeamCityError as e: self.log.error("Error while proceed TeamCity events: %s" % e) return if feed is None: self.log.error("Can't get teamcity feed") return add_stylesheet(req,'teamcity/css/teamcity.css') add_javascript(req,'teamcity/js/loadlog.js') # iterate over resulted xml feed for entry in feed.iterfind('{http://www.w3.org/2005/Atom}entry'): event_date = entry.find('{http://www.w3.org/2005/Atom}published').text event_date = datetime.strptime(event_date, '%Y-%m-%dT%H:%M:%SZ') event_date = event_date.replace(tzinfo=GMT0()) if (event_date < start) or (event_date > stop): continue event_title = entry.find('{http://www.w3.org/2005/Atom}title').text event_status = entry.find('{http://purl.org/dc/elements/1.1/}creator').text event_status = event_status.lower().replace(' ','_') # get build id build_url = entry.find('{http://www.w3.org/2005/Atom}link').attrib['href'] build_id, build_type = get_build_ids(build_url) # get build message if event_status == 'successful_build': msg = 'Build was successful' else: msg = 'Build failed' data = { 'date': event_date, 'status': event_status, 'title': event_title, 'build_url': build_url, 'build_type': build_type, 'build_id': build_id, 'message': msg, } yield event_status, event_date, 'ci server', data
def render_admin_panel(self, req, category, page, path_info): if not req.perm.has_permission('TEAMCITY_ADMIN'): raise HTTPForbidden('You are not allowed to configure TC plugin') if req.method == 'POST': options, errors = self._save_options(req.args) if not errors: # redirect here req.redirect(req.href(req.path_info)) else: options, errors = get_options(self.config), [] tc = TeamCityQuery(options) url = "%s/httpAuth/app/rest/buildTypes" % options['base_url'] # load builds from TC using REST API try: builds_xml = tc.xml_query(url) except TeamCityError, e: errors.append("Fix base config options: %s" % e) t_data = {'options': options, 'projects': {}, 'errors': errors} return 'teamcity_admin.html', t_data
def render_admin_panel(self,req,category,page,path_info): if not req.perm.has_permission('TEAMCITY_ADMIN'): raise HTTPForbidden('You are not allowed to configure TC plugin') if req.method == 'POST': options,errors = self._save_options(req.args) if not errors: # redirect here req.redirect(req.href(req.path_info)) else: options,errors = get_options(self.config),[] tc = TeamCityQuery(options) url = "%s/httpAuth/app/rest/buildTypes" % options['base_url'] # load builds from TC using REST API try: builds_xml = tc.xml_query(url) except TeamCityError,e: errors.append("Fix base config options: %s" % e) t_data = {'options':options,'projects':{},'errors':errors} return 'teamcity_admin.html',t_data
def process_request(self,req): if not req.perm.has_permission('TEAMCITY_BUILD'): raise HTTPForbidden('You are not allowed to view/run TC builds') options = get_options(self.config) tc = TeamCityQuery(options) # projects variable will collect builds result in following format: # {'projectId': { # 'name': 'Proj1', # 'btypes': [{ # it's a list of build types assigned to this project # 'btype_id': 'bt1', # 'btype_name': 'PS3 builds' # 'build': { # 'number': 5555 # teamcity number # 'status': 'Success', # 'start_date': datetime_object, # 'end_date': datetime_object, # },] # } # } projects = {} for build_type in options['builds']: # load builds xml from teamcity url = "%s/httpAuth/app/rest/buildTypes/id:%s/builds" %\ (options['base_url'],build_type) btype_xml = tc.xml_query(url) if btype_xml is None: self.log.error("Can't load builds xml at %s" % url) continue if len(btype_xml) < 1: # there is not any builds yet url = '%s/httpAuth/app/rest/buildTypes/id:%s' % (options['base_url'], build_type) build_xml = tc.xml_query(url) if build_xml is None: continue proj_id = build_xml.xpath('/buildType/project/@id')[0] # collect here as many build info as possible and continue build_info = { 'btype_id': build_type, 'btype_name': build_xml.attrib['name'], 'build': { 'id': None, 'number': None, 'status': 'unknown', 'end_date': 'Never', 'duration': 'Unknown' } } if proj_id in projects: projects[proj_id]['btypes'].append(build_info) else: # or create new item in projects projects[proj_id] = { 'name': proj_name, 'btypes': [build_info,] } continue # There is at least one finished build last_build = btype_xml[0].attrib # load this build xml url = "%s%s" % (options['base_url'],last_build['href']) build_xml = tc.xml_query(url) if build_xml is None: self.log.error("Can't load build xml at %s" % url) proj_id = build_xml.xpath('/build/buildType/@projectId')[0] proj_name = build_xml.xpath('/build/buildType/@projectName')[0] # F**k! python2.5 has not support for timezones in datetime.strptime try: # datetime lacks timezone info start_date = build_xml.xpath('/build/startDate/text()')[0].split('+')[0] start_date = datetime.strptime(start_date, '%Y%m%dT%H%M%S') # datetime lacks timezone info end_date = build_xml.xpath('/build/finishDate/text()')[0].split('+')[0] end_date = datetime.strptime(end_date, '%Y%m%dT%H%M%S') except IndexError: # no start_date or end_date, duration is unknown end_date = 'Never' duration = 'Unknown' else: duration = end_date - start_date # parse build status try: status = build_xml.xpath('/build/statusText/text()')[0].lower() except IndexError: # no last status yet status = 'unknown' # result build dictionary build_info = { 'btype_id': build_type, 'btype_name': build_xml.xpath('/build/buildType/@name')[0], 'build': { 'id': build_xml.attrib['id'], 'number': build_xml.attrib['number'], 'status': status, 'end_date': end_date, 'duration': duration } } # add new build to project if proj_id in projects: projects[proj_id]['btypes'].append(build_info) else: # or create new item in projects projects[proj_id] = { 'name': proj_name, 'btypes': [build_info,] } add_stylesheet(req,'teamcity/css/teamcity.css') add_javascript(req,'teamcity/js/jquery.timers-1.2.js') add_javascript(req,'teamcity/js/event_tracker.js') return 'teamcity_builds.html', { 'projects':projects, 'dpath':req.href('builds/download') }, None