<gh_stars>1000+
"""Cleans up PRs that correspond to abandoned CLs in Gerrit."""

import argparse
import logging

from blinkpy.common.system.log_utils import configure_logging
from blinkpy.w3c.wpt_github import WPTGitHub
from blinkpy.w3c.gerrit import GerritAPI, GerritError
from blinkpy.w3c.common import (read_credentials)

_log = logging.getLogger(__name__)


class PrCleanupTool(object):
    def __init__(self, host):
        self.host = host
        self.wpt_github = None
        self.gerrit = None

    def main(self, argv=None):
        """Closes all PRs that are abandoned in Gerrit."""
        options = self.parse_args(argv)
        log_level = logging.DEBUG if options.verbose else logging.INFO
        configure_logging(logging_level=log_level, include_time=True)
        credentials = read_credentials(self.host, options.credentials_json)
        gh_user = credentials.get('GH_USER')
        gh_token = credentials.get('GH_TOKEN')
        if not gh_user or not gh_token:
            _log.error('You have not set your GitHub credentials. This '
                       'script may fail with a network error when making '
                       'an API request to GitHub.')
            _log.error('See https://chromium.googlesource.com/chromium/src'
                       '/+/master/docs/testing/web_platform_tests.md'
                       '#GitHub-credentials for instructions on how to set '
                       'your credentials up.')
            return False

        gr_user = credentials['GERRIT_USER']
        gr_token = credentials['GERRIT_TOKEN']
        if not gr_user or not gr_token:
            _log.warning('You have not set your Gerrit credentials. This '
                         'script may fail with a network error when making '
                         'an API request to Gerrit.')

        self.wpt_github = self.wpt_github or WPTGitHub(self.host, gh_user,
                                                       gh_token)
        self.gerrit = self.gerrit or GerritAPI(self.host, gr_user, gr_token)
        pull_requests = self.retrieve_all_prs()
        for pull_request in pull_requests:
            if pull_request.state != 'open':
                continue
            change_id = self.wpt_github.extract_metadata(
                'Change-Id: ', pull_request.body)

            if not change_id:
                continue

            try:
                cl = self.gerrit.query_cl(change_id)
            except GerritError as e:
                _log.error('Could not query change_id %s: %s', change_id,
                           str(e))
                continue

            cl_status = cl.status
            if cl_status == 'ABANDONED':
                comment = 'Close this PR because the Chromium CL has been abandoned.'
                self.log_affected_pr_details(pull_request, comment)
                self.close_pr_and_delete_branch(pull_request.number, comment)
            elif cl_status == 'MERGED' and (not cl.is_exportable()):
                comment = 'Close this PR because the Chromium CL does not have exportable changes.'
                self.log_affected_pr_details(pull_request, comment)
                self.close_pr_and_delete_branch(pull_request.number, comment)

        return True

    def parse_args(self, argv):
        parser = argparse.ArgumentParser()
        parser.description = __doc__
        parser.add_argument(
            '-v',
            '--verbose',
            action='store_true',
            help='log extra details that may be helpful when debugging')
        parser.add_argument(
            '--credentials-json',
            help='A JSON file with GitHub credentials, '
            'generally not necessary on developer machines')
        return parser.parse_args(argv)

    def retrieve_all_prs(self):
        """Retrieves last 1000 PRs."""
        return self.wpt_github.all_pull_requests()

    def close_pr_and_delete_branch(self, pull_request_number, comment):
        """Closes a PR with a comment and delete the corresponding branch."""
        self.wpt_github.add_comment(pull_request_number, comment)
        self.wpt_github.update_pr(pull_request_number, state='closed')
        branch = self.wpt_github.get_pr_branch(pull_request_number)
        self.wpt_github.delete_remote_branch(branch)

    def log_affected_pr_details(self, pull_request, comment):
        """Logs details of an affected PR."""
        _log.info(comment)
        _log.info('https://github.com/web-platform-tests/wpt/pull/%s',
                  pull_request.number)
        _log.info(
            self.wpt_github.extract_metadata('Reviewed-on: ',
                                             pull_request.body))

"""Cleans up PRs that correspond to abandoned CLs in Gerrit."""

import argparse
import logging

