Exemplo n.º 1
0
    def main(self, argv=None):
        """Creates PRs for in-flight CLs and merges changes that land on master.

        Returns:
            A boolean: True if success, False if there were any patch failures.
        """
        options = self.parse_args(argv)

        self.dry_run = options.dry_run
        log_level = logging.DEBUG if options.verbose else logging.INFO
        configure_logging(logging_level=log_level, include_time=True)
        if options.verbose:
            # Print out the full output when executive.run_command fails.
            self.host.executive.error_output_limit = None

        credentials = read_credentials(self.host, options.credentials_json)
        if not (credentials.get('GH_USER') and credentials.get('GH_TOKEN')):
            _log.error('You must provide your GitHub credentials for this '
                       'script to work.')
            _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

        self.wpt_github = self.wpt_github or WPTGitHub(
            self.host, credentials['GH_USER'], credentials['GH_TOKEN'])
        self.gerrit = self.gerrit or GerritAPI(
            self.host, credentials['GERRIT_USER'], credentials['GERRIT_TOKEN'])
        self.local_wpt = self.local_wpt or LocalWPT(self.host,
                                                    credentials['GH_TOKEN'])
        self.local_wpt.fetch()

        _log.info('Searching for exportable in-flight CLs.')
        # The Gerrit search API is slow and easy to fail, so we wrap it in a try
        # statement to continue exporting landed commits when it fails.
        try:
            open_gerrit_cls = self.gerrit.query_exportable_open_cls()
        except GerritError as e:
            _log.info(
                'In-flight CLs cannot be exported due to the following error:')
            _log.error(str(e))
            gerrit_error = True
        else:
            self.process_gerrit_cls(open_gerrit_cls)
            gerrit_error = False

        _log.info('Searching for exportable Chromium commits.')
        exportable_commits, git_errors = self.get_exportable_commits()
        self.process_chromium_commits(exportable_commits)
        if git_errors:
            _log.info(
                'Attention: The following errors have prevented some commits from being '
                'exported:')
            for error in git_errors:
                _log.error(error)

        return not (gerrit_error or git_errors)
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
 def test_get_credentials_gets_values_from_environment(self):
     host = MockHost()
     host.environ.update({
         'GH_USER': '******',
         'GH_TOKEN': 'pass-github',
         'GERRIT_USER': '******',
         'GERRIT_TOKEN': 'pass-gerrit',
         'UNUSED_VALUE': 'foo',
     })
     self.assertEqual(
         read_credentials(host, None), {
             'GH_USER': '******',
             'GH_TOKEN': 'pass-github',
             'GERRIT_USER': '******',
             'GERRIT_TOKEN': 'pass-gerrit',
         })
Exemplo n.º 4
0
 def test_get_credentials_gets_values_from_file(self):
     host = MockHost()
     host.filesystem.write_text_file(
         '/tmp/credentials.json',
         json.dumps({
             'GH_USER': '******',
             'GH_TOKEN': 'pass-github',
             'GERRIT_USER': '******',
             'GERRIT_TOKEN': 'pass-gerrit',
         }))
     self.assertEqual(
         read_credentials(host, '/tmp/credentials.json'), {
             'GH_USER': '******',
             'GH_TOKEN': 'pass-github',
             'GERRIT_USER': '******',
             'GERRIT_TOKEN': 'pass-gerrit',
         })
Exemplo n.º 5
0
 def test_get_credentials_choose_file_over_environment(self):
     host = MockHost()
     host.environ.update({
         'GH_USER': '******',
         'GH_TOKEN': 'pass-github-from-env',
         'GERRIT_USER': '******',
         'GERRIT_TOKEN': 'pass-gerrit-from-env',
     })
     host.filesystem.write_text_file(
         '/tmp/credentials.json',
         json.dumps({
             'GH_USER': '******',
             'GH_TOKEN': 'pass-github-from-json',
         }))
     self.assertEqual(
         read_credentials(host, '/tmp/credentials.json'), {
             'GH_USER': '******',
             'GH_TOKEN': 'pass-github-from-json',
         })
Exemplo n.º 6
0
    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
            cl_status = self.gerrit.query_cl(change_id).status
            if cl_status == 'ABANDONED':
                _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))
                self.close_abandoned_pr(pull_request)
        return True
