示例#1
0
    def test_publish_summary(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            IssueComment('Terrible things'),
            Comment(filename_1, 117, 117, 'Something bad'),
            Comment(filename_1, 119, 119, 'Something bad'),
        )
        problems.add_many(errors)
        problems.set_changes([1])

        review = Review(self.repo, self.pr, self.config)
        review.publish_summary(problems)

        assert self.pr.create_comment.called
        self.assertEqual(1, self.pr.create_comment.call_count)

        msg = """There are 3 errors:

* Terrible things
* Console/Command/Task/AssetBuildTask.php, line 117 - Something bad
* Console/Command/Task/AssetBuildTask.php, line 119 - Something bad
"""
        self.pr.create_comment.assert_called_with(msg)
示例#2
0
    def test_publish_problems_remove_ok_label(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        sha = 'abc123'

        review = Review(self.gh, 3)
        label = 'No lint errors'

        with add_ok_label(self.gh, 3, review, label):
            sha = 'abc123'
            review.publish_problems(problems, sha)

        assert self.issue.remove_label.called, 'Label should be removed'
        assert self.pr.create_review_comment.called, 'Comments should be added'
        eq_(2, self.pr.create_review_comment.call_count)

        self.issue.remove_label.assert_called_with(label)
        assert_review_comments_created(
            self.pr.create_review_comment.call_args_list,
            errors,
            sha)
示例#3
0
    def test_publish_problems(self):
        gh = Mock()
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        sha = 'abc123'

        review = Review(gh, 3)
        review.publish_problems(problems, sha)

        assert gh.pull_requests.comments.create.called
        eq_(2, gh.pull_requests.comments.create.call_count)
        calls = gh.pull_requests.comments.create.call_args_list

        expected = call(3, {
            'commit_id': sha,
            'path': errors[0][0],
            'position': errors[0][1],
            'body': errors[0][2]
        })
        eq_(calls[0], expected)

        expected = call(3, {
            'commit_id': sha,
            'path': errors[1][0],
            'position': errors[1][1],
            'body': errors[1][2]
        })
        eq_(calls[1], expected)
示例#4
0
class Processor(object):

    def __init__(self, client, number, head, target_path):
        self._client = client
        self._number = number
        self._head = head
        self._target_path = target_path
        self._changes = None
        self._problems = Problems(target_path)
        self._review = Review(client, number)

    def load_changes(self):
        log.info('Loading pull request patches from github.')
        files = self._client.pull_requests.list_files(self._number)
        pull_request_patches = files.all()
        self._changes = DiffCollection(pull_request_patches)
        self._problems.set_changes(self._changes)

    def run_tools(self, review_config):
        if self._changes is None:
            raise RuntimeError('No loaded changes, cannot run tools. '
                               'Try calling load_changes first.')
        files_to_check = self._changes.get_files(
            append_base=self._target_path,
            ignore_patterns=review_config.ignore_patterns())
        tools.run(
            review_config,
            self._problems,
            files_to_check,
            self._target_path)

    def publish(self, wait_time=0):
        self._problems.limit_to_changes()
        self._review.publish(self._problems, self._head, wait_time)
示例#5
0
    def test_filter_existing__removes_duplicates(self):
        fixture_data = load_fixture('comments_current.json')
        self.pr.review_comments.return_value = map(
            lambda f: GhIssueComment(f),
            json.loads(fixture_data))
        problems = Problems()
        review = Review(self.gh, 2)
        filename_1 = "Routing/Filter/AssetCompressor.php"
        filename_2 = "View/Helper/AssetCompressHelper.php"

        problems.add(filename_1, 87, 'A pithy remark')
        problems.add(filename_1, 87, 'Something different')
        problems.add(filename_2, 88, 'I <3 it')
        problems.add(filename_2, 89, 'Not such a good comment')

        review.load_comments()
        review.remove_existing(problems)

        res = problems.all(filename_1)
        eq_(1, len(res))
        expected = Comment(filename_1, 87, 87, 'Something different')
        eq_(res[0], expected)

        res = problems.all(filename_2)
        eq_(1, len(res))
        expected = Comment(filename_2, 88, 88, 'I <3 it')
        eq_(res[0], expected)
示例#6
0
    def test_publish_checkrun(self):
        self.repo.create_checkrun = Mock()
        tst_config = build_review_config(fixer_ini,
                                         {'PULLREQUEST_STATUS': True})
        problems = Problems()
        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 8, 'Something bad'),
            Comment(filename_1, 119, 9, 'Something worse'),
        )
        problems.add_many(errors)
        run_id = 42

        review = Review(self.repo, self.pr, tst_config)
        review.publish_checkrun(problems, run_id)

        assert self.repo.update_checkrun.called
        self.assertEqual(1, self.repo.update_checkrun.call_count)

        assert_checkrun(
            self,
            self.repo.update_checkrun.call_args,
            errors,
            run_id)
        assert self.repo.create_status.called is False, 'no status required'