from blinkpy.common.system.log_utils import configure_logging
from blinkpy.w3c.wpt_github import WPTGitHub
from blinkpy.w3c.gerrit import GerritAPI, GerritError
from blinkpy.w3c.common import (read_credentials)

_log = logging.getLogger(__name__)


class PrCleanupTool(object):
    def __init__(self, host):
        self.host = host
        self.wpt_github = None
        self.gerrit = None

    def main(self, argv=None):
        """Closes all PRs that are abandoned in Gerrit."""
        options = self.parse_args(argv)
        log_level = logging.DEBUG if options.verbose else logging.INFO
        configure_logging(logging_level=log_level, include_time=True)
        credentials = read_credentials(self.host, options.credentials_json)
        gh_user = credentials.get('GH_USER')
        gh_token = credentials.get('GH_TOKEN')
        if not gh_user or not gh_token:
            _log.error('You have not set your GitHub credentials. This '
                       'script may fail with a network error when making '
                       'an API request to GitHub.')
            _log.error('See https://chromium.googlesource.com/chromium/src'
                       '/+/master/docs/testing/web_platform_tests.md'
                       '#GitHub-credentials for instructions on how to set '
                       'your credentials up.')
            return False

        gr_user = credentials['GERRIT_USER']
        gr_token = credentials['GERRIT_TOKEN']
        if not gr_user or not gr_token:
            _log.warning('You have not set your Gerrit credentials. This '
                         'script may fail with a network error when making '
                         'an API request to Gerrit.')

        self.wpt_github = self.wpt_github or WPTGitHub(self.host, gh_user,
                                                       gh_token)
        self.gerrit = self.gerrit or GerritAPI(self.host, gr_user, gr_token)
        pull_requests = self.retrieve_all_prs()
        for pull_request in pull_requests:
            if pull_request.state != 'open':
                continue
            change_id = self.wpt_github.extract_metadata(
                'Change-Id: ', pull_request.body)

            if not change_id:
                continue

            try:
                cl = self.gerrit.query_cl(change_id)
            except GerritError as e:
                _log.error('Could not query change_id %s: %s', change_id,
                           str(e))
                continue

            cl_status = cl.status
            if cl_status == 'ABANDONED':
                comment = 'Close this PR because the Chromium CL has been abandoned.'
                self.log_affected_pr_details(pull_request, comment)
                self.close_pr_and_delete_branch(pull_request.number, comment)
            elif cl_status == 'MERGED' and (not cl.is_exportable()):
                comment = 'Close this PR because the Chromium CL does not have exportable changes.'
                self.log_affected_pr_details(pull_request, comment)
                self.close_pr_and_delete_branch(pull_request.number, comment)

        return True

    def parse_args(self, argv):
        parser = argparse.ArgumentParser()
        parser.description = __doc__
        parser.add_argument(
            '-v',
            '--verbose',
            action='store_true',
            help='log extra details that may be helpful when debugging')
        parser.add_argument(
            '--credentials-json',
            help='A JSON file with GitHub credentials, '
            'generally not necessary on developer machines')
        return parser.parse_args(argv)

    def retrieve_all_prs(self):
        """Retrieves last 1000 PRs."""
        return self.wpt_github.all_pull_requests()

    def close_pr_and_delete_branch(self, pull_request_number, comment):
        """Closes a PR with a comment and delete the corresponding branch."""
        self.wpt_github.add_comment(pull_request_number, comment)
        self.wpt_github.update_pr(pull_request_number, state='closed')
        branch = self.wpt_github.get_pr_branch(pull_request_number)
        self.wpt_github.delete_remote_branch(branch)

    def log_affected_pr_details(self, pull_request, comment):
        """Logs details of an affected PR."""
        _log.info(comment)
        _log.info('https://github.com/web-platform-tests/wpt/pull/%s',
                  pull_request.number)
        _log.info(
            self.wpt_github.extract_metadata('Reviewed-on: ',
                                             pull_request.body))
Cleans up PRs that correspond to abandoned CLs in Gerrit. Closes all PRs that are abandoned in Gerrit. Retrieves last 1000 PRs. Closes a PR with a comment and delete the corresponding branch. Logs details of an affected PR.