ansible/roles/easyfix/files/gather_easyfix.py
Pierre-Yves Chibon 8fc4efe824 Add first work on the easyfix role
This still requires some work:
- It has no playbook
- It is missing the proxy bits
   - configuration of the proxies themselves
   - cron job copying the files from the app running the cron job onto
     the proxies
2014-03-03 17:55:03 +01:00

266 lines
8.6 KiB
Python
Executable file

#!/usr/bin/python -tt
#-*- coding: utf-8 -*-
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
The idea of this program is to gather tickets from different project
which are marked as 'easyfix' (or any other keyword for that matter).
This version is a simple proof of concept, eventually it should be
converted to an html page and this script run by a cron job of some sort.
The different project to suscribe by email or a git repo or a page on
the wiki. To be sorted out...
"""
import datetime
import json
import logging
import os
import re
import urllib2
import xmlrpclib
from bugzilla.rhbugzilla import RHBugzilla
import fedora.client
from kitchen.text.converters import to_bytes
# Let's import template stuff
from jinja2 import Template
__version__ = '0.1.1'
bzclient = RHBugzilla(url='https://bugzilla.redhat.com/xmlrpc.cgi',
cookiefile=None)
# So the bugzilla module has some way to complain
logging.basicConfig()
logger = logging.getLogger('bugzilla')
#logger.setLevel(logging.DEBUG)
RETRIES = 2
class MediaWikiException(Exception):
""" MediaWikiException class.
Exception class generated when something has gone wrong while
querying the MediaWiki instance of the project.
"""
pass
class MediaWiki(fedora.client.Wiki):
""" Mediawiki class.
Handles interaction with the Mediawiki.
Code stollen from cnucnu:
http://fedorapeople.org/gitweb?p=till/public_git/cnucnu.git;a=summary
"""
def __init__(self, base_url='https://fedoraproject.org/w/', *args,
**kwargs):
""" Instanciate a Mediawiki client.
:arg base_url: base url of the mediawiki to query.
"""
super(MediaWiki, self).__init__(base_url, *args, **kwargs)
def json_request(self, method="api.php", req_params=None,
auth=False, **kwargs):
""" Perform a json request to retrieve the content of a page.
"""
if req_params:
req_params["format"] = "json"
data = None
for i in range(0, RETRIES+1):
try:
data = self.send_request(method, req_params, auth, **kwargs)
except fedora.client.ServerError, ex:
if i >= RETRIES:
raise MediaWikiException(
'Could not contact the wiki -- error: %s' % ex)
else:
break
if 'error' in data:
raise MediaWikiException(data['error']['info'])
return data
def get_pagesource(self, titles):
""" Retrieve the content of a given page from Mediawiki.
:arg titles, the title of the page to return
"""
data = self.json_request(req_params={
'action': 'query',
'titles': titles,
'prop': 'revisions',
'rvprop': 'content'
}
)
return data['query']['pages'].popitem()[1]['revisions'][0]['*']
class Project(object):
""" Simple object representation of a project. """
def __init__(self):
self.name = ""
self.url = ""
self.site = ""
self.owner = ""
self.tag = ""
self.tickets = []
class Ticket(object):
""" Simple object representation of a ticket. """
def __init__(self):
self.id = ""
self.url = ""
self.title = ""
self.status = ""
self.type = ""
self.component = ""
def gather_bugzilla_easyfix():
""" From the Red Hat bugzilla, retrieve all new tickets flagged as
easyfix.
"""
bugbz = bzclient.query(
{'f1': 'keywords',
'o1': 'allwords',
'v1': 'easyfix',
'query_format': 'advanced',
'bug_status': ['NEW'],
'classification': 'Fedora'})
#print " {0} easyfix bugs retrieve from the BZ ".format(len(bugbz))
return bugbz
def gather_project():
""" Retrieve all the projects which have subscribed to this idea.
"""
wiki = MediaWiki(base_url='https://fedoraproject.org/w/')
page = wiki.get_pagesource("Easyfix")
projects = []
for row in page.split('\n'):
regex = re.search(' \* ([^ ]*) ([^ ]*)( [^ ]*)?', row)
if regex:
project = Project()
project.name = regex.group(1)
project.tag = regex.group(2)
project.owner = regex.group(3)
projects.append(project)
return projects
def get_open_tickets_for_keyword(project, keyword):
""" For a given project return the tickets ID which have the given
keyword attached.
:arg project, name of the project on fedorahosted.org
:arg keyword, search the trac for open tickets having this keyword
in the keywords field.
"""
tickets = []
try:
server = xmlrpclib.ServerProxy(
'https://fedorahosted.org/%s/rpc' % project)
query = 'status=assigned&status=new&status=reopened&' \
'keywords=~%s' % keyword
for ticket in server.ticket.query(query):
tickets.append(server.ticket.get(ticket))
except xmlrpclib.Error, err:
print ' Could not retrieve information for project: %s' % project
print ' Error: %s' % err
return tickets
def main():
""" For each projects which have suscribed in the correct place
(fedoraproject wiki page), gather all the tickets containing the
provided keyword.
"""
template = '/etc/fedora-gather-easyfix/template.html'
if not os.path.exists(template):
template = './template.html'
if not os.path.exists(template):
print 'No template found'
return 1
try:
projects = gather_project()
except MediaWikiException, ex:
print ex
return
ticket_num = 0
for project in projects:
#print 'Project: %s' % project.name
tickets = []
if project.name.startswith('github:'):
project.name = project.name.split('github:')[1]
project.url = 'http://github.com/%s/' % (project.name)
project.site = 'github'
url = 'https://api.github.com/repos/%s/issues' \
'?labels=%s&state=open' % (project.name, project.tag)
stream = urllib2.urlopen(url)
output = stream.read()
jsonobj = json.loads(output)
if jsonobj:
for ticket in jsonobj:
ticket_num = ticket_num + 1
ticketobj = Ticket()
ticketobj.id = ticket['number']
ticketobj.title = ticket['title']
ticketobj.url = ticket['html_url']
ticketobj.status = ticket['state']
tickets.append(ticketobj)
else:
project.url = 'http://fedorahosted.org/%s/' % (project.name)
project.site = 'trac'
for ticket in get_open_tickets_for_keyword(project.name,
project.tag):
ticket_num = ticket_num + 1
ticketobj = Ticket()
ticketobj.id = ticket[0]
ticketobj.title = ticket[3]['summary']
ticketobj.url = 'http://fedorahosted.org/%s/ticket/%s' %(
project, ticket[0])
ticketobj.status = ticket[3]['status']
ticketobj.type = ticket[3]['type']
ticketobj.component = ticket[3]['component']
tickets.append(ticketobj)
project.tickets = tickets
bzbugs = gather_bugzilla_easyfix()
try:
# Read in template
stream = open(template, 'r')
tplfile = stream.read()
stream.close()
# Fill the template
mytemplate = Template(tplfile)
html = mytemplate.render(projects=projects, bzbugs = bzbugs,
ticket_num=ticket_num, bzbugs_num=len(bzbugs),
date=datetime.datetime.now().strftime("%a %b %d %Y %H:%M"))
# Write down the page
stream = open('index.html', 'w')
stream.write(to_bytes(html))
stream.close()
except IOError, err:
print 'ERROR: %s' % err
if __name__ == '__main__':
main()