示例#7
0
    def test_filter_existing__removes_duplicates(self):
        fixture_data = load_fixture('comments_current.json')
        self.pr.review_comments.return_value = [
            GhIssueComment(f, self.session) for f in json.loads(fixture_data)
        ]
        problems = Problems()
        review = Review(self.repo, self.pr, self.config)
        filename_1 = "Routing/Filter/AssetCompressor.php"
        filename_2 = "View/Helper/AssetCompressHelper.php"

        problems.add(filename_1, 87, 'A pithy remark')
        problems.add(filename_1, 87, 'Something different')
        problems.add(filename_2, 88, 'I <3 it')
        problems.add(filename_2, 89, 'Not such a good comment')

        review.load_comments()
        review.remove_existing(problems)

        res = problems.all(filename_1)
        self.assertEqual(1, len(res))
        expected = Comment(filename_1,
                           87,
                           87,
                           'A pithy remark\nSomething different')
        self.assertEqual(res[0], expected)

        res = problems.all(filename_2)
        self.assertEqual(1, len(res))
        expected = Comment(filename_2, 88, 88, 'I <3 it')
        self.assertEqual(res[0], expected)
示例#8
0
    def test_filter_existing__removes_duplicates(self, http):
        fixture_data = load_fixture('comments_current.json')
        response = Response()
        response._content = fixture_data
        http.return_value = response

        gh = Github()
        problems = Problems()
        review = Review(gh, 2)
        filename_1 = "Routing/Filter/AssetCompressor.php"
        filename_2 = "View/Helper/AssetCompressHelper.php"

        problems.add(filename_1, 87, 'A pithy remark')
        problems.add(filename_1, 87, 'Something different')
        problems.add(filename_2, 88, 'I <3 it')
        problems.add(filename_2, 89, 'Not such a good comment')

        review.load_comments()
        review.remove_existing(problems)

        res = problems.all(filename_1)
        eq_(1, len(res))
        expected = Comment(filename_1, 87, 87, 'Something different')
        eq_(res[0], expected)

        res = problems.all(filename_2)
        eq_(1, len(res))
        expected = Comment(filename_2, 88, 88, 'I <3 it')
        eq_(res[0], expected)
示例#9
0
    def test_publish_empty_comment_add_ok_label(self):
        gh = Mock()
        problems = Problems(changes=[])
        review = Review(gh, 3)
        label = config.get('OK_LABEL', 'No lint errors')

        with add_ok_label(gh, 3, label):
            sha = 'abc123'
            review.publish(problems, sha)

        assert not gh.pull_requests.comments.create.called
        assert gh.issues.comments.create.called
        assert gh.issues.labels.remove_from_issue.called
        assert_add_to_issue(gh)

        calls = gh.issues.labels.remove_from_issue.call_args_list

        expected = call(3, label)
        eq_(calls, [expected])

        calls = gh.issues.comments.create.call_args_list

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')
        expected = call(3, msg)
        eq_(calls[0], expected)
示例#10
0
    def test_publish_pull_review_remove_ok_label(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 117, 'Something bad'),
            Comment(filename_1, 119, 119, 'Something bad'),
        )
        problems.add_many(errors)
        tst_config = build_review_config(fixer_ini, {'OK_LABEL': 'No lint'})

        review = Review(self.repo, self.pr, tst_config)
        sha = 'abc123'
        review.publish_pull_review(problems, sha)

        assert self.pr.remove_label.called, 'Label should be removed'
        assert self.pr.create_review.called, 'Review should be added'
        self.assertEqual(1, self.pr.create_review.call_count)

        self.pr.remove_label.assert_called_with(tst_config['OK_LABEL'])
        assert_review(
            self,
            self.pr.create_review.call_args,
            errors,
            sha)
示例#11
0
    def test_publish_summary(self):
        gh = Mock()
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        problems.set_changes([1])
        sha = 'abc123'

        review = Review(gh, 3)
        review.publish_summary(problems)

        assert gh.issues.comments.create.called
        eq_(1, gh.issues.comments.create.call_count)
        calls = gh.issues.comments.create.call_args_list

        msg = """There are 2 errors:

* Console/Command/Task/AssetBuildTask.php, line 117 - Something bad
* Console/Command/Task/AssetBuildTask.php, line 119 - Something bad
"""
        expected = call(3, msg)
        eq_(calls[0], expected)
