#!/usr/bin/env python3 import argparse import logging import os import re import sys import time import gitlab from launchpadlib.launchpad import Launchpad import lazr.restfulclient.errors LOG_FORMAT = "%(levelname)s - %(funcName)s - %(message)s" logging.basicConfig(format=LOG_FORMAT) LOG = logging.getLogger(__name__) parser = argparse.ArgumentParser(description="Close incomplete bug reports.") parser.add_argument('-l', '--lp-project-name', dest='lp_project_name', default='qemu', help='The Launchpad project name (qemu).') parser.add_argument('-g', '--gl-project-id', dest='gl_project_id', help='The Gitlab project ID.') parser.add_argument('--verbose', '-v', help='Enable debug logging.', action="store_true") parser.add_argument('--search-text', '-s', dest='search_text', help='Look up bugs by searching for text.') args = parser.parse_args() LOG.info(args) LOG.setLevel(logging.DEBUG if args.verbose else logging.INFO) def get_launchpad(): cache_dir = os.path.expanduser("~/.launchpadlib/cache/") if not os.path.exists(cache_dir): os.makedirs(cache_dir, 0o700) launchpad = Launchpad.login_anonymously(args.lp_project_name + '-bugs', 'production', cache_dir) return launchpad def show_bug_task(bug_task): print('Bug #%d - %s' % (bug_task.bug.id, str(bug_task.bug.title))) if args.verbose: print(' - Description: %s' % bug_task.bug.description) print(' - Tags: %s' % bug_task.bug.tags) print(' - Status: %s' % bug_task.status) print(' - Assignee: %s' % bug_task.assignee) for message in bug_task.bug.messages: print(' - Message: %s' % message.content) def transfer_to_gitlab(launchpad, project, bug_task): bug = bug_task.bug desc = "This bug has been copied automatically from: " + bug_task.web_link + \ "\n\n
" + bug.description.replace("-", "-") + "
" issue = project.issues.create({'title': bug.title, 'description': desc}) issue.labels = bug.tags for msg in bug.messages: if msg == bug.messages[0] or not msg.content.strip(): continue comment = msg.content.replace("-", "-") note = "Comment from '" + re.sub(r'^.*~', '', msg.owner_link) \ + "' on Launchpad (" \ + msg.date_created.date().isoformat() + "):\n\n
" \
		       + comment + "
" issue.notes.create({'body': note}) time.sleep(0.2) # To avoid "spamming" issue.save() def main(): LOG.info("args: %s", args) LOG.info("getting reports...") launchpad = get_launchpad() lp_project = launchpad.projects[args.lp_project_name] if args.search_text: bug_tasks = lp_project.searchTasks( search_text=args.search_text, omit_duplicates=True, order_by="datecreated") else: bug_tasks = lp_project.searchTasks( status=["New", "Confirmed", "Triaged", "In Progress"], omit_duplicates=True, order_by="datecreated") if args.gl_project_id: try: priv_token = os.environ['GITLAB_PRIVATE_TOKEN'] except Exception as e: print("Please set the GITLAB_PRIVATE_TOKEN env variable!") return gl = gitlab.Gitlab('https://gitlab.com', private_token=priv_token) gl.auth() project = gl.projects.get(args.gl_project_id) else: LOG.info("Please provide a Gitlab project ID to transfer the bugs ('-g')") for bug_task in bug_tasks: show_bug_task(bug_task) if args.gl_project_id: transfer_to_gitlab(launchpad, project, bug_task) LOG.info("All done.") if __name__ == '__main__': main()