Пример #1
0
 def test_handles_request_becoming_wip_after_push(self, unused_time_sleep):
     api, mocklab = self.api, self.mocklab
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/54/merge',
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='now_is_wip',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, work_in_progress=True),
         from_state='now_is_wip',
     )
     message = 'The request was marked as WIP as I was processing it (maybe a WIP commit?)'
     with patch('marge.job.update_from_target_branch_and_push',
                side_effect=mocklab.push_updated):
         with mocklab.expected_failure(message):
             job = self.make_job()
             job.execute()
     assert api.state == 'now_is_wip'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #2
0
 def test_assumes_unresolved_discussions_on_merge_refusal(self, mocks):
     mocklab, api, job = mocks
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/{iid}/merge'.format(
                 iid=mocklab.merge_request_info['iid']),
             dict(sha=rewritten_sha,
                  remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='unresolved_discussions',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info),
         from_state='unresolved_discussions',
     )
     message = (
         "Gitlab refused to merge this request and I don't know why! "
         "Maybe you have unresolved discussions?")
     with mocklab.expected_failure(message):
         with patch.dict(
                 mocklab.project_info,
                 only_allow_merge_if_all_discussions_are_resolved=True):
             job.execute()
     assert api.state == 'unresolved_discussions'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #3
0
 def test_handles_races_for_merging(self, unused_time_sleep):
     api, mocklab = self.api, self.mocklab
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/54/merge',
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.NotFound(404,
                                   {'message': '404 Branch Not Found'})),
         from_state='passed',
         to_state='someone_else_merged',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, state='merged'),
         from_state='someone_else_merged',
     )
     with patch('marge.job.update_from_target_branch_and_push',
                side_effect=mocklab.push_updated):
         job = self.make_job()
         job.execute()
     assert api.state == 'someone_else_merged'
     assert api.notes == []
Пример #4
0
 def test_discovers_if_someone_closed_the_merge_request(self, mocks):
     mocklab, api, job = mocks
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/{iid}/merge'.format(
                 iid=mocklab.merge_request_info['iid']),
             dict(sha=rewritten_sha,
                  remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='oops_someone_closed_it',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, state='closed'),
         from_state='oops_someone_closed_it',
     )
     message = 'Someone closed the merge request while I was attempting to merge it.'
     with mocklab.expected_failure(message):
         job.execute()
     assert api.state == 'oops_someone_closed_it'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #5
0
 def test_handles_request_becoming_wip_after_push(self, mocks):
     mocklab, api, job = mocks
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/{iid}/merge'.format(
                 iid=mocklab.merge_request_info['iid']),
             dict(sha=rewritten_sha,
                  remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='now_is_wip',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, work_in_progress=True),
         from_state='now_is_wip',
     )
     message = 'The request was marked as WIP as I was processing it (maybe a WIP commit?)'
     with mocklab.expected_failure(message):
         job.execute()
     assert api.state == 'now_is_wip'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #6
0
 def test_guesses_git_hook_error_on_merge_refusal(self, mocks):
     mocklab, api, job = mocks
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/{iid}/merge'.format(
                 iid=mocklab.merge_request_info['iid']),
             dict(sha=rewritten_sha,
                  remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='rejected_by_git_hook',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, state='reopened'),
         from_state='rejected_by_git_hook',
     )
     message = (
         'GitLab refused to merge this branch. I suspect that a Push Rule or a git-hook '
         'is rejecting my commits; maybe my email needs to be white-listed?'
     )
     with mocklab.expected_failure(message):
         job.execute()
     assert api.state == 'rejected_by_git_hook'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #7
0
 def test_handles_races_for_merging(self, api, mocklab):
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/{iid}/merge'.format(
                 iid=mocklab.merge_request_info['iid']),
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.NotFound(404,
                                   {'message': '404 Branch Not Found'})),
         from_state='passed',
         to_state='someone_else_merged',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, state='merged'),
         from_state='someone_else_merged',
     )
     with mocklab.branch_update():
         job = self.make_job(api, mocklab)
         job.execute()
     assert api.state == 'someone_else_merged'
     assert api.notes == []
Пример #8
0
 def test_tells_explicitly_that_gitlab_refused_to_merge(
         self, unused_time_sleep):
     api, mocklab = self.api, self.mocklab
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/54/merge',
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='rejected_for_misterious_reasons',
     )
     message = "Gitlab refused to merge this request and I don't know why!"
     with patch('marge.job.update_from_target_branch_and_push',
                side_effect=mocklab.push_updated):
         with mocklab.expected_failure(message):
             job = self.make_job()
             job.execute()
     assert api.state == 'rejected_for_misterious_reasons'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #9
0
    def test_fails_if_branch_is_protected(self, mocks_factory, fusion):
        def reject_push(*_args, **_kwargs):
            raise marge.git.GitError()

        mocklab, api, job = mocks_factory(on_push=reject_push)
        api.add_transition(
            GET(
                '/projects/{source_project_id}/repository/branches/useless_new_feature'.format(
                    source_project_id=mocklab.merge_request_info['source_project_id'],
                ),
            ),
            Ok(_branch('useless_new_feature', protected=True)),
            from_state='initial', to_state='protected'
        )

        if fusion is Fusion.gitlab_rebase:
            api.add_transition(
                PUT(
                    '/projects/{project_id}/merge_requests/{iid}/rebase'.format(
                        project_id=mocklab.merge_request_info['project_id'],
                        iid=mocklab.merge_request_info['iid'],
                    ),
                ),
                Error(marge.gitlab.MethodNotAllowed(405, {'message': '405 Method Not Allowed'})),
                from_state='initial',
            )

        with mocklab.expected_failure("Sorry, I can't modify protected branches!"):
            job.execute()

        assert api.state == 'protected'
Пример #10
0
 def test_discovers_if_someone_closed_the_merge_request(
         self, unused_time_sleep):
     api, mocklab = self.api, self.mocklab
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/54/merge',
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='oops_someone_closed_it',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, state='closed'),
         from_state='oops_someone_closed_it',
     )
     message = 'Someone closed the merge request while I was attempting to merge it.'
     with patch('marge.job.update_from_target_branch_and_push',
                side_effect=mocklab.push_updated):
         with mocklab.expected_failure(message):
             job = self.make_job()
             job.execute()
     assert api.state == 'oops_someone_closed_it'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #11
0
 def test_guesses_git_hook_error_on_merge_refusal(self, unused_time_sleep):
     api, mocklab = self.api, self.mocklab
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/54/merge',
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Error(
             marge.gitlab.MethodNotAllowed(
                 405, {'message': '405 Method Not Allowed'})),
         from_state='passed',
         to_state='rejected_by_git_hook',
     )
     api.add_merge_request(
         dict(mocklab.merge_request_info, state='reopened'),
         from_state='rejected_by_git_hook',
     )
     message = (
         'GitLab refused to merge this branch. I suspect that a Push Rule or a git-hook '
         'is rejecting my commits; maybe my email needs to be white-listed?'
     )
     with patch('marge.job.update_from_target_branch_and_push',
                side_effect=mocklab.push_updated):
         with mocklab.expected_failure(message):
             job = self.make_job()
             job.execute()
     assert api.state == 'rejected_by_git_hook'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #12
0
    def test_succeeds_second_time_if_master_moved(self, unused_time_sleep):
        api, mocklab = self.api, self.mocklab
        moved_master_sha = 'fafafa'
        first_rewritten_sha = '1o1'
        api.add_pipelines(
            mocklab.project_info['id'],
            _pipeline(sha1=first_rewritten_sha, status='success'),
            from_state=['pushed_but_master_moved', 'merged_rejected'],
        )
        api.add_transition(
            PUT(
                '/projects/1234/merge_requests/54/merge',
                dict(
                    sha=first_rewritten_sha,
                    should_remove_source_branch=True,
                    merge_when_pipeline_succeeds=True,
                ),
            ),
            Error(marge.gitlab.NotAcceptable()),
            from_state='pushed_but_master_moved',
            to_state='merge_rejected',
        )
        api.add_transition(
            GET('/projects/1234/repository/branches/useless_new_feature'),
            Ok({
                'commit':
                _commit(commit_id=first_rewritten_sha, status='success')
            }),
            from_state='pushed_but_master_moved')
        api.add_transition(GET('/projects/1234/repository/branches/master'),
                           Ok({
                               'commit':
                               _commit(commit_id=moved_master_sha,
                                       status='success')
                           }),
                           from_state='merge_rejected')

        def push_effects():
            assert api.state == 'initial'
            api.state = 'pushed_but_master_moved'
            yield mocklab.initial_master_sha, 'f00ba4', first_rewritten_sha

            assert api.state == 'merge_rejected'
            api.state = 'pushed'
            yield moved_master_sha, 'deadbeef', mocklab.rewritten_sha

        with patch('marge.job.update_from_target_branch_and_push',
                   side_effect=push_effects()):
            job = self.make_job(
                marge.job.MergeJobOptions.default(add_tested=True,
                                                  add_reviewers=False))
            job.execute()

        assert api.state == 'merged'
        assert api.notes == [
            "My job would be easier if people didn't jump the queue and push directly... *sigh*",
        ]
Пример #13
0
 def __init__(self, gitlab_url=None, fork=False, merge_request_options=None):
     super().__init__(gitlab_url, fork=fork, merge_request_options=merge_request_options)
     api = self.api
     self.rewritten_sha = rewritten_sha = 'af7a'
     api.add_pipelines(
         self.merge_request_info['source_project_id'],
         _pipeline(sha1=rewritten_sha, status='running', ref=self.merge_request_info['source_branch']),
         from_state='pushed', to_state='passed',
     )
     api.add_pipelines(
         self.merge_request_info['source_project_id'],
         _pipeline(sha1=rewritten_sha, status='success', ref=self.merge_request_info['source_branch']),
         from_state=['passed', 'merged'],
     )
     source_project_id = self.merge_request_info['source_project_id']
     api.add_transition(
         GET(
             '/projects/{}/repository/branches/{}'.format(
                 source_project_id, self.merge_request_info['source_branch'],
             ),
         ),
         Ok({'commit': _commit(commit_id=rewritten_sha, status='running')}),
         from_state='pushed',
     )
     api.add_transition(
         GET(
             '/projects/{}/repository/branches/{}'.format(
                 source_project_id, self.merge_request_info['source_branch'],
             ),
         ),
         Ok({'commit': _commit(commit_id=rewritten_sha, status='success')}),
         from_state='passed'
     )
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/{iid}/merge'.format(iid=self.merge_request_info['iid']),
             dict(sha=rewritten_sha, should_remove_source_branch=True, merge_when_pipeline_succeeds=True),
         ),
         Ok({}),
         from_state=['passed', 'skipped'], to_state='merged',
     )
     api.add_merge_request(dict(self.merge_request_info, state='merged'), from_state='merged')
     api.add_transition(
         GET('/projects/1234/repository/branches/{}'.format(self.merge_request_info['target_branch'])),
         Ok({'commit': {'id': self.rewritten_sha}}),
         from_state='merged'
     )
     api.expected_note(
         self.merge_request_info,
         "My job would be easier if people didn't jump the queue and push directly... *sigh*",
         from_state=['pushed_but_master_moved', 'merge_rejected'],
     )
     api.expected_note(
         self.merge_request_info,
         "I'm broken on the inside, please somebody fix me... :cry:"
     )
Пример #14
0
 def test_accept_merge_when_pipeline_succeeds(self):
     self._load(dict(INFO, sha='badc0de'))
     self.merge_request.accept(merge_when_pipeline_succeeds=False)
     self.api.call.assert_called_once_with(
         PUT(
             '/projects/1234/merge_requests/54/merge',
             dict(
                 merge_when_pipeline_succeeds=False,
                 should_remove_source_branch=False,
                 sha='badc0de',
             )))
Пример #15
0
    def test_accept(self):
        self._load(dict(INFO, sha='badc0de'))

        for boolean in (True, False):
            self.merge_request.accept(remove_branch=boolean)
            self.api.call.assert_called_once_with(
                PUT('/projects/1234/merge_requests/54/merge',
                    dict(
                        should_remove_source_branch=boolean,
                        sha='badc0de',
                    )))
            self.api.call.reset_mock()

        self.merge_request.accept(sha='g00dc0de')
        self.api.call.assert_called_once_with(
            PUT('/projects/1234/merge_requests/54/merge',
                dict(
                    should_remove_source_branch=False,
                    sha='g00dc0de',
                )))
Пример #16
0
 def __init__(self, gitlab_url=None):
     super().__init__(gitlab_url)
     api = self.api
     self.rewritten_sha = rewritten_sha = 'af7a'
     api.add_pipelines(
         self.project_info['id'],
         _pipeline(sha1=rewritten_sha, status='running'),
         from_state='pushed',
         to_state='passed',
     )
     api.add_pipelines(
         self.project_info['id'],
         _pipeline(sha1=rewritten_sha, status='success'),
         from_state=['passed', 'merged'],
     )
     api.add_transition(
         GET('/projects/1234/repository/branches/useless_new_feature'),
         Ok({'commit': _commit(commit_id=rewritten_sha, status='running')}),
         from_state='pushed',
     )
     api.add_transition(
         GET('/projects/1234/repository/branches/useless_new_feature'),
         Ok({'commit': _commit(commit_id=rewritten_sha, status='success')}),
         from_state='passed')
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/54/merge',
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=True),
         ),
         Ok({}),
         from_state='passed',
         to_state='merged',
     )
     api.add_merge_request(dict(self.merge_request_info, state='merged'),
                           from_state='merged')
     api.add_transition(GET('/projects/1234/repository/branches/master'),
                        Ok({'commit': {
                            'id': self.rewritten_sha
                        }}),
                        from_state='merged')
     api.expected_note(
         self.merge_request_info,
         "My job would be easier if people didn't jump the queue and push directly... *sigh*",
         from_state=['pushed_but_master_moved', 'merge_rejected'],
     )
     api.expected_note(
         self.merge_request_info,
         "I'm broken on the inside, please somebody fix me... :cry:")
Пример #17
0
 def test_tells_explicitly_that_gitlab_refused_to_merge(self, mocks):
     mocklab, api, job = mocks
     rewritten_sha = mocklab.rewritten_sha
     api.add_transition(
         PUT(
             '/projects/1234/merge_requests/{iid}/merge'.format(iid=mocklab.merge_request_info['iid']),
             dict(sha=rewritten_sha, should_remove_source_branch=True),
         ),
         Error(marge.gitlab.MethodNotAllowed(405, {'message': '405 Method Not Allowed'})),
         from_state='passed', to_state='rejected_for_mysterious_reasons',
     )
     message = "Gitlab refused to merge this request and I don't know why!"
     with mocklab.expected_failure(message):
         job.execute()
     assert api.state == 'rejected_for_mysterious_reasons'
     assert api.notes == ["I couldn't merge this branch: %s" % message]
Пример #18
0
    def expected_failure(self, message):
        author_assigned = False
        def assign_to_author():
            nonlocal author_assigned
            author_assigned = True

        self.api.add_transition(
            PUT('/projects/1234/merge_requests/54', args={'assignee_id': self.author_id}),
            assign_to_author,
        )
        error_note = "I couldn't merge this branch: %s" % message
        self.api.expected_note(self.merge_request_info, error_note)

        yield

        assert author_assigned
        assert error_note in self.api.notes
Пример #19
0
    def test_rebase_was_not_in_progress_error(self):
        expected = [
            (
                GET('/projects/1234/merge_requests/54'
                    ),  # refetch_info -> not in progress
                INFO),
            (PUT('/projects/1234/merge_requests/54/rebase'), True),
            (
                GET('/projects/1234/merge_requests/54'
                    ),  # refetch_info -> BOOM
                dict(INFO,
                     rebase_in_progress=False,
                     merge_error="Rebase failed. Please rebase locally")),
        ]

        self.api.call = Mock(side_effect=[resp for (req, resp) in expected])

        with pytest.raises(MergeRequestRebaseFailed):
            self.merge_request.rebase()
        self.api.call.assert_has_calls([call(req) for (req, resp) in expected])
Пример #20
0
    def test_rebase_was_not_in_progress_no_error(self):
        expected = [
            (
                GET('/projects/1234/merge_requests/54'
                    ),  # refetch_info -> not in progress
                INFO),
            (PUT('/projects/1234/merge_requests/54/rebase'), True),
            (
                GET('/projects/1234/merge_requests/54'
                    ),  # refetch_info -> in progress
                dict(INFO, rebase_in_progress=True)),
            (
                GET('/projects/1234/merge_requests/54'
                    ),  # refetch_info -> succeeded
                dict(INFO, rebase_in_progress=False)),
        ]

        self.api.call = Mock(side_effect=[resp for (req, resp) in expected])
        self.merge_request.rebase()
        self.api.call.assert_has_calls([call(req) for (req, resp) in expected])
Пример #21
0
 def test_calculates_merge_when_pipeline_succeeds_correctly(
         self, mocks, only_allow_merge_if_pipeline_succeeds):
     mocklab, api, job = mocks
     rewritten_sha = mocklab.rewritten_sha
     project_info = dict(TEST_PROJECT_INFO)
     project_info[
         "only_allow_merge_if_pipeline_succeeds"] = only_allow_merge_if_pipeline_succeeds
     api.add_project(project_info)
     api.add_transition(
         PUT(
             '/projects/{pid}/merge_requests/{iid}/merge'.format(
                 iid=mocklab.merge_request_info['iid'],
                 pid=project_info["id"]),
             dict(sha=rewritten_sha,
                  should_remove_source_branch=True,
                  merge_when_pipeline_succeeds=
                  only_allow_merge_if_pipeline_succeeds),
         ),
         Ok(True),
         to_state='merged',
     )
     job.execute()
     assert api.state == 'merged'
Пример #22
0
 def test_unassign(self):
     self.merge_request.unassign()
     self.api.call.assert_called_once_with(
         PUT('/projects/1234/merge_requests/54', {'assignee_id': 0}))
Пример #23
0
 def test_assign(self):
     self.merge_request.assign_to(42)
     self.api.call.assert_called_once_with(
         PUT('/projects/1234/merge_requests/54', {'assignee_id': 42}))
Пример #24
0
    def test_second_time_if_master_moved(self, mocks_factory, fusion, update_sha, rewrite_sha):
        initial_master_sha = 'eaeaea9e9e'
        moved_master_sha = 'fafafa'
        first_rewritten_sha = rewrite_sha(update_sha(INITIAL_MR_SHA, initial_master_sha))
        second_rewritten_sha = rewrite_sha(update_sha(first_rewritten_sha, moved_master_sha))

        # pylint: disable=unused-argument
        def push_effects(remote_url, remote_branch, old_sha, new_sha):
            nonlocal mocklab, target_branch, remote_target_repo

            if api.state == 'initial':
                assert old_sha == INITIAL_MR_SHA
                assert new_sha == first_rewritten_sha
                api.state = 'pushed_but_master_moved'
                remote_target_repo.set_ref(target_branch, moved_master_sha)
            elif api.state == 'merge_rejected':
                assert new_sha == second_rewritten_sha
                api.state = 'pushed'

        mocklab, api, job = mocks_factory(
            initial_master_sha=initial_master_sha,
            rewritten_sha=second_rewritten_sha,
            on_push=push_effects,
        )

        source_project_info = mocklab.forked_project_info or mocklab.project_info
        target_project_info = mocklab.project_info

        source_project_url = source_project_info['ssh_url_to_repo']
        target_project_url = target_project_info['ssh_url_to_repo']

        source_branch = mocklab.merge_request_info['source_branch']
        target_branch = mocklab.merge_request_info['target_branch']

        remote_source_repo = job.repo.mock_impl.remote_repos[source_project_url]
        remote_target_repo = job.repo.mock_impl.remote_repos[target_project_url]

        api.add_merge_request(
            dict(
                mocklab.merge_request_info,
                sha=first_rewritten_sha,
            ),
            from_state=['pushed_but_master_moved', 'merge_rejected'],
        )
        api.add_pipelines(
            mocklab.merge_request_info['source_project_id'],
            _pipeline(sha1=first_rewritten_sha, status='success'),
            from_state=['pushed_but_master_moved', 'merge_rejected'],
        )
        api.add_transition(
            PUT(
                '/projects/1234/merge_requests/{iid}/merge'.format(iid=mocklab.merge_request_info['iid']),
                dict(
                    sha=first_rewritten_sha,
                    should_remove_source_branch=True,
                ),
            ),
            Error(marge.gitlab.NotAcceptable()),
            from_state='pushed_but_master_moved', to_state='merge_rejected',
        )
        api.add_transition(
            GET(
                '/projects/{source_project_id}/repository/branches/useless_new_feature'.format(
                    source_project_id=mocklab.merge_request_info['source_project_id'],
                ),
            ),
            Ok({'commit': _commit(commit_id=first_rewritten_sha, status='success')}),
            from_state='pushed_but_master_moved'
        )
        api.add_transition(
            GET('/projects/1234/repository/branches/master'),
            Ok({'commit': _commit(commit_id=moved_master_sha, status='success')}),
            from_state='merge_rejected'
        )
        if fusion is Fusion.gitlab_rebase:
            rebase_url = '/projects/{project_id}/merge_requests/{iid}/rebase'.format(
                project_id=mocklab.merge_request_info['project_id'],
                iid=mocklab.merge_request_info['iid'],
            )

            api.add_transition(
                PUT(rebase_url), Ok(True),
                from_state='initial', to_state='pushed_but_master_moved',
                side_effect=lambda: (
                    remote_source_repo.set_ref(source_branch, first_rewritten_sha),
                    remote_target_repo.set_ref(target_branch, moved_master_sha)
                )
            )
            api.add_transition(
                PUT(rebase_url), Ok(True),
                from_state='merge_rejected', to_state='rebase-in-progress',
                side_effect=lambda: remote_source_repo.set_ref(source_branch, second_rewritten_sha)
            )

        job.execute()
        assert api.state == 'merged'
        assert api.notes == [
            "My job would be easier if people didn't jump the queue and push directly... *sigh*",
        ]
Пример #25
0
    def __init__(self, gitlab_url=None):
        self.gitlab_url = gitlab_url = gitlab_url or 'http://git.example.com'
        self.api = api = ApiMock(gitlab_url=gitlab_url,
                                 auth_token='no-token',
                                 initial_state='initial')

        api.add_transition(GET('/version'), Ok({'version': '9.2.3-ee'}))

        self.user_info = dict(test_user.INFO)
        self.user_id = self.user_info['id']
        api.add_user(self.user_info, is_current=True)

        self.project_info = dict(test_project.INFO)
        api.add_project(self.project_info)

        self.commit_info = dict(test_commit.INFO)
        api.add_commit(self.project_info['id'], self.commit_info)

        self.author_id = 234234
        self.merge_request_info = {
            'id': 53,
            'iid': 54,
            'title': 'a title',
            'project_id': 1234,
            'author': {
                'id': self.author_id
            },
            'assignee': {
                'id': self.user_id
            },
            'approved_by': [],
            'state': 'opened',
            'sha': self.commit_info['id'],
            'source_project_id': 1234,
            'target_project_id': 1234,
            'source_branch': 'useless_new_feature',
            'target_branch': 'master',
            'work_in_progress': False,
            'web_url':
            'http://git.example.com/group/project/merge_request/666',
        }
        api.add_merge_request(self.merge_request_info)

        self.initial_master_sha = '505e'
        self.rewritten_sha = rewritten_sha = 'af7a'
        api.add_pipelines(
            self.project_info['id'],
            _pipeline(sha1=rewritten_sha, status='running'),
            from_state='pushed',
            to_state='passed',
        )
        api.add_pipelines(
            self.project_info['id'],
            _pipeline(sha1=rewritten_sha, status='success'),
            from_state=['passed', 'merged'],
        )
        api.add_transition(
            GET('/projects/1234/repository/branches/useless_new_feature'),
            Ok({'commit': _commit(commit_id=rewritten_sha, status='running')}),
            from_state='pushed',
        )
        api.add_transition(
            GET('/projects/1234/repository/branches/useless_new_feature'),
            Ok({'commit': _commit(commit_id=rewritten_sha, status='success')}),
            from_state='passed')
        api.add_transition(
            PUT(
                '/projects/1234/merge_requests/54/merge',
                dict(sha=rewritten_sha,
                     should_remove_source_branch=True,
                     merge_when_pipeline_succeeds=True),
            ),
            Ok({}),
            from_state='passed',
            to_state='merged',
        )
        api.add_merge_request(dict(self.merge_request_info, state='merged'),
                              from_state='merged')
        self.approvals_info = dict(
            test_approvals.INFO,
            id=self.merge_request_info['id'],
            iid=self.merge_request_info['iid'],
            project_id=self.merge_request_info['project_id'],
            approvals_left=0,
        )
        api.add_approvals(self.approvals_info)
        api.add_transition(
            GET('/projects/1234/repository/branches/master'),
            Ok({'commit': {
                'id': self.initial_master_sha
            }}),
        )
        api.add_transition(GET('/projects/1234/repository/branches/master'),
                           Ok({'commit': {
                               'id': self.rewritten_sha
                           }}),
                           from_state='merged')
        api.expected_note(
            self.merge_request_info,
            "My job would be easier if people didn't jump the queue and push directly... *sigh*",
            from_state=['pushed_but_master_moved', 'merge_rejected'],
        )
        api.expected_note(
            self.merge_request_info,
            "I'm broken on the inside, please somebody fix me... :cry:")