示例#12
0
    def test_publish_problems_remove_ok_label(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        sha = 'abc123'
        config = {'OK_LABEL': 'No lint'}

        review = Review(self.repo, self.pr, config)
        sha = 'abc123'
        review.publish_problems(problems, sha)

        assert self.pr.remove_label.called, 'Label should be removed'
        assert self.pr.create_review_comment.called, 'Comments should be added'
        eq_(2, self.pr.create_review_comment.call_count)

        self.pr.remove_label.assert_called_with(config['OK_LABEL'])
        assert_review_comments_created(
            self.pr.create_review_comment.call_args_list,
            errors,
            sha)
示例#13
0
    def test_load_comments__none_active(self):
        fixture_data = load_fixture('comments_none_current.json')
        self.pr.review_comments.return_value = [GhIssueComment(f) for f in json.loads(fixture_data)]

        review = Review(self.gh, 2)
        review.load_comments()

        eq_(0, len(review.comments("View/Helper/AssetCompressHelper.php")))
示例#14
0
    def test_publish_status__ok_no_comment_or_label(self):
        config = {'OK_COMMENT': None, 'OK_LABEL': None}
        review = Review(self.gh, 3, config)
        review.publish_status(0)

        assert self.gh.create_status.called, 'Create status not called'
        assert not self.issue.create_comment.called, 'Comment not created'
        assert not self.issue.add_labels.called, 'Label added created'
示例#15
0
    def test_publish_pull_review__no_comments(self):
        problems = Problems()
        sha = 'abc123'

        review = Review(self.repo, self.pr, self.config)
        review.publish_pull_review(problems, sha)

        assert self.pr.create_review.called is False
示例#16
0
    def test_load_comments__none_active(self):
        fixture_data = load_fixture('comments_none_current.json')
        self.pr.review_comments.return_value = map(
            lambda f: GhIssueComment(f),
            json.loads(fixture_data))

        review = Review(self.repo, self.pr)
        review.load_comments()

        eq_(0, len(review.comments("View/Helper/AssetCompressHelper.php")))
示例#17
0
    def test_load_comments__none_active(self):
        fixture_data = load_fixture('comments_none_current.json')
        self.pr.review_comments.return_value = [
            GhIssueComment(f, self.session) for f in json.loads(fixture_data)
        ]

        review = Review(self.repo, self.pr, self.config)
        review.load_comments()

        filename = "View/Helper/AssetCompressHelper.php"
        self.assertEqual(0, len(review.comments(filename)))
示例#18
0
    def test_load_comments__none_active(self, http):
        fixture_data = load_fixture('comments_none_current.json')
        response = Response()
        response._content = fixture_data
        http.return_value = response

        gh = Github()
        review = Review(gh, 2)
        review.load_comments()

        eq_(0, len(review.comments("View/Helper/AssetCompressHelper.php")))
示例#19
0
class Processor(object):

    _client = None
    _number = None
    _head = None
    _target_path = None
    _changes = None
    _problems = None
    _review = None
    _config = None

    def __init__(self, client, number, head, target_path, config=None):
        self._client = client
        self._number = number
        self._head = head
        self._target_path = target_path
        self._problems = Problems(target_path)
        self._review = Review(client, number)

        if config is None:
            config = {}
        self._config = config

    def load_changes(self):
        log.info('Loading pull request patches from github.')
        files = self._client.pull_requests.list_files(self._number)
        pull_request_patches = files.all()
        self._changes = DiffCollection(pull_request_patches)
        self._problems.set_changes(self._changes)

    def run_tools(self, review_config):
        if self._changes is None:
            raise RuntimeError('No loaded changes, cannot run tools. '
                               'Try calling load_changes first.')
        files_to_check = self._changes.get_files(
            append_base=self._target_path,
            ignore_patterns=review_config.ignore_patterns())
        commits_to_check = self.get_commits(self._number)
        tools.run(
            review_config,
            self._problems,
            files_to_check,
            commits_to_check,
            self._target_path)

    def publish(self):
        self._problems.limit_to_changes()
        self._review.publish(
            self._problems,
            self._head,
            self._config.get('SUMMARY_THRESHOLD'))

    def get_commits(self, number):
        return self._client.pull_requests.list_commits(number).all()
示例#20
0
    def test_publish_status__ok_no_comment_label_or_status(self):
        config = {
            'OK_COMMENT': None,
            'OK_LABEL': None,
            'PULLREQUEST_STATUS': False,
        }
        review = Review(self.repo, self.pr, config)
        review.publish_status(0)

        assert not self.repo.create_status.called, 'Create status called'
        assert not self.pr.create_comment.called, 'Comment not created'
        assert not self.pr.add_label.called, 'Label added created'
示例#21
0
    def test_publish_review_empty_comment(self):
        problems = Problems(changes=DiffCollection([]))
        review = Review(self.repo, self.pr, self.config)

        sha = 'abc123'
        review.publish_review(problems, sha)

        assert self.pr.create_comment.called, 'Should create a comment'

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')
        self.pr.create_comment.assert_called_with(msg)
示例#22
0
    def test_publish_empty_comment(self):
        problems = Problems(changes=[])
        review = Review(self.gh, 3)

        sha = 'abc123'
        review.publish(problems, sha)

        assert self.issue.create_comment.called, 'Should create a comment'

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')
        self.issue.create_comment.assert_called_with(msg)
示例#23
0
    def test_publish_status__ok_no_comment_or_label(self):
        app_config = {
            'OK_COMMENT': None,
            'OK_LABEL': None,
            'PULLREQUEST_STATUS': False,
        }
        tst_config = build_review_config(fixer_ini, app_config)
        review = Review(self.repo, self.pr, tst_config)
        review.publish_status(False)

        assert self.repo.create_status.called, 'Create status called'
        assert not self.pr.create_comment.called, 'Comment not created'
        assert not self.pr.add_label.called, 'Label added created'
示例#24
0
class Processor(object):

    _repository = None
    _pull_request = None
    _target_path = None
    _changes = None
    _problems = None
    _review = None
    _config = None

    def __init__(self, repository, pull_request, target_path, config=None):
        config = config if config else {}
        self._config = config
        self._repository = repository
        self._pull_request = pull_request
        self._target_path = target_path
        self._problems = Problems(target_path)
        self._review = Review(repository, pull_request, config)

    def load_changes(self):
        log.info('Loading pull request patches from github.')
        files = self._pull_request.files()
        self._changes = DiffCollection(files)
        self._problems.set_changes(self._changes)

    def run_tools(self, review_config):
        if self._changes is None:
            raise RuntimeError('No loaded changes, cannot run tools. '
                               'Try calling load_changes first.')
        files_to_check = self._changes.get_files(
            append_base=self._target_path,
            ignore_patterns=review_config.ignore_patterns())
        commits_to_check = self._pull_request.commits()
        log.debug("_problems before tools: %s" % len(self._problems))
        self._problems = tools.run(
            review_config,
            self._problems,
            files_to_check,
            commits_to_check,
            self._target_path)
        log.debug("_problems after tools: %s" % len(self._problems))


    def publish(self):
        self._problems.limit_to_changes()
        self._review.publish(
            self._problems,
            self._pull_request.head,
            self._config.get('SUMMARY_THRESHOLD'))
示例#25
0
    def test_publish_review_empty_comment_add_ok_label(self):
        problems = Problems(changes=DiffCollection([]))
        tst_config = build_review_config(fixer_ini, {'OK_LABEL': 'No lint'})
        review = Review(self.repo, self.pr, tst_config)

        sha = 'abc123'
        review.publish_review(problems, sha)

        assert self.pr.create_comment.called, 'ok comment should be added.'
        assert self.pr.remove_label.called, 'label should be removed.'
        self.pr.remove_label.assert_called_with(tst_config['OK_LABEL'])

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')
        self.pr.create_comment.assert_called_with(msg)
示例#26
0
    def test_publish_pull_review__only_issue_comment(self):
        problems = Problems()
        problems.add(IssueComment('Very bad'))
        sha = 'abc123'

        review = Review(self.repo, self.pr, self.config)
        review.publish_pull_review(problems, sha)

        assert self.pr.create_review.called
        assert_review(
            self,
            self.pr.create_review.call_args,
            [],
            sha,
            body='Very bad')
示例#27
0
    def test_publish_empty_comment_add_ok_label(self):
        problems = Problems(changes=[])
        config = {'OK_LABEL': 'No lint'}
        review = Review(self.repo, self.pr, config)

        sha = 'abc123'
        review.publish(problems, sha)

        assert self.pr.create_comment.called, 'ok comment should be added.'
        assert self.pr.remove_label.called, 'label should be removed.'
        self.pr.remove_label.assert_called_with(config['OK_LABEL'])

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')
        self.pr.create_comment.assert_called_with(msg)
示例#28
0
    def test_publish_ok_comment(self):
        gh = Mock()
        problems = Problems()
        review = Review(gh, 3)

        sha = 'abc123'
        review.publish(problems, sha)

        assert not(gh.pull_requests.comments.create.called)
        assert gh.issues.comments.create.called

        calls = gh.issues.comments.create.call_args_list

        expected = call(3, ':+1: No lint errors found.')
        eq_(calls[0], expected)
示例#29
0
 def test_factory_generates_tools(self):
     gh = Mock(spec=github3.GitHub)
     config = build_review_config(sample_ini)
     linters = tools.factory(config, Review(gh, None, config), '')
     self.assertEqual(2, len(linters))
     self.assertIsInstance(linters[0], pep8.Pep8)
     self.assertIsInstance(linters[1], jshint.Jshint)
示例#30
0
    def test_publish_status__ok_with_comment_and_label(self):
        config = {'OK_COMMENT': 'Great job!', 'OK_LABEL': 'No lint errors'}
        review = Review(self.repo, self.pr, config)
        review.publish_status(0)

        assert self.repo.create_status.called, 'Create status not called'
        self.repo.create_status.assert_called_with(
            self.pr.head,
            'success',
            'No lint errors found.')

        assert self.pr.create_comment.called, 'Issue comment created'
        self.pr.create_comment.assert_called_with('Great job!')

        assert self.pr.add_label.called, 'Label added created'
        self.pr.add_label.assert_called_with('No lint errors')
示例#31
0
    def test_publish_ok_comment(self):
        gh = Mock()
        problems = Problems(changes=[1])
        review = Review(gh, 3)

        sha = 'abc123'
        review.publish(problems, sha)

        assert not (gh.pull_requests.comments.create.called)
        assert gh.issues.comments.create.called

        calls = gh.issues.comments.create.call_args_list

        expected = call(3,
                        config.get('OK_COMMENT', ':+1: No lint errors found.'))
        eq_(calls[0], expected)
示例#32
0
 def __init__(self, repository, pull_request, target_path, config):
     self._config = config
     self._repository = repository
     self._pull_request = pull_request
     self._target_path = target_path
     self.problems = Problems()
     self._review = Review(repository, pull_request, config)
示例#33
0
    def test_publish_status__has_errors(self):
        config = {
            'OK_COMMENT': 'Great job!',
            'OK_LABEL': 'No lint errors',
            'APP_NAME': 'custom-name'
        }
        review = Review(self.repo, self.pr, config)
        review.publish_status(1)

        assert self.repo.create_status.called, 'Create status not called'

        self.repo.create_status.assert_called_with(
            self.pr.head, 'failure',
            'Lint errors found, see pull request comments.')
        assert not self.pr.create_comment.called, 'Comment not created'
        assert not self.pr.add_label.called, 'Label added created'
示例#34
0
    def setUp(self):
        repo = Mock(spec=GithubRepository)
        pr = Mock(spec=GithubPullRequest, head='abc123', number=2)
        repo.pull_request.return_value = pr

        self.repo, self.pr = repo, pr
        self.review = Review(repo, pr)
示例#35
0
def test_factory_generates_tools():
    gh = Mock(spec=github3.GitHub)
    config = build_review_config(sample_ini)
    linters = tools.factory(Review(gh, None), config, '')
    eq_(2, len(linters))
    assert isinstance(linters[0], tools.pep8.Pep8)
    assert isinstance(linters[1], tools.jshint.Jshint)
示例#36
0
    def test_publish_empty_comment_add_ok_label(self):
        problems = Problems(changes=[])
        review = Review(self.gh, 3)
        label = 'No lint errors'

        with add_ok_label(self.gh, 3, review, label):
            sha = 'abc123'
            review.publish(problems, sha)

        assert self.issue.create_comment.called, 'ok comment should be added.'
        assert self.issue.remove_label.called, 'label should be removed.'
        self.issue.remove_label.assert_called_with(label)

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')
        self.issue.create_comment.assert_called_with(msg)
示例#37
0
    def test_publish_empty_comment(self):
        gh = Mock()
        problems = Problems(changes=[])
        review = Review(gh, 3)

        sha = 'abc123'
        review.publish(problems, sha)

        assert not (gh.pull_requests.comments.create.called)
        assert gh.issues.comments.create.called

        calls = gh.issues.comments.create.call_args_list

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')
        expected = call(3, msg)
        eq_(calls[0], expected)
示例#38
0
    def test_publish_checkrun__multiple_chunks(self):
        self.repo.create_checkrun = Mock()
        tst_config = build_review_config(fixer_ini,
                                         {'PULLREQUEST_STATUS': True})
        problems = Problems()
        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = [
            Comment(filename_1, i, i, 'Something worse') for i in range(0, 70)
        ]
        problems.add_many(errors)
        problems.add(IssueComment('In the body'))
        run_id = 42

        review = Review(self.repo, self.pr, tst_config)
        review.publish_checkrun(problems, run_id)

        assert self.repo.update_checkrun.call_count == 2
        assert self.repo.create_status.called is False, 'no status required'

        first_call = self.repo.update_checkrun.call_args_list[0]
        assert run_id == first_call[0][0]

        first_payload = first_call[0][1]
        assert 'failure' == first_payload['conclusion']

        assert 'completed_at' in first_payload
        assert 'title' in first_payload['output']
        assert 'summary' in first_payload['output']
        assert 'annotations' in first_payload['output']

        assert 'In the body' == first_payload['output']['summary']
        assert 50 == len(first_payload['output']['annotations'])

        second_call = self.repo.update_checkrun.call_args_list[1]
        assert run_id == second_call[0][0]

        # The second payload should only contain additional annotations.
        second_payload = second_call[0][1]
        assert 'completed_at' not in second_payload
        assert 'title' in second_payload['output']
        assert 'summary' in second_payload['output']
        assert 'annotations' in second_payload['output']
        assert 'In the body' == second_payload['output']['summary']

        assert 20 == len(second_payload['output']['annotations'])
示例#39
0
    def test_publish_status__ok_with_comment_label_and_status(self):
        config = {
            'OK_COMMENT': 'Great job!',
            'OK_LABEL': 'No lint errors',
            'PULLREQUEST_STATUS': True,
        }
        review = Review(self.repo, self.pr, config)
        review.publish_status(0)

        assert self.repo.create_status.called, 'Create status not called'
        self.repo.create_status.assert_called_with(self.pr.head, 'success',
                                                   'No lint errors found.')

        assert self.pr.create_comment.called, 'Issue comment created'
        self.pr.create_comment.assert_called_with('Great job!')

        assert self.pr.add_label.called, 'Label added created'
        self.pr.add_label.assert_called_with('No lint errors')
示例#40
0
    def test_publish_status__ok_with_comment_and_label(self):
        config = {'OK_COMMENT': 'Great job!', 'OK_LABEL': 'No lint errors'}
        review = Review(self.gh, 3, config)
        review.publish_status(0)

        assert self.gh.create_status.called, 'Create status not called'
        self.gh.create_status.assert_called_with(
            self.pr.head.sha,
            'success',
            None,
            'No lint errors found.',
            'lintreview')

        assert self.issue.create_comment.called, 'Issue comment created'
        self.issue.create_comment.assert_called_with('Great job!')

        assert self.issue.add_labels.called, 'Label added created'
        self.issue.add_labels.assert_called_with('No lint errors')
示例#41
0
    def test_publish_empty_comment_with_comment_status(self):
        config = build_review_config(fixer_ini, {'PULLREQUEST_STATUS': True})

        problems = Problems(changes=[])
        review = Review(self.repo, self.pr, config)

        sha = 'abc123'
        review.publish(problems, sha)

        assert self.pr.create_comment.called, 'Should create a comment'

        msg = ('Could not review pull request. '
               'It may be too large, or contain no reviewable changes.')

        self.repo.create_status.assert_called_with(self.pr.head, 'success',
                                                   msg)

        self.pr.create_comment.assert_called_with(msg)
示例#42
0
    def test_publish_checkrun__no_problems(self):
        self.repo.create_checkrun = Mock()
        config = build_review_config(fixer_ini,
                                     {'PULLREQUEST_STATUS': True})
        problems = Problems()
        run_id = 42

        review = Review(self.repo, self.pr, config)
        review.publish_checkrun(problems, run_id)

        assert self.repo.update_checkrun.called
        eq_(1, self.repo.update_checkrun.call_count)

        assert_checkrun(
            self.repo.update_checkrun.call_args,
            [],
            run_id)
        assert self.repo.create_status.called is False, 'no status required'
示例#43
0
    def test_publish_review(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 117, 'Something bad'),
            Comment(filename_1, 119, 119, 'Something bad'),
        )
        problems.add_many(errors)
        sha = 'abc123'

        review = Review(self.repo, self.pr, self.config)
        review.publish_review(problems, sha)

        assert self.pr.create_review.called
        eq_(1, self.pr.create_review.call_count)

        assert_review(self.pr.create_review.call_args, errors, sha)
