See PR: https://github.com/fedora-infra/fedora-gather-easyfix/pull/13 Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
308 lines
10 KiB
Python
Executable file
308 lines
10 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 argparse
|
|
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, tokenfile=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 stolen from cnucnu:
|
|
https://fedorapeople.org/gitweb?p=till/public_git/cnucnu.git;a=summary
|
|
"""
|
|
|
|
{% if env == 'staging' %}
|
|
def __init__(self, base_url='https://stg.fedoraproject.org/w/', *args,
|
|
{% else %}
|
|
def __init__(self, base_url='https://fedoraproject.org/w/', *args,
|
|
{% endif %}
|
|
**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 with keyword
|
|
easyfix or whiteboard trivial.
|
|
"""
|
|
bugbz_easyfix = bzclient.query(
|
|
{'f1': 'keywords',
|
|
'o1': 'allwords',
|
|
'v1': 'easyfix',
|
|
'query_format': 'advanced',
|
|
'bug_status': ['NEW'],
|
|
'classification': 'Fedora'})
|
|
# print " {0} easyfix bugs retrieved from BZ".format(len(bugbz_easyfix))
|
|
bugbz_trivial = bzclient.query(
|
|
{
|
|
'status_whiteboard': 'trivial',
|
|
'status_whiteboard_type': 'anywords',
|
|
'query_format': 'advanced',
|
|
'bug_status': ['NEW'],
|
|
'classification': 'Fedora'
|
|
})
|
|
# print " {0} trivial bugs retrieved from BZ".format(len(bugbz))
|
|
return (bugbz_easyfix + bugbz_trivial)
|
|
|
|
|
|
def gather_project():
|
|
""" Retrieve all the projects which have subscribed to this idea.
|
|
"""
|
|
{% if env == 'staging' %}
|
|
wiki = MediaWiki(base_url='https://stg.fedoraproject.org/w/')
|
|
{% else %}
|
|
wiki = MediaWiki(base_url='https://fedoraproject.org/w/')
|
|
{% endif %}
|
|
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 parse_arguments():
|
|
parser = argparse.ArgumentParser(__doc__)
|
|
parser.add_argument(
|
|
'--fedmenu-url', help="URL of the fedmenu resources (optional)")
|
|
parser.add_argument(
|
|
'--fedmenu-data-url', help="URL of the fedmenu data source (optional)")
|
|
args = parser.parse_args()
|
|
result = {}
|
|
for key in ['fedmenu_url', 'fedmenu_data_url']:
|
|
if getattr(args, key):
|
|
result[key] = getattr(args, key)
|
|
return result
|
|
|
|
|
|
def main():
|
|
""" For each projects which have suscribed in the correct place
|
|
(fedoraproject wiki page), gather all the tickets containing the
|
|
provided keyword.
|
|
"""
|
|
|
|
extra_kwargs = parse_arguments()
|
|
|
|
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 = 'https://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)
|
|
elif project.name.startswith('pagure.io:'):
|
|
project.name = project.name.split('pagure.io:')[1]
|
|
project.url = 'https://pagure.io/%s/' % (project.name)
|
|
project.site = 'pagure.io'
|
|
url = 'https://pagure.io/api/0/%s/issues' \
|
|
'?status=Open&tags=%s' % (project.name, project.tag)
|
|
stream = urllib2.urlopen(url)
|
|
output = stream.read()
|
|
jsonobj = json.loads(output)
|
|
if jsonobj:
|
|
for ticket in jsonobj['issues']:
|
|
ticket_num = ticket_num + 1
|
|
ticketobj = Ticket()
|
|
ticketobj.id = ticket['id']
|
|
ticketobj.title = ticket['title']
|
|
ticketobj.url = 'https://pagure.io/%s/issue/%s' % (
|
|
project.name, ticket['id'])
|
|
ticketobj.status = ticket['status']
|
|
tickets.append(ticketobj)
|
|
elif project.name.startswith('gitlab.com:'):
|
|
# https://docs.gitlab.com/ee/api/issues.html#list-project-issues
|
|
project.name = project.name.split('gitlab.com:')[1]
|
|
project.url = 'https://gitlab.com/%s/' % (project.name)
|
|
project.site = 'gitlab.com'
|
|
url = 'https://gitlab.com/api/v4/projects/%s/issues' \
|
|
'?state=opened&labels=%s' % (urllib2.quote(project.name,
|
|
safe=''),
|
|
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['id']
|
|
ticketobj.title = ticket['title']
|
|
ticketobj.url = ticket['web_url']
|
|
ticketobj.status = ticket['state']
|
|
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"),
|
|
**extra_kwargs
|
|
)
|
|
# 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()
|