Beispiel #1
0
 def test_init_missing_required_fields(self):
     with self.assertRaises(AssertionError):
         MonorailIssue('', summary='test', status='Untriaged')
     with self.assertRaises(AssertionError):
         MonorailIssue('chromium', summary='', status='Untriaged')
     with self.assertRaises(AssertionError):
         MonorailIssue('chromium', summary='test', status='')
 def test_init_string_passed_for_list_fields(self):
     with self.assertRaises(AssertionError):
         MonorailIssue('chromium', summary='test', status='Untriaged', cc='*****@*****.**')
     with self.assertRaises(AssertionError):
         MonorailIssue('chromium', summary='test', status='Untriaged', components='Infra')
     with self.assertRaises(AssertionError):
         MonorailIssue('chromium', summary='test', status='Untriaged', labels='Flaky')
Beispiel #3
0
 def test_init_succeeds(self):
     # Minimum example.
     MonorailIssue('chromium', summary='test', status='Untriaged')
     # All fields.
     MonorailIssue('chromium',
                   summary='test',
                   status='Untriaged',
                   description='body',
                   cc=['*****@*****.**'],
                   labels=['Flaky'],
                   components=['Infra'])
 def test_new_chromium_issue(self):
     issue = MonorailIssue.new_chromium_issue(
         'test', description='body', cc=['*****@*****.**'], components=['Infra'])
     self.assertEqual(issue.project_id, 'chromium')
     self.assertEqual(issue.body['summary'], 'test')
     self.assertEqual(issue.body['description'], 'body')
     self.assertEqual(issue.body['cc'], ['*****@*****.**'])
     self.assertEqual(issue.body['components'], ['Infra'])
 def test_str(self):
     issue = MonorailIssue('chromium', summary='test', status='Untriaged', description='body',
                           cc=['*****@*****.**', '*****@*****.**'], labels=['Flaky'], components=['Infra'])
     self.assertEqual(str(issue),
                      ('Monorail issue in project chromium\n'
                       'Summary: test\n'
                       'Status: Untriaged\n'
                       'CC: [email protected], [email protected]\n'
                       'Components: Infra\n'
                       'Labels: Flaky\n'
                       'Description:\nbody\n'))
Beispiel #6
0
    def create_bugs_from_new_failures(self, wpt_revision_start, wpt_revision_end, gerrit_url):
        """Files bug reports for new failures.

        Args:
            wpt_revision_start: The start of the imported WPT revision range
                (exclusive), i.e. the last imported revision.
            wpt_revision_end: The end of the imported WPT revision range
                (inclusive), i.e. the current imported revision.
            gerrit_url: Gerrit URL of the CL.

        Return:
            A list of MonorailIssue objects that should be filed.
        """
        imported_commits = self.local_wpt.commits_in_range(wpt_revision_start, wpt_revision_end)
        bugs = []
        for directory, failures in self.new_failures_by_directory.iteritems():
            summary = '[WPT] New failures introduced in {} by import {}'.format(directory, gerrit_url)

            full_directory = self.host.filesystem.join(self.finder.layout_tests_dir(), directory)
            owners_file = self.host.filesystem.join(full_directory, 'OWNERS')
            is_wpt_notify_enabled = self.owners_extractor.is_wpt_notify_enabled(owners_file)

            owners = self.owners_extractor.extract_owners(owners_file)
            # owners may be empty but not None.
            cc = owners + ['*****@*****.**']

            component = self.owners_extractor.extract_component(owners_file)
            # component could be None.
            components = [component] if component else None

            prologue = ('WPT import {} introduced new failures in {}:\n\n'
                        'List of new failures:\n'.format(gerrit_url, directory))
            failure_list = ''
            for failure in failures:
                failure_list += str(failure) + '\n'

            epilogue = '\nThis import contains upstream changes from {} to {}:\n'.format(
                wpt_revision_start, wpt_revision_end
            )
            commit_list = self.format_commit_list(imported_commits, full_directory)

            description = prologue + failure_list + epilogue + commit_list

            bug = MonorailIssue.new_chromium_issue(summary, description, cc, components)
            _log.info(unicode(bug))

            if is_wpt_notify_enabled:
                _log.info("WPT-NOTIFY enabled in this directory; adding the bug to the pending list.")
                bugs.append(bug)
            else:
                _log.info("WPT-NOTIFY disabled in this directory; discarding the bug.")
        return bugs
Beispiel #7
0
    def create_bugs_for_product(self, wpt_revision_start, wpt_revision_end,
                                gerrit_url, product, expectation_lines):
        """Files bug reports for new failures per product

        Args:
            wpt_revision_start: The start of the imported WPT revision range
                (exclusive), i.e. the last imported revision.
            wpt_revision_end: The end of the imported WPT revision range
                (inclusive), i.e. the current imported revision.
            gerrit_url: Gerrit URL of the CL.
            product: the product for which to file bugs for.
            expectation_lines: list of new expectations for this product

        Return:
            A MonorailIssue object that should be filed.
        """
        bugs = []
        summary = '[WPT] New failures introduced by import {}'.format(gerrit_url)

        prologue = ('WPT import {} introduced new failures:\n\n'
                    'List of new failures:\n'.format(gerrit_url))

        failure_list = ''
        for _, failure in expectation_lines.items():
            failure_list += str(failure) + '\n'

        expectations_statement = (
            '\nExpectations have been automatically added for '
            'the failing results to keep the bots green. Please '
            'investigate the new failures and triage as appropriate.\n')

        range_statement = '\nThis import contains upstream changes from {} to {}:\n'.format(
            wpt_revision_start, wpt_revision_end)

        description = (prologue + failure_list + expectations_statement +
                       range_statement)

        bug = MonorailIssue.new_chromium_issue(
            summary,
            description,
            cc=[],
            components=self.components_for_product[product],
            labels=self.labels_for_product[product])
        bugs.append(bug)
        return bugs