示例#44
0
    def setUp(self):
        pr = Mock()
        issue = Mock()
        gh = Mock()

        gh.pull_request.return_value = pr
        gh.issue.return_value = issue

        self.gh, self.pr, self.issue = gh, pr, issue
        self.review = Review(self.gh, 2)
示例#45
0
    def test_publish_problems(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        sha = 'abc123'

        review = Review(self.repo, self.pr)
        review.publish_problems(problems, sha)

        assert self.pr.create_review_comment.called
        eq_(2, self.pr.create_review_comment.call_count)

        assert_review_comments_created(
            self.pr.create_review_comment.call_args_list, errors, sha)
示例#46
0
    def test_publish_status__has_errors__success_status(self):
        app_config = {
            'PULLREQUEST_STATUS': False,
            'OK_COMMENT': 'Great job!',
            'OK_LABEL': 'No lint errors',
            'APP_NAME': 'custom-name'
        }
        config = build_review_config(fixer_ini, app_config)
        eq_('success', config.failed_review_status(), 'config object changed')

        review = Review(self.repo, self.pr, config)
        review.publish_status(True)

        assert self.repo.create_status.called, 'Create status not called'
        self.repo.create_status.assert_called_with(
            self.pr.head, 'success',
            'Lint errors found, see pull request comments.')
        assert not self.pr.create_comment.called, 'Comment not created'
        assert not self.pr.add_label.called, 'Label added created'
示例#47
0
    def test_publish_comment_threshold_checks(self):
        fixture = load_fixture('comments_current.json')
        self.pr.review_comments.return_value = [GhIssueComment(f) for f in json.loads(fixture)]

        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        problems.set_changes([1])
        sha = 'abc123'

        review = Review(self.gh, 3)
        review.publish_summary = Mock()
        review.publish(problems, sha, 1)

        assert review.publish_summary.called, 'Should have been called.'
示例#48
0
    def test_publish_checkrun(self):
        tst_config = build_review_config(fixer_ini,
                                         {'PULLREQUEST_STATUS': True})
        problems = Problems()
        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 8, 'Something bad'),
            Comment(filename_1, 119, 9, 'Something worse'),
        )
        problems.add_many(errors)
        run_id = 42

        review = Review(self.repo, self.pr, tst_config)
        review.publish_checkrun(problems, run_id)

        assert self.repo.update_checkrun.called
        self.assertEqual(1, self.repo.update_checkrun.call_count)

        assert_checkrun(self.repo.update_checkrun.call_args, errors, run_id)
        assert self.repo.create_status.called is False, 'no status required'