Exemplo n.º 7
0
 def test_get_credentials_none(self):
     self.assertEqual(read_credentials(MockHost(), None), {})
Exemplo n.º 8
0
 def test_get_credentials_empty(self):
     host = MockHost()
     host.filesystem.write_text_file('/tmp/credentials.json', '{}')
     self.assertEqual(read_credentials(host, '/tmp/credentials.json'), {})
Exemplo n.º 9
0
    def main(self, argv=None):
        # TODO(robertma): Test this method! Split it to make it easier to test
        # if necessary.

        options = self.parse_args(argv)

        self.verbose = options.verbose
        log_level = logging.DEBUG if self.verbose else logging.INFO
        configure_logging(logging_level=log_level, include_time=True)

        # Having the full output when executive.run_command fails is useful when
        # investigating a failed import, as all we have are logs.
        self.executive.error_output_limit = None

        if options.auto_update and options.auto_upload:
            _log.error(
                '--auto-upload and --auto-update cannot be used together.')
            return 1

        if not self.checkout_is_okay():
            return 1

        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.warning('You have not set your GitHub credentials. This '
                         'script may fail with a network error when making '
                         'an API request to GitHub.')
            _log.warning('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.')
        self.wpt_github = self.wpt_github or WPTGitHub(self.host, gh_user,
                                                       gh_token)
        self.git_cl = GitCL(
            self.host, auth_refresh_token_json=options.auth_refresh_token_json)

        _log.debug('Noting the current Chromium revision.')
        chromium_revision = self.chromium_git.latest_git_commit()

        # Instantiate Git after local_wpt.fetch() to make sure the path exists.
        local_wpt = LocalWPT(self.host, gh_token=gh_token)
        local_wpt.fetch()
        self.wpt_git = self.host.git(local_wpt.path)

        if options.revision is not None:
            _log.info('Checking out %s', options.revision)
            self.wpt_git.run(['checkout', options.revision])

        _log.debug('Noting the revision we are importing.')
        self.wpt_revision = self.wpt_git.latest_git_commit()
        self.last_wpt_revision = self._get_last_imported_wpt_revision()
        import_commit = 'wpt@%s' % self.wpt_revision

        _log.info('Importing %s to Chromium %s', import_commit,
                  chromium_revision)

        if options.ignore_exportable_commits:
            commit_message = self._commit_message(chromium_revision,
                                                  import_commit)
        else:
            commits = self.apply_exportable_commits_locally(local_wpt)
            if commits is None:
                _log.error('Could not apply some exportable commits cleanly.')
                _log.error('Aborting import to prevent clobbering commits.')
                return 1
            commit_message = self._commit_message(
                chromium_revision,
                import_commit,
                locally_applied_commits=commits)

        self._clear_out_dest_path()

        _log.info('Copying the tests from the temp repo to the destination.')
        test_copier = TestCopier(self.host, local_wpt.path)
        test_copier.do_import()

        # TODO(robertma): Implement `add --all` in Git (it is different from `commit --all`).
        self.chromium_git.run(['add', '--all', self.dest_path])

        # Remove expectations for tests that were deleted and rename tests
        # in expectations for renamed tests.
        self._expectations_updater.cleanup_test_expectations_files()

        self._generate_manifest()

        # TODO(crbug.com/800570 robertma): Re-enable it once we fix the bug.
        # self._delete_orphaned_baselines()


        if not self.chromium_git.has_working_directory_changes():
            _log.info('Done: no changes to import.')
            return 0

        if self._only_wpt_manifest_changed():
            _log.info('Only manifest was updated; skipping the import.')
            return 0

        self._commit_changes(commit_message)
        _log.info('Changes imported and committed.')

        if not options.auto_upload and not options.auto_update:
            return 0

        self._upload_cl()
        _log.info('Issue: %s', self.git_cl.run(['issue']).strip())

        if not self.update_expectations_for_cl():
            return 1

        if not options.auto_update:
            return 0

        if not self.run_commit_queue_for_cl():
            return 1

        if not self.send_notifications(local_wpt, options.auto_file_bugs,
                                       options.monorail_auth_json):
            return 1

        return 0