Beispiel #8
0
    def file_bugs(self, bugs, dry_run, service_account_key_json=None):
        """Files a list of bugs to Monorail.

        Args:
            bugs: A list of MonorailIssue objects.
            dry_run: A boolean, whether we are in dry run mode.
            service_account_key_json: Optional, see docs for main().
        """
        # TODO(robertma): Better error handling in this method.
        if dry_run:
            _log.info('[dry_run] Would have filed the %d bugs in the pending list.', len(bugs))
            return

        _log.info('Filing %d bugs in the pending list to Monorail', len(bugs))
        api = self._get_monorail_api(service_account_key_json)
        for index, bug in enumerate(bugs, start=1):
            response = api.insert_issue(bug)
            _log.info('[%d] Filed bug: %s', index, MonorailIssue.crbug_link(response['id']))
Beispiel #9
0
 def test_unicode(self):
     issue = MonorailIssue(
         'chromium',
         summary=u'test',
         status='Untriaged',
         description=
         u'ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ',
         cc=['*****@*****.**', '*****@*****.**'],
         labels=['Flaky'],
         components=['Infra'])
     self.assertEqual(type(unicode(issue)), unicode)
     self.assertEqual(unicode(issue), (
         u'Monorail issue in project chromium\n'
         u'Summary: test\n'
         u'Status: Untriaged\n'
         u'CC: [email protected], [email protected]\n'
         u'Components: Infra\n'
         u'Labels: Flaky\n'
         u'Description:\nABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ\n'
     ))
Beispiel #10
0
    def create_bugs_from_new_failures(self, wpt_revision_start,
                                      wpt_revision_end, gerrit_url):
        """Files bug reports for new failures.

        Args:
            wpt_revision_start: The start of the imported WPT revision range
                (exclusive), i.e. the last imported revision.
            wpt_revision_end: The end of the imported WPT revision range
                (inclusive), i.e. the current imported revision.
            gerrit_url: Gerrit URL of the CL.

        Return:
            A list of MonorailIssue objects that should be filed.
        """
        imported_commits = self.local_wpt.commits_in_range(
            wpt_revision_start, wpt_revision_end)
        bugs = []
        for directory, failures in self.new_failures_by_directory.items():
            summary = '[WPT] New failures introduced in {} by import {}'.format(
                directory, gerrit_url)

            full_directory = self.host.filesystem.join(
                self.finder.web_tests_dir(), directory)
            owners_file = self.host.filesystem.join(full_directory, 'OWNERS')
            metadata_file = self.host.filesystem.join(full_directory,
                                                      'DIR_METADATA')
            is_wpt_notify_enabled = False
            try:
                is_wpt_notify_enabled = self.owners_extractor.is_wpt_notify_enabled(
                    metadata_file)
            except KeyError:
                _log.info('KeyError when parsing %s' % metadata_file)

            if not is_wpt_notify_enabled:
                _log.info("WPT-NOTIFY disabled in %s." % full_directory)
                continue

            owners = self.owners_extractor.extract_owners(owners_file)
            # owners may be empty but not None.
            cc = owners

            component = self.owners_extractor.extract_component(metadata_file)
            # component could be None.
            components = [component] if component else None

            prologue = ('WPT import {} introduced new failures in {}:\n\n'
                        'List of new failures:\n'.format(
                            gerrit_url, directory))
            failure_list = ''
            for failure in failures:
                failure_list += str(failure) + '\n'

            expectations_statement = (
                '\nExpectations or baseline files [0] have been automatically '
                'added for the failing results to keep the bots green. Please '
                'investigate the new failures and triage as appropriate.\n')

            range_statement = '\nThis import contains upstream changes from {} to {}:\n'.format(
                wpt_revision_start, wpt_revision_end)
            commit_list = self.format_commit_list(imported_commits,
                                                  full_directory)

            links_list = '\n[0]: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/web_test_expectations.md\n'

            description = (prologue + failure_list + expectations_statement +
                           range_statement + commit_list + links_list)

            bug = MonorailIssue.new_chromium_issue(summary,
                                                   description,
                                                   cc,
                                                   components,
                                                   labels=['Test-WebTest'])
            _log.info(bug)
            _log.info("WPT-NOTIFY enabled in %s; adding the bug to the pending list." % full_directory)
            bugs.append(bug)
        return bugs
Beispiel #11
0
 def test_crbug_link(self):
     self.assertEqual(MonorailIssue.crbug_link(12345),
                      'https://crbug.com/12345')
Beispiel #12
0
 def test_init_unknown_status(self):
     with self.assertRaises(AssertionError):
         MonorailIssue('chromium', summary='test', status='unknown')
Beispiel #13
0
 def test_init_unknown_fields(self):
     with self.assertRaises(AssertionError):
         MonorailIssue('chromium', component='foo')
Beispiel #14
0
 def test_init_fills_project_id(self):
     issue = MonorailIssue('chromium', summary='test', status='Untriaged')
     self.assertEqual(issue.body['projectId'], 'chromium')