示例#49
0
    def test_publish_checks_api(self):
        self.repo.create_checkrun = Mock()
        config = build_review_config(checks_ini, {'PULLREQUEST_STATUS': True})
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 8, 'Something bad'),
            Comment(filename_1, 119, 9, 'Something worse'),
        )
        problems.add_many(errors)
        sha = 'abc123'

        review = Review(self.repo, self.pr, config)
        review.publish_checkrun(problems, True, sha)

        assert self.repo.create_checkrun.called
        eq_(1, self.repo.create_checkrun.call_count)

        assert_checkrun(self.repo.create_checkrun.call_args, errors, sha)
示例#50
0
    def test_publish_pull_review_remove_ok_label(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 117, 'Something bad'),
            Comment(filename_1, 119, 119, 'Something bad'),
        )
        problems.add_many(errors)
        tst_config = build_review_config(fixer_ini, {'OK_LABEL': 'No lint'})

        review = Review(self.repo, self.pr, tst_config)
        sha = 'abc123'
        review.publish_pull_review(problems, sha)

        assert self.pr.remove_label.called, 'Label should be removed'
        assert self.pr.create_review.called, 'Review should be added'
        self.assertEqual(1, self.pr.create_review.call_count)

        self.pr.remove_label.assert_called_with(tst_config['OK_LABEL'])
        assert_review(self, self.pr.create_review.call_args, errors, sha)
示例#51
0
    def test_publish__join_issue_comments(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            IssueComment('First'),
            Comment(filename_1, 119, 119, 'Something bad'),
            IssueComment('Second'),
        )
        problems.add_many(errors)
        sha = 'abc123'

        review = Review(self.repo, self.pr, self.config)
        review.publish_review(problems, sha)

        assert self.pr.create_review.called
        eq_(1, self.pr.create_review.call_count)

        assert_review(self.pr.create_review.call_args, [errors[1]],
                      sha,
                      body='First\n\nSecond')
示例#52
0
    def test_publish_with__wait_time(self, time):
        gh = Mock()
        problems = Problems()
        review = Review(gh, 3)

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        sha = 'abc123'

        review.publish_problems(problems, sha, 1)
        assert time.sleep.called
        eq_(2, time.sleep.call_count)
        calls = time.sleep.call_args_list

        expected = call(1)
        eq_(calls[0], expected)
        eq_(calls[1], expected)
示例#53
0
    def test_filter_existing__removes_duplicates(self):
        fixture_data = load_fixture('comments_current.json')
        self.pr.review_comments.return_value = [
            GhIssueComment(f) for f in json.loads(fixture_data)
        ]
        problems = Problems()
        review = Review(self.repo, self.pr, self.config)
        filename_1 = "Routing/Filter/AssetCompressor.php"
        filename_2 = "View/Helper/AssetCompressHelper.php"

        problems.add(filename_1, 87, 'A pithy remark')
        problems.add(filename_1, 87, 'Something different')
        problems.add(filename_2, 88, 'I <3 it')
        problems.add(filename_2, 89, 'Not such a good comment')

        review.load_comments()
        review.remove_existing(problems)

        res = problems.all(filename_1)
        eq_(1, len(res))
        expected = Comment(filename_1, 87, 87,
                           'A pithy remark\nSomething different')
        eq_(res[0], expected)

        res = problems.all(filename_2)
        eq_(1, len(res))
        expected = Comment(filename_2, 88, 88, 'I <3 it')
        eq_(res[0], expected)
示例#54
0
    def test_publish_review_no_count_change(self):
        fixture = load_fixture('comments_current.json')
        self.pr.review_comments.return_value = [
            GhIssueComment(f) for f in json.loads(fixture)
        ]
        problems = Problems()

        # Match the line/positions in comments_current.json
        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 40, 40, '2. Something bad'),
            Comment(filename_1, 87, 87, '1. Something bad'),
            Comment(filename_1, 89, 89, '2. Something bad'),
        )
        problems.add_many(errors)
        problems.set_changes([1])
        sha = 'abc123'

        config = build_review_config(fixer_ini, {'SUMMARY_THRESHOLD': 1})
        review = Review(self.repo, self.pr, config)
        review.publish_summary = Mock()
        review.publish_status = Mock()

        review.publish_review(problems, sha)
        # Ensure publish_status(True) means the status=failed
        review.publish_status.assert_called_with(True)
示例#55
0
    def test_filter_existing__removes_duplicates(self, http):
        fixture_data = load_fixture('comments_current.json')
        response = Response()
        response._content = fixture_data
        http.return_value = response

        gh = Github()
        problems = Problems()
        review = Review(gh, 2)
        filename_1 = "Routing/Filter/AssetCompressor.php"
        filename_2 = "View/Helper/AssetCompressHelper.php"

        problems.add(filename_1, 87, 'A pithy remark')
        problems.add(filename_1, 87, 'Something different')
        problems.add(filename_2, 88, 'I <3 it')
        problems.add(filename_2, 89, 'Not such a good comment')

        review.load_comments()
        review.remove_existing(problems)

        res = problems.all(filename_1)
        eq_(1, len(res))
        expected = Comment(filename_1, 87, 87, 'Something different')
        eq_(res[0], expected)

        res = problems.all(filename_2)
        eq_(1, len(res))
        expected = Comment(filename_2, 88, 88, 'I <3 it')
        eq_(res[0], expected)
示例#56
0
class Processor(object):

    _repository = None
    _pull_request = None
    _target_path = None
    _changes = None
    _problems = None
    _review = None
    _config = None

    def __init__(self, repository, pull_request, target_path, config=None):
        config = config if config else {}
        self._config = config
        self._repository = repository
        self._pull_request = pull_request
        self._target_path = target_path
        self._problems = Problems(target_path)
        self._review = Review(repository, pull_request, config)

    def load_changes(self):
        log.info('Loading pull request patches from github.')
        files = self._pull_request.files()
        self._changes = DiffCollection(files)
        self._problems.set_changes(self._changes)

    def run_tools(self, review_config):
        if self._changes is None:
            raise RuntimeError('No loaded changes, cannot run tools. '
                               'Try calling load_changes first.')
        files_to_check = self._changes.get_files(
            append_base=self._target_path,
            ignore_patterns=review_config.ignore_patterns())
        commits_to_check = self._pull_request.commits()
        tools.run(review_config, self._problems, files_to_check,
                  commits_to_check, self._target_path)

    def publish(self):
        self._problems.limit_to_changes()
        self._review.publish(self._problems, self._pull_request.head,
                             self._config.get('SUMMARY_THRESHOLD'))
示例#57
0
    def test_publish_review_comment_threshold_checks(self):
        fixture = load_fixture('comments_current.json')
        self.pr.review_comments.return_value = [
            GhIssueComment(f) for f in json.loads(fixture)]

        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 117, 'Something bad'),
            Comment(filename_1, 119, 119, 'Something bad'),
        )
        problems.add_many(errors)
        problems.set_changes([1])
        sha = 'abc123'

        config = build_review_config(fixer_ini, {'SUMMARY_THRESHOLD': 1})
        review = Review(self.repo, self.pr, config)
        review.publish_summary = Mock()
        review.publish_review(problems, sha)

        assert review.publish_summary.called, 'Should have been called.'
示例#58
0
    def test_publish_checkrun__has_errors_force_success_status(self):
        self.repo.create_checkrun = Mock()
        config = build_review_config(fixer_ini, {'PULLREQUEST_STATUS': False})
        eq_('success', config.failed_review_status(), 'config object changed')

        review = Review(self.repo, self.pr, config)

        problems = Problems()
        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            Comment(filename_1, 117, 8, 'Something bad'),
            Comment(filename_1, 119, 9, 'Something worse'),
        )
        problems.add_many(errors)
        run_id = 42
        review.publish_checkrun(problems, run_id)

        assert self.repo.create_status.called is False, 'no status required'

        checkrun = self.repo.update_checkrun.call_args[0][1]
        eq_('success', checkrun['conclusion'])
        assert len(checkrun['output']['annotations']) > 0
示例#59
0
    def test_publish_summary(self):
        problems = Problems()

        filename_1 = 'Console/Command/Task/AssetBuildTask.php'
        errors = (
            (filename_1, 117, 'Something bad'),
            (filename_1, 119, 'Something bad'),
        )
        problems.add_many(errors)
        problems.set_changes([1])

        review = Review(self.repo, self.pr)
        review.publish_summary(problems)

        assert self.pr.create_comment.called
        eq_(1, self.pr.create_comment.call_count)

        msg = """There are 2 errors:

* Console/Command/Task/AssetBuildTask.php, line 117 - Something bad
* Console/Command/Task/AssetBuildTask.php, line 119 - Something bad
"""
        self.pr.create_comment.assert_called_with(msg)