def test_create_pull_request(self):

        test_pr_id = 1

        # set return values
        self.mock_validate_token.return_value = True
        self.mock_create_PR.return_value.id = test_pr_id

        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,
            detect='off')

        # assert
        self.mock_validate_token.assert_not_called()
        self.mock_create_PR.assert_called_once()
        self.mock_update_PR.assert_not_called()
        assert response.id == test_pr_id

        #compare the PR objects
        pr_object_from_create_call = self.mock_create_PR.call_args_list[0][1][
            'git_pull_request_to_create']
        assert pr_object_from_create_call.title == self._TEST_PR_TITLE
        assert pr_object_from_create_call.description == '\n'.join(
            self._TEST_PR_DESCRIPTION)
        assert pr_object_from_create_call.source_ref_name == resolve_git_ref_heads(
            self._TEST_SOURCE_BRANCH)
        assert pr_object_from_create_call.target_ref_name == resolve_git_ref_heads(
            self._TEST_TARGET_BRANCH)
        assert pr_object_from_create_call.work_item_refs == None
Example #2
0
def list_pull_requests(repository=None,
                       creator=None,
                       include_links=False,
                       reviewer=None,
                       source_branch=None,
                       status=None,
                       target_branch=None,
                       project=None,
                       skip=None,
                       top=None,
                       organization=None,
                       detect=None):
    """List pull requests.
    :param repository: Name or ID of the repository.
    :type repository: str
    :param creator: Limit results to pull requests created by this user.
    :type creator: str
    :param include_links: Include _links for each pull request.
    :type include_links: bool
    :param reviewer: Limit results to pull requests where this user is a reviewer.
    :type reviewer: str
    :param source_branch: Limit results to pull requests that originate from this source branch.
    :type source_branch: str
    :param status: Limit results to pull requests with this status.
    :type status: str
    :param target_branch: Limit results to pull requests that target this branch.
    :type target_branch: str
    :param skip: Number of pull requests to skip.
    :type skip: int
    :param top: Maximum number of pull requests to list.
    :type top: int
    :rtype: list of :class:`VssJsonCollectionWrapper <v5_0.git.models.VssJsonCollectionWrapper>`
    """
    organization, project, repository = resolve_instance_project_and_repo(
        detect=detect,
        organization=organization,
        project=project,
        repo=repository)
    search_criteria = GitPullRequestSearchCriteria(
        creator_id=resolve_identity_as_id(creator, organization),
        include_links=include_links,
        reviewer_id=resolve_identity_as_id(reviewer, organization),
        source_ref_name=resolve_git_ref_heads(source_branch),
        status=status,
        target_ref_name=resolve_git_ref_heads(target_branch))
    client = get_git_client(organization)
    if repository is None:
        pr_list = client.get_pull_requests_by_project(
            project=project,
            search_criteria=search_criteria,
            skip=skip,
            top=top)
    else:
        pr_list = client.get_pull_requests(project=project,
                                           repository_id=repository,
                                           search_criteria=search_criteria,
                                           skip=skip,
                                           top=top)
    return pr_list
def build_queue(
        definition_id=None,
        definition_name=None,
        branch=None,
        variables=None,
        open=False,  # pylint: disable=redefined-builtin
        organization=None,
        project=None,
        detect=None,
        commit_id=None,
        queue_id=None):
    """Request (queue) a build.
    :param definition_id: ID of the definition to queue. Required if --name is not supplied.
    :type definition_id: int
    :param definition_name: Name of the definition to queue. Ignored if --id is supplied.
    :type definition_name: str
    :param branch: Branch to build. Required if there is not a default branch set up on the definition. Example: "dev".
    :type branch: str
    :param variables: Space separated "name=value" pairs for the variables you would like to set.
    :type variables: [str]
    :param open: Open the build results page in your web browser.
    :type open: bool
    :param commit_id: Commit ID of the branch to build.
    :type commit_id: str
    :param queue_id: Queue Id of the pool that will be used to queue the build.
    :type queue_id: str
    :rtype: :class:`<Build> <v5_0.build.models.Build>`
    """
    organization, project = resolve_instance_and_project(
        detect=detect, organization=organization, project=project)
    if definition_id is None and definition_name is None:
        raise ValueError(
            'Either the --definition-id argument or the --definition-name argument '
            + 'must be supplied for this command.')
    client = get_build_client(organization)
    if definition_id is None:
        definition_id = get_definition_id_from_name(definition_name, client,
                                                    project)
    definition_reference = DefinitionReference(id=definition_id)
    build = Build(definition=definition_reference)
    build.source_branch = resolve_git_ref_heads(branch)
    build.source_version = commit_id
    if queue_id is not None:
        build.queue = AgentPoolQueue()
        build.queue.id = queue_id
    if variables is not None and variables:
        build.parameters = {}
        for variable in variables:
            separator_pos = variable.find('=')
            if separator_pos >= 0:
                build.parameters[
                    variable[:separator_pos]] = variable[separator_pos + 1:]
            else:
                raise ValueError(
                    'The --variables argument should consist of space separated "name=value" pairs.'
                )
    queued_build = client.queue_build(build=build, project=project)
    if open:
        _open_build(queued_build, organization)
    return queued_build
