diff --git a/import.py b/import.py index 605487e..3865591 100755 --- a/import.py +++ b/import.py @@ -8,7 +8,8 @@ import argparse import sys -from importer import validate_json, print_labels +from importer import validate_json, print_labels, create_issue, get_as_json, format_post_body, format_issue, fake_message +from termcolor import cprint if __name__ == '__main__': parser = argparse.ArgumentParser() @@ -18,8 +19,43 @@ help='Print all labels used by issues.') parser.add_argument('-f', '--force', action='store_true', help='Don\'t validate labels against the issues repo.') + parser.add_argument('-o', '--origin', + choices=['moz', 'ms', 'blink', 'apple'], + help='Adjust the import to the JSON issue format') + publishgroup = parser.add_mutually_exclusive_group() + publishgroup.add_argument('-t', '--test', action='store_true', + help='NO publishing on Github, just testing') + publishgroup.add_argument('-g', '--github', action='store_true', + help='Publishing on Github. Irreversible.') args = parser.parse_args() + # Printing the list of existing labels on Github if args.labels: print_labels() sys.exit(0) - validate_json(args.issue_file, args.force) + elif args.origin: + # Let's get the data + json_data = get_as_json(args.issue_file) + # create the data with the right format + webcompat_issue = format_issue(json_data, args.origin) + else: + cprint('Missing --labels or --origin', 'white', 'on_red') + parser.print_help() + sys.exit(0) + # Validation + if validate_json(webcompat_issue, args.force): + if args.github: + # Mode with consequences + create_issue(webcompat_issue) + cprint('Creating the issue on Github', 'green') + elif args.test: + # Mode without consequences + cprint('Test Mode Run. Nothing is sent to github', 'yellow') + print fake_message(webcompat_issue) + else: + cprint('Missing --test or --github', 'white', 'on_red') + parser.print_help() + sys.exit(0) + else: + cprint('Invalid JSON data for the issue', 'red') + sys.exit(0) + diff --git a/importer/__init__.py b/importer/__init__.py index d6ed2d9..b375560 100644 --- a/importer/__init__.py +++ b/importer/__init__.py @@ -17,6 +17,8 @@ from schema import schema from termcolor import cprint from textwrap import fill +import adapters + LABEL_VALIDATION_ERROR = ''' You attempted to create an issue with an unknown label. GitHub ignores unknown @@ -26,7 +28,7 @@ ''' REPO_URI = 'https://api.github.com/repos/{0}'.format(REPO_PATH) - +USER_AGENT = 'Webcompat-Issue-Importer' def get_issue_body(json_data): '''Return the issue body in the proper format.''' @@ -42,6 +44,18 @@ def get_issue_body(json_data): json_data['body']) +def format_issue(json_data, json_format): + '''Transform the issue data into something usable by importer''' + if json_format == 'moz': + cprint('Converting Mozilla bugs', 'yellow') + webcompat_json = adapters.mozilla_adapter.convert_issue_data(json_data) + else: + webcompat_json = None + cprint('Time for you to code an adapter', 'white', 'on_red') + print 'We need an adapter for the format %s' % (json_format) + print 'See http://github.com/webcompat/issue-importer' + return webcompat_json + def format_post_body(json_data): '''Create the POST "body" object.''' body = {'body': get_issue_body(json_data), @@ -55,10 +69,21 @@ def api_post(uri, body): what gets created (currently either an issue or a comment).''' headers = { 'Authorization': 'token {0}'.format(OAUTH_TOKEN), - 'User-Agent': 'Webcompat-Issue-Importer' + 'User-Agent': USER_AGENT } return requests.post(uri, data=json.dumps(body), headers=headers) +def fake_message(webcompat_issue): + '''Generate a fake message for the dry run''' + message = u''' + POST /repos/{0} HTTP/1.1 + Host: api.github.com + Authorization: ***OBFUSCATED**** + User-Agent: {1} + + {2} + ''' + return message.format(REPO_PATH, USER_AGENT, format_post_body(webcompat_issue)) def create_issue(json_data): '''Create a new GitHub issue by POSTing data to the issues API endpoint. @@ -103,14 +128,15 @@ def get_as_json(issue_file): return r -def validate_json(issue_file, skip_labels=False): - '''Validate the structure of `file_name` against our JSON schema.''' - json_data = get_as_json(issue_file) +def validate_json(json_data, skip_labels=False): + '''Validate the structure of `json_data` against our JSON schema.''' if not skip_labels: - schema['properties']['labels']['items'].update(enum=get_labels()) + labels = get_labels() + labels.extend(['serversniff', 'clientsniff', 'imported']) + schema['properties']['labels']['items'].update(enum=labels) try: jsonschema.validate(json_data, schema) - create_issue(json_data) + return True except jsonschema.exceptions.ValidationError as e: cprint('JSON Schema validation failed:', 'white', 'on_red') print('\n') @@ -119,6 +145,7 @@ def validate_json(issue_file, skip_labels=False): print(e.message) else: print(e) + return False def get_labels(): diff --git a/importer/adapters/__init__.py b/importer/adapters/__init__.py new file mode 100644 index 0000000..d82ef5a --- /dev/null +++ b/importer/adapters/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from . import mozilla_adapter \ No newline at end of file diff --git a/importer/adapters/mozilla_adapter.py b/importer/adapters/mozilla_adapter.py new file mode 100644 index 0000000..caddd2d --- /dev/null +++ b/importer/adapters/mozilla_adapter.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import re +VALID_LABELS = ['serversniff', 'clientsniff'] + +def convert_issue_data(json_data): + '''Take the json data from the bug repo and convert it + into json data suitable for webcompat. + + Documentation of HTTP Mozilla Bugzilla API: + http://bugzilla.org/docs/tip/html/api/Bugzilla/WebService/Server/REST.html + http://bugzilla.org/docs/tip/html/api/Bugzilla/WebService/Bug.html + ''' + webcompat_json = None + # json_data is a list of bugs we only want the first one + bug_data = json_data['bugs'][0] + source = 'https://bugzilla.mozilla.org/show_bug.cgi?id=%s' % (bug_data['id']) + os = bug_data['op_sys'].lower() + # Let's gather some labels + regex = re.compile(ur'\[(.*?)\]') + whiteboard_labels = re.findall(regex, bug_data['whiteboard']) + # We probably want to filter out labels that are only mozilla. + moz_labels = [label for label in whiteboard_labels if label in VALID_LABELS] + moz_labels.extend([u'firefox', os, u'imported']) + webcompat_json = { + 'url': bug_data['url'], + 'title': bug_data['summary'], + 'os': os, + 'browser': u'Firefox', + 'source_human': source, + 'labels': moz_labels, + 'body': 'body is missing. Need to code it' + } + return webcompat_json \ No newline at end of file