def test_show_pull_request(self): test_pr_id = 1 test_project_id = 20 test_repository_id = 25 #big setup because this object is passed around pr_to_return = GitPullRequest() pr_to_return.pull_request_id = test_pr_id pr_to_return.repository = GitRepository() pr_to_return.repository.id = test_repository_id pr_to_return.repository.project = TeamProjectReference() pr_to_return.repository.project.id = test_project_id self.mock_get_PR_byId.return_value = pr_to_return response = show_pull_request( id=test_pr_id, open=False, organization=self._TEST_DEVOPS_ORGANIZATION) #assert self.mock_get_PR_byId.assert_called_once_with(test_pr_id) self.mock_get_PR.assert_called_once_with( project=test_project_id, repository_id=test_repository_id, pull_request_id=test_pr_id, include_commits=False, include_work_item_refs=True)
def test_create_pull_request_with_auto_complete(self): test_pr_id = 1 merge_complete_message = 'merge complete message' #big setup because this object is passed around in create with auto complete flow pr_to_return = GitPullRequest() pr_to_return.pull_request_id = test_pr_id pr_to_return.repository = GitRepository() pr_to_return.repository.project = TeamProjectReference() self.mock_create_PR.return_value = pr_to_return self.mock_resolve_identity.return_value = 'resolved identity' response = create_pull_request( project=self._TEST_PROJECT_NAME, repository=self._TEST_REPOSITORY_NAME, source_branch=self._TEST_SOURCE_BRANCH, target_branch=self._TEST_TARGET_BRANCH, title=self._TEST_PR_TITLE, description=self._TEST_PR_DESCRIPTION, organization=self._TEST_DEVOPS_ORGANIZATION, auto_complete=True, merge_commit_message=merge_complete_message) # assert self.mock_create_PR.assert_called_once() self.mock_update_PR.assert_called_once() pr_id_from_udpate_call = self.mock_update_PR.call_args_list[0][1][ 'pull_request_id'] assert pr_id_from_udpate_call == test_pr_id update_object_from_update_call = self.mock_update_PR.call_args_list[0][ 1]['git_pull_request_to_update'] assert update_object_from_update_call.completion_options.merge_commit_message == merge_complete_message
def _update_pull_request_status(pull_request_id, new_status, organization=None, detect=None): organization = resolve_instance(detect=detect, organization=organization) client = get_git_client(organization) existing_pr = client.get_pull_request_by_id(pull_request_id) pr = GitPullRequest(status=new_status) if new_status == 'completed': pr.last_merge_source_commit = existing_pr.last_merge_source_commit pr = client.update_pull_request(git_pull_request_to_update=pr, project=existing_pr.repository.project.name, repository_id=existing_pr.repository.name, pull_request_id=pull_request_id) return pr
def test_list_pr_policies(self): test_pr_id = 1 test_project_id = 20 test_repository_id = 25 #big setup because this object is passed around pr_to_return = GitPullRequest() pr_to_return.pull_request_id = test_pr_id pr_to_return.repository = GitRepository() pr_to_return.repository.id = test_repository_id pr_to_return.repository.project = TeamProjectReference() pr_to_return.repository.project.id = test_project_id self.mock_get_PR_byId.return_value = pr_to_return response = list_pr_policies( id=1, organization=self._TEST_DEVOPS_ORGANIZATION) #assert self.mock_get_PR_byId.assert_called_once() self.mock_get_policy_evaluation.assert_called_once()
def update_pull_request( id, title=None, description=None, auto_complete=None, # pylint: disable=redefined-builtin squash=None, delete_source_branch=None, bypass_policy=None, draft=None, bypass_policy_reason=None, merge_commit_message=None, organization=None, detect=None, transition_work_items=None): """Update a pull request. :param id: ID of the pull request. :type id: int :param title: New title for the pull request. :type title: str :param description: New description for the pull request. Can include markdown. Each value sent to this arg will be a new line. For example: --description "First Line" "Second Line" :type description: list of str :param auto_complete: Set the pull request to complete automatically when all policies have passed and the source branch can be merged into the target branch. :type auto_complete: bool :param squash: Squash the commits in the source branch when merging into the target branch. :type squash: bool :param delete_source_branch: Delete the source branch after the pull request has been completed and merged into the target branch. :type delete_source_branch: bool :param bypass_policy: Bypass required policies (if any) and completes the pull request once it can be merged. :type bypass_policy: bool :param bypass_policy_reason: Reason for bypassing the required policies. :type bypass_policy_reason: str :param draft: Publish the PR or convert to draft mode. :type draft: bool :param merge_commit_message: Message displayed when commits are merged. :type merge_commit_message: str :param transition_work_items: Transition any work items linked to the pull request into the next logical state. (e.g. Active -> Resolved) :type transition_work_items: bool :rtype: :class:`GitPullRequest <v5_0.git.models.GitPullRequest>` """ organization = resolve_instance(detect=detect, organization=organization) client = get_git_client(organization) existing_pr = client.get_pull_request_by_id(id) if description is not None: multi_line_description = '\n'.join(description) else: multi_line_description = None pr = GitPullRequest(title=title, description=multi_line_description) if (bypass_policy is not None or # pylint: disable=too-many-boolean-expressions bypass_policy_reason is not None or squash is not None or merge_commit_message is not None or delete_source_branch is not None or transition_work_items is not None): completion_options = existing_pr.completion_options if completion_options is None: completion_options = GitPullRequestCompletionOptions() if bypass_policy is not None: completion_options.bypass_policy = bypass_policy if bypass_policy_reason is not None: completion_options.bypass_reason = bypass_policy_reason if delete_source_branch is not None: completion_options.delete_source_branch = delete_source_branch if squash is not None: completion_options.squash_merge = squash if merge_commit_message is not None: completion_options.merge_commit_message = merge_commit_message if transition_work_items is not None: completion_options.transition_work_items = transition_work_items pr.completion_options = completion_options if auto_complete is not None: if auto_complete: pr.auto_complete_set_by = IdentityRef( id=resolve_identity_as_id(ME, organization)) else: pr.auto_complete_set_by = IdentityRef(id=EMPTY_UUID) if draft is not None: pr.is_draft = draft pr = client.update_pull_request( git_pull_request_to_update=pr, project=existing_pr.repository.project.name, repository_id=existing_pr.repository.name, pull_request_id=id) return pr
def create_pull_request(project=None, repository=None, source_branch=None, target_branch=None, title=None, description=None, auto_complete=False, squash=False, delete_source_branch=False, bypass_policy=False, bypass_policy_reason=None, merge_commit_message=None, reviewers=None, work_items=None, draft=None, open=False, organization=None, detect=None, transition_work_items=False): # pylint: disable=redefined-builtin """Create a pull request. :param project: Name or ID of the team project. :type project: str :param repository: Name or ID of the repository to create the pull request in. :type repository: str :param source_branch: Name of the source branch. Example: "dev". :type source_branch: str :param target_branch: Name of the target branch. If not specified, defaults to the default branch of the target repository. :type target_branch: str :param title: Title for the new pull request. :type title: str :param draft: Use this flag to create the pull request in draft/work in progress mode. :type draft: bool :param description: Description for the new pull request. Can include markdown. Each value sent to this arg will be a new line. For example: --description "First Line" "Second Line" :type description: list of str :param auto_complete: Set the pull request to complete automatically when all policies have passed and the source branch can be merged into the target branch. :type auto_complete: bool :param squash: Squash the commits in the source branch when merging into the target branch. :type squash: bool :param delete_source_branch: Delete the source branch after the pull request has been completed and merged into the target branch. :type delete_source_branch: bool :param bypass_policy: Bypass required policies (if any) and completes the pull request once it can be merged. :type bypass_policy: bool :param bypass_policy_reason: Reason for bypassing the required policies. :type bypass_policy_reason: str :param merge_commit_message: Message displayed when commits are merged. :type merge_commit_message: str :param reviewers: Additional users or groups to include as reviewers on the new pull request. Space separated. :type reviewers: list of str :param work_items: IDs of the work items to link to the new pull request. Space separated. :type work_items: list of str :param open: Open the pull request in your web browser. :type open: bool :param transition_work_items: Transition any work items linked to the pull request into the next logical state. (e.g. Active -> Resolved) :type transition_work_items: bool :rtype: :class:`GitPullRequest <v5_0.git.models.GitPullRequest>` """ organization, project, repository = resolve_instance_project_and_repo( detect=detect, organization=organization, project=project, repo=repository) source_branch, target_branch = _get_branches_for_pull_request( organization, project, repository, source_branch, target_branch, detect) client = get_git_client(organization) multi_line_description = None if description is not None: multi_line_description = '\n'.join(description) pr = GitPullRequest(description=multi_line_description, source_ref_name=source_branch, target_ref_name=target_branch) if draft is not None: pr.is_draft = draft if title is not None: pr.title = title else: pr.title = 'Merge ' + source_branch + ' to ' + target_branch pr.source_ref_name = resolve_git_ref_heads(source_branch) pr.target_ref_name = resolve_git_ref_heads(target_branch) if pr.source_ref_name == pr.target_ref_name: raise CLIError( 'The source branch, "{}", can not be the same as the target branch.' .format(pr.source_ref_name)) pr.reviewers = _resolve_reviewers_as_refs(reviewers, organization) if work_items is not None and work_items: resolved_work_items = [] for work_item in work_items: resolved_work_items.append(ResourceRef(id=work_item)) pr.work_item_refs = resolved_work_items pr = client.create_pull_request(git_pull_request_to_create=pr, project=project, repository_id=repository) title_from_commit = None if title is None: # if title wasn't specified and only one commit, we will set the PR title to the comment of that commit commits = client.get_pull_request_commits( repository_id=repository, pull_request_id=pr.pull_request_id, project=project) if len(commits) == 1: title_from_commit = commits[0].comment set_completion_options = (bypass_policy or bypass_policy_reason is not None or squash or merge_commit_message is not None or delete_source_branch or transition_work_items) if auto_complete or set_completion_options or title_from_commit is not None: pr_for_update = GitPullRequest() if auto_complete: # auto-complete will not get set on create, so a subsequent update is required. pr_for_update.auto_complete_set_by = IdentityRef( id=resolve_identity_as_id(ME, organization)) if set_completion_options: completion_options = GitPullRequestCompletionOptions() completion_options.bypass_policy = bypass_policy completion_options.bypass_reason = bypass_policy_reason completion_options.delete_source_branch = delete_source_branch completion_options.squash_merge = squash completion_options.merge_commit_message = merge_commit_message completion_options.transition_work_items = transition_work_items pr_for_update.completion_options = completion_options if title_from_commit is not None: pr_for_update.title = title_from_commit pr = client.update_pull_request( git_pull_request_to_update=pr_for_update, project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pr.pull_request_id) if open: _open_pull_request(pr, organization) return pr