Example #4
0
def list_policy(organization=None, project=None, repository_id=None, branch=None, detect=None):
    """List all policies in a project.
    :param repository_id: Id (UUID) of the repository.
    :type repository_id: string
    :param branch: Branch. (--repository-id is required)
    :type branch: string
    :rtype: [PolicyConfiguration]
    """
    organization, project = resolve_instance_and_project(
        detect=detect, organization=organization, project=project)

    if branch is not None and repository_id is None:
        raise CLIError('--repository-id is required with --branch')

    scope = None

    if repository_id is not None:
        repository_id = repository_id.replace('-', '')
        scope = repository_id
        if branch is not None:
            branch = resolve_git_ref_heads(branch)
            scope = scope + ':' + branch

    policy_client = get_policy_client(organization)
    return policy_client.get_policy_configurations(project=project, scope=scope)
Example #5
0
def get_github_branch(repo, branch):
    """
    API Documentation - https://developer.github.com/v3/repos/branches/#get-branch
    Returns branch, is_folder
    branch : None if the branch with this name does not exist else branch ref
    is_folder : True or False
    """
    token = get_github_pat_token()
    head_ref_name = resolve_git_ref_heads(branch).lower()
    get_branch_url = 'https://api.github.com/repos/{repo_id}/git/{refs_heads_branch}'.format(
        repo_id=repo, refs_heads_branch=head_ref_name)
    get_response = requests.get(get_branch_url, auth=('', token))
    if get_response.status_code == _HTTP_NOT_FOUND_STATUS:
        return None, False
    if get_response.status_code == _HTTP_SUCCESS_STATUS:
        import json
        refs = json.loads(get_response.text)
        if isinstance(refs, list):
            if refs[0]['ref'].startswith(head_ref_name + '/'):
                logger.debug('Branch name is a folder hence invalid branch name.')
                return None, True
            # Parse and find correct branch
            for ref in refs:
                if ref['ref'] == head_ref_name:
                    return ref, False
            return None, False
        if refs['ref'] == head_ref_name:
            return refs, False
    raise CLIError('Cannot get branch ({branch})'.format(branch=branch))
Example #6
0
def create_github_branch(repo, source):
    """
    API Documentation - https://developer.github.com/v3/git/refs/#create-a-reference
    """
    token = get_github_pat_token()
    # Validate new branch name is valid
    branch_is_valid = False
    while not branch_is_valid:
        new_branch = prompt_not_empty(msg='Enter new branch name to create: ')
        ref, is_folder = get_github_branch(repo, new_branch)
        if not ref and not is_folder:
            branch_is_valid = True
        else:
            logger.warning('Not a valid branch name.')
    # Get source branch ref
    ref_item, is_folder = get_github_branch(repo, source)
    if not ref_item or is_folder:
        raise CLIError('Branch ({branch}) does not exist.'.format(branch=source))
    source_ref = ref_item['object']['sha']
    create_github_ref_url = 'https://api.github.com/repos/{repo_id}/git/refs'.format(repo_id=repo)
    create_github_ref_request_body = {
        "ref": resolve_git_ref_heads(new_branch),
        "sha": source_ref
    }
    create_response = requests.post(url=create_github_ref_url, auth=('', token),
                                    json=create_github_ref_request_body, headers=get_application_json_header())
    if not create_response.status_code == _HTTP_CREATED_STATUS:
        raise CLIError('Branch creation failed. Error: ({err})'.format(err=create_response.reason))
    return get_branch_name_from_ref(new_branch)
def pipeline_run(
        id=None,
        branch=None,
        commit_id=None,
        name=None,
        open=False,
        variables=None,  # pylint: disable=redefined-builtin
        folder_path=None,
        organization=None,
        project=None,
        detect=None):
    """ Queue (run) a pipeline.
    :param id: ID of the pipeline to queue. Required if --name is not supplied.
    :type id: int
    :param name: Name of the pipeline to queue. Ignored if --id is supplied.
    :type name: str
    :param branch: Name of the branch on which the pipeline run is to be queued. Example: refs/heads/master or master
    or refs/pull/1/merge or refs/tags/tag
    :type branch: str
    :param folder_path: Folder path of pipeline. Default is root level folder.
    :type folder_path: str
    :param variables: Space separated "name=value" pairs for the variables you would like to set.
    :type variables: [str]
    :param commit_id: Commit-id on which the pipeline run is to be queued.
    :type commit_id: str
    :param open: Open the pipeline results page in your web browser.
    :type open: bool
    :param detect: Automatically detect organization and project. Default is "on".
    :type detect: str
    """
    organization, project = resolve_instance_and_project(
        detect=detect, organization=organization, project=project)
    if id is None and name is None:
        raise ValueError('Either the --id argument or the --name argument ' +
                         'must be supplied for this command.')
    client = get_build_client(organization)
    if id is None:
        id = get_definition_id_from_name(name, client, project, folder_path)
    definition_reference = DefinitionReference(id=id)
    branch = resolve_git_ref_heads(branch)
    build = Build(definition=definition_reference,
                  source_branch=branch,
                  source_version=commit_id)
    if variables is not None and variables:
        build.parameters = {}
        for variable in variables:
            separator_pos = variable.find('=')
            if separator_pos >= 0:
                build.parameters[
                    variable[:separator_pos]] = variable[separator_pos + 1:]
            else:
                raise ValueError(
                    'The --variables argument should consist of space separated "name=value" pairs.'
                )
    queued_build = client.queue_build(build=build, project=project)
    if open:
        _open_pipeline_run(queued_build, organization)
    return queued_build
def build_list(definition_ids=None,
               branch=None,
               organization=None,
               project=None,
               detect=None,
               top=None,
               result=None,
               status=None,
               reason=None,
               tags=None,
               requested_for=None):
    """List build results.
    :param definition_ids: IDs (space separated) of definitions to list builds for.
    :type definition_ids: list of int
    :param branch: Filter by builds for this branch.
    :type branch: str
    :param organization: Azure Devops organization URL. Example: https://dev.azure.com/MyOrganizationName/
    :type organization: str
    :param project: Name or ID of the team project.
    :type project: str
    :param detect: Automatically detect organization and project. Default is "on".
    :type detect: str
    :param top: Maximum number of builds to list.
    :type top: int
    :param result: Limit to builds with this result.
    :type result: str
    :param status: Limit to builds with this status.
    :type status: str
    :param reason: Limit to builds with this reason.
    :type reason: str
    :param tags: Limit to builds with each of the specified tags. Space separated.
    :type tags: list of str
    :param requested_for: Limit to builds requested for this user or group.
    :type requested_for: str
    :rtype: :class:`<Build> <build.v4_0.models.Build>`
    """
    try:
        organization, project = resolve_instance_and_project(
            detect=detect, organization=organization, project=project)
        client = get_build_client(organization)
        if definition_ids is not None and definition_ids:
            definition_ids = list(set(definition_ids))  # make distinct
        if tags is not None and tags:
            tags = list(set(tags))  # make distinct
        builds = client.get_builds(definitions=definition_ids,
                                   project=project,
                                   branch_name=resolve_git_ref_heads(branch),
                                   top=top,
                                   result_filter=result,
                                   status_filter=status,
                                   reason_filter=reason,
                                   tag_filters=tags,
                                   requested_for=resolve_identity_as_id(
                                       requested_for, organization))
        return builds
    except VstsServiceError as ex:
        raise CLIError(ex)
def pipeline_run_list(pipeline_ids=None,
                      branch=None,
                      organization=None,
                      project=None,
                      detect=None,
                      top=None,
                      query_order=None,
                      result=None,
                      status=None,
                      reason=None,
                      tags=None,
                      requested_for=None):
    """ List the pipeline runs in a project.
    :param pipeline_ids: IDs (space separated) of definitions to list builds for.
    For multiple pipeline ids:  --pipeline-ids 1 2
    :type pipeline_ids: list of int
    :param branch: Filter by builds for this branch.
    :type branch: str
    :param top: Maximum number of builds to list.
    :type top: int
    :param query_order: Order of pipeline runs.
    :type query_order: str
    :param result: Limit to builds with this result.
    :type result: str
    :param status: Limit to builds with this status.
    :type status: str
    :param reason: Limit to builds with this reason.
    :type reason: str
    :param tags: Limit to builds with each of the specified tags. Space separated.
    :type tags: list of str
    :param requested_for: Limit to builds requested for this user or group.
    :type requested_for: str
    """
    organization, project = resolve_instance_and_project(
        detect=detect, organization=organization, project=project)
    client = get_build_client(organization)
    if pipeline_ids is not None and pipeline_ids:
        pipeline_ids = list(set(pipeline_ids))  # make distinct
    if tags is not None and tags:
        tags = list(set(tags))  # make distinct
    query_order = _resolve_runs_query_order(query_order)
    builds = client.get_builds(definitions=pipeline_ids,
                               project=project,
                               branch_name=resolve_git_ref_heads(branch),
                               top=top,
                               result_filter=result,
                               status_filter=status,
                               reason_filter=reason,
                               tag_filters=tags,
                               query_order=query_order,
                               requested_for=resolve_identity_as_id(
                                   requested_for, organization))
    return builds
def _checkin_file_to_azure_repo(path_to_commit, content, repo_name, branch,
                                organization, project, message):
    logger.warning('Checking in file %s in the Azure repo %s', path_to_commit, repo_name)
    message = message + ' [skip ci]'
    git_client = get_git_client(organization=organization)
    from azext_devops.devops_sdk.v5_0.git.models import GitPush, GitRefUpdate
    # Get base commit Id
    all_heads_refs = git_client.get_refs(repository_id=repo_name,
                                         project=project,
                                         filter='heads/')
    old_object_id = None
    for ref in all_heads_refs:
        if ref.name == resolve_git_ref_heads(branch):
            old_object_id = ref.object_id
    if not old_object_id:
        raise CLIError('Cannot checkin the file. Error in getting the commits info for {branch}'.format(branch=branch))

    push_object = GitPush()
    ref_update = GitRefUpdate()
    ref_update.name = resolve_git_ref_heads(branch)
    ref_update.old_object_id = old_object_id
    push_object.ref_updates = [ref_update]
    push_object.commits = _get_commits_object(path_to_commit, content, message)
    git_client.create_push(push=push_object, repository_id=repo_name, project=project)
def build_list(definition_ids=None,
               branch=None,
               organization=None,
               project=None,
               detect=None,
               top=None,
               result=None,
               status=None,
               reason=None,
               tags=None,
               requested_for=None):
    """List build results.
    :param definition_ids: IDs (space separated) of definitions to list builds for.
    :type definition_ids: list of int
    :param branch: Filter by builds for this branch.
    :type branch: str
    :param top: Maximum number of builds to list.
    :type top: int
    :param result: Limit to builds with this result.
    :type result: str
    :param status: Limit to builds with this status.
    :type status: str
    :param reason: Limit to builds with this reason.
    :type reason: str
    :param tags: Limit to builds with each of the specified tags. Space separated.
    :type tags: list of str
    :param requested_for: Limit to builds requested for this user or group.
    :type requested_for: str
    :rtype: :class:`<Build> <build.v4_0.models.Build>`
    """
    organization, project = resolve_instance_and_project(
        detect=detect, organization=organization, project=project)
    client = get_build_client(organization)
    if definition_ids is not None and definition_ids:
        definition_ids = list(set(definition_ids))  # make distinct
    if tags is not None and tags:
        tags = list(set(tags))  # make distinct
    builds = client.get_builds(definitions=definition_ids,
                               project=project,
                               branch_name=resolve_git_ref_heads(branch),
                               top=top,
                               result_filter=result,
                               status_filter=status,
                               reason_filter=reason,
                               tag_filters=tags,
                               requested_for=resolve_identity_as_id(
                                   requested_for, organization))
    return builds
def update_repo(repository,
                default_branch=None,
                name=None,
                organization=None,
                project=None,
                detect=None):
    """Update the Git repository.
    :param repository: Name or ID of the repository.
    :type repository: str
    :param organization: Azure Devops organization URL. Example: https://dev.azure.com/MyOrganizationName/
    :type organization: str
    :param project: Name or ID of the team project.
    :type project: str
    :param name: New name for the repository.
    :type name: str
    :param default_branch: Default branch to be set for the repository. Example: 'refs/heads/live' or 'live'.
    :type default_branch: str
    :param detect: Automatically detect organization, project and repository. Default is "on".
    :type detect: str
    """
    if not default_branch and not name:
        raise CLIError(
            "Either --default-branch or --name (for rename) must be provided to update repository."
        )
    try:
        organization, project, repository = resolve_instance_project_and_repo(
            detect=detect,
            organization=organization,
            project=project,
            project_required=True,
            repo=repository)
        git_client = get_git_client(organization)
        # Get the repo to be updated
        repository = git_client.get_repository(project=project,
                                               repository_id=repository)
        if default_branch:
            default_branch = resolve_git_ref_heads(default_branch)
            repository.default_branch = default_branch
        if name:
            repository.name = name
        repository = git_client.update_repository(
            project=project,
            repository_id=repository.id,
            new_repository_info=repository)
        return repository
    except VstsServiceError as ex:
        raise CLIError(ex)
def create_configuration_object(repository_id,
                                branch,
                                blocking,
                                enabled,
                                policy_type_id,
                                param_name_array,
                                param_value_array,
                                branch_match_type='exact'):
    branch = resolve_git_ref_heads(branch)
    policyConfiguration = PolicyConfiguration(is_blocking=blocking,
                                              is_enabled=enabled)
    scope = createScope(repository_id, branch, branch_match_type)
    policyConfiguration.settings = {'scope': scope}
    policyConfiguration.type = {'id': policy_type_id}

    index = 0
    for param in param_name_array:
        policyConfiguration.settings[param] = param_value_array[index]
        index = index + 1

    return policyConfiguration
def get_new_azure_repo_branch(organization, project, repository, source):
    from azext_devops.dev.repos.ref import list_refs, create_ref
    # get source ref object id
    object_id = None
    branch = resolve_git_ref_heads(source)
    filter_str = branch[5:]  # remove 'refs' to use as filter
    refs_list = list_refs(filter=filter_str, repository=repository, organization=organization, project=project)
    for ref in refs_list:
        if ref.name == branch:
            object_id = ref.object_id
            break
    if not object_id:
        raise CLIError('Cannot fetch source branch details for branch {br}'.format(br=branch))
    # get valid branch name
    branch_is_valid = False
    while not branch_is_valid:
        new_branch = prompt_not_empty(msg='Enter new branch name to create: ')
        try:
            create_ref('heads/' + new_branch, object_id, repository, organization, project)
            branch_is_valid = True
        except Exception:  # pylint: disable=broad-except
            logger.warning('Not a valid branch name.')
    return new_branch
Example #15
0
def update_repo(repository,
                default_branch=None,
                name=None,
                organization=None,
                project=None,
                detect=None):
    """Update the Git repository.
    :param repository: Name or ID of the repository.
    :type repository: str
    :param name: New name for the repository.
    :type name: str
    :param default_branch: Default branch to be set for the repository. Example: 'refs/heads/live' or 'live'.
    :type default_branch: str
    """
    if not default_branch and not name:
        raise CLIError(
            "Either --default-branch or --name (for rename) must be provided to update repository."
        )
    organization, project, repository = resolve_instance_project_and_repo(
        detect=detect,
        organization=organization,
        project=project,
        project_required=True,
        repo=repository)
    git_client = get_git_client(organization)
    # Get the repo to be updated
    repository = git_client.get_repository(project=project,
                                           repository_id=repository)
    if default_branch:
        default_branch = resolve_git_ref_heads(default_branch)
        repository.default_branch = default_branch
    if name:
        repository.name = name
    repository = git_client.update_repository(project=project,
                                              repository_id=repository.id,
                                              new_repository_info=repository)
    return repository
Example #16
0
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
def pipeline_run(
        id=None,
        branch=None,
        commit_id=None,
        name=None,
        open=False,
        variables=None,  # pylint: disable=redefined-builtin
        folder_path=None,
        organization=None,
        project=None,
        detect=None,
        parameters=None):
    """ Queue (run) a pipeline.
    :param id: ID of the pipeline to queue. Required if --name is not supplied.
    :type id: int
    :param name: Name of the pipeline to queue. Ignored if --id is supplied.
    :type name: str
    :param branch: Name of the branch on which the pipeline run is to be queued. Example: refs/heads/master or master
    or refs/pull/1/merge or refs/tags/tag
    :type branch: str
    :param folder_path: Folder path of pipeline. Default is root level folder.
    :type folder_path: str
    :param variables: Space separated "name=value" pairs for the variables you would like to set.
    :type variables: [str]
    :param parameters: Space separated "name=value" pairs for the parameters you would like to set.
    :type parameters: [str]
    :param commit_id: Commit-id on which the pipeline run is to be queued.
    :type commit_id: str
    :param open: Open the pipeline results page in your web browser.
    :type open: bool
    :param detect: Automatically detect organization and project. Default is "on".
    :type detect: str
    """
    organization, project = resolve_instance_and_project(
        detect=detect, organization=organization, project=project)
    if id is None and name is None:
        raise ValueError('Either the --id argument or the --name argument ' +
                         'must be supplied for this command.')
    client = get_build_client(organization)

    if id is None:
        id = get_definition_id_from_name(name, client, project, folder_path)

    if parameters:
        logger.debug(
            'Using "pipelines client v6_0" to include parameters in run')
        client = get_new_pipeline_client_v60(organization)

        repositories = {
            "self":
            RepositoryResourceParameters(ref_name=branch, version=commit_id)
        }
        resources = RunResourcesParameters(repositories=repositories)
        template_parameters = set_param_variable(parameters,
                                                 argument='parameters')

        param_variables = set_param_variable(variables, as_dict=True)
        run_parameters = RunPipelineParameters(
            resources=resources,
            variables=param_variables,
            template_parameters=template_parameters)

        queued_pipeline = client.run_pipeline(run_parameters=run_parameters,
                                              project=project,
                                              pipeline_id=id)
        if open:
            _open_pipeline_run6_0(queued_pipeline, project, organization)
        return queued_pipeline

    definition_reference = DefinitionReference(id=id)
    branch = resolve_git_ref_heads(branch)
    build = Build(definition=definition_reference,
                  source_branch=branch,
                  source_version=commit_id)

    param_variables = set_param_variable(variables)
    build.parameters = param_variables

    queued_build = client.queue_build(build=build, project=project)

    if open:
        _open_pipeline_run(queued_build, organization)
    return queued_build
def build_queue(
        definition_id=None,
        definition_name=None,
        branch=None,
        variables=None,
        open=False,  # pylint: disable=redefined-builtin
        organization=None,
        project=None,
        detect=None,
        source_branch=None,
        commit_id=None):
    """Request (queue) a build.
    :param definition_id: ID of the definition to queue. Required if --name is not supplied.
    :type definition_id: int
    :param definition_name: Name of the definition to queue. Ignored if --id is supplied.
    :type definition_name: str
    :param branch: Branch to build. Required if there is not a default branch set up on the definition. Example: "dev".
    :type branch: str
    :param variables: Space separated "name=value" pairs for the variables you would like to set.
    :type variables: [str]
    :param open: Open the build results page in your web browser.
    :type open: bool
    :param organization: Azure Devops organization URL. Example: https://dev.azure.com/MyOrganizationName/
    :type organization: str
    :param project: Name or ID of the team project.
    :type project: str
    :param detect: Automatically detect organization and project. Default is "on".
    :type detect: str
    :param source_branch: Obsolete. Use --branch instead.
    :type source_branch: str
    :param commit_id: Commit ID of the branch to build.
    :type commit_id: str
    :rtype: :class:`<Build> <build.v4_0.models.Build>`
    """
    try:
        if branch is None:
            branch = source_branch
        organization, project = resolve_instance_and_project(
            detect=detect, organization=organization, project=project)
        if definition_id is None and definition_name is None:
            raise ValueError(
                'Either the --definition-id argument or the --definition-name argument '
                + 'must be supplied for this command.')
        client = get_build_client(organization)
        if definition_id is None:
            definition_id = get_definition_id_from_name(
                definition_name, client, project)
        definition_reference = DefinitionReference(id=definition_id)
        build = Build(definition=definition_reference)
        build.source_branch = resolve_git_ref_heads(branch)
        build.source_version = commit_id
        if variables is not None and variables:
            build.parameters = {}
            for variable in variables:
                separator_pos = variable.find('=')
                if separator_pos >= 0:
                    build.parameters[
                        variable[:separator_pos]] = variable[separator_pos +
                                                             1:]
                else:
                    raise ValueError(
                        'The --variables argument should consist of space separated "name=value" pairs.'
                    )
        queued_build = client.queue_build(build=build, project=project)
        if open:
            _open_build(queued_build, organization)
        return queued_build
    except VstsServiceError as ex:
        raise CLIError(ex)