def show_pull_request(pull_request_id, open_browser=False, team_instance=None, detect=None): """Get the details of a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param open_browser: Open the pull request in your web browser. :type open_browser: bool :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: :class:`GitPullRequest <git.v4_0.models.GitPullRequest>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) pr = client.get_pull_request_by_id(pull_request_id) pr = client.get_pull_request(project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pull_request_id, include_commits=False, include_work_item_refs=True) if open_browser: _open_pull_request(pr, team_instance) return pr
def show_project(project_id=None, name=None, team_instance=None, detect=None, open_browser=False): """Show team project. :param project_id: The id (UUID) of the project to show. Required if the --name argument is not specified. :type project_id: str :param name: Name of the project to show. Ignored if the --id argument is specified. :type name: str :param team_instance: The URI for the VSTS account (https://<account>.visualstudio.com) or your TFS project collection. :type team_instance: str :param detect: When 'On' unsupplied arg values will be detected from the current working directory's repo. :type detect: str :param open_browser: Open the team project in the default web browser. :type open_browser: bool :rtype: :class:`<TeamProject> <core.v4_0.models.TeamProject>` """ try: if project_id is None and name is None: raise CLIError('Either the --name argument or the --id argument needs to be specified.') if project_id is not None: identifier = project_id else: identifier = name team_instance = resolve_instance(detect=detect, team_instance=team_instance) core_client = get_core_client(team_instance) team_project = core_client.get_project(project_id=identifier, include_capabilities=True) if open_browser: _open_project(team_project) return team_project except Exception as ex: handle_command_exception(ex)
def show_work_item(work_item_id, open_browser=False, team_instance=None, detect=None): """Show details for a work item. :param work_item_id: The ID of the work item :type work_item_id: int :param open_browser: Open the work item in the default web browser. :type open_browser: bool :param team_instance: The URI for the VSTS account (https://<account>.visualstudio.com) or your TFS project collection. :type team_instance: str :param detect: When 'On' unsupplied arg values will be detected from the current working directory's repo. :type detect: str :rtype: :class:`<WorkItem> <work-item-tracking.v4_0.models.WorkItem>` """ try: team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_work_item_tracking_client(team_instance) work_item = client.get_work_item(work_item_id) if open_browser: _open_work_item(work_item, team_instance) return work_item except Exception as ex: handle_command_exception(ex)
def create_pull_request_reviewers(pull_request_id, reviewers, team_instance=None, detect=None): """Add one or more reviewers to a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param reviewers: Users or groups to include as reviewers on a pull request. Space separated. :type reviewers: list of str :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: list of :class:`IdentityRefWithVote <git.v4_0.models.IdentityRefWithVote>` """ try: team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) pr = client.get_pull_request_by_id(pull_request_id) resolved_reviewers = _resolve_reviewers_as_refs( reviewers, team_instance) identities = client.create_pull_request_reviewers( reviewers=resolved_reviewers, project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pull_request_id) except Exception as ex: handle_command_exception(ex) return identities
def queue_pr_policy(pull_request_id, evaluation_id, team_instance=None, detect=None): """Queue an evaluation of a policy for a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param evaluation_id: ID of the policy evaluation to queue. :type evaluation_id: str :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: :class:`PolicyEvaluationRecord <policy.v4_0.models.PolicyEvaluationRecord>` """ try: team_instance = resolve_instance(detect=detect, team_instance=team_instance) git_client = get_git_client(team_instance) pr = git_client.get_pull_request_by_id(pull_request_id) policy_client = get_policy_client(team_instance) return policy_client.requeue_policy_evaluation( project=pr.repository.project.id, evaluation_id=evaluation_id) except Exception as ex: handle_command_exception(ex)
def vote_pull_request(pull_request_id, vote, team_instance=None, detect=None): """Vote on a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param vote: New vote value for the pull request. :type vote: int :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: :class:`IdentityRefWithVote <git.v4_0.models.IdentityRefWithVote>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) pr = client.get_pull_request_by_id(pull_request_id) resolved_reviewer = IdentityRefWithVote( id=resolve_identity_as_id(ME, team_instance)) resolved_reviewer.vote = _convert_vote_to_int(vote) created_reviewer = client.create_pull_request_reviewer( project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pull_request_id, reviewer_id=resolved_reviewer.id, reviewer=resolved_reviewer) return created_reviewer
def list_pr_policies(pull_request_id, team_instance=None, detect=None, top=None, skip=None): """List policies of a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :param top: Maximum number of policies to list. :type top: int :param skip: Number of policies to skip. :type skip: int :rtype: list of :class:`PolicyEvaluationRecord <policy.v4_0.models.PolicyEvaluationRecord>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) git_client = get_git_client(team_instance) pr = git_client.get_pull_request_by_id(pull_request_id) policy_client = get_policy_client(team_instance) artifact_id = "vstfs:///CodeReview/CodeReviewId/{project_id}/{pull_request_id}".format( project_id=pr.repository.project.id, pull_request_id=pull_request_id) return policy_client.get_policy_evaluations( project=pr.repository.project.id, artifact_id=artifact_id, top=top, skip=skip)
def list_pull_request_work_items(pull_request_id, team_instance=None, detect=None): """List linked work items for a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: list of :class:`AssociatedWorkItem <git.v4_0.models.AssociatedWorkItem>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) pr = client.get_pull_request_by_id(pull_request_id) refs = client.get_pull_request_work_items(project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pull_request_id) if refs: ids = [] for ref in refs: ids.append(ref.id) wit_client = get_work_item_tracking_client(team_instance) return wit_client.get_work_items(ids=ids)
def delete_pull_request_reviewers(pull_request_id, reviewers, team_instance=None, detect=None): """Remove one or more reviewers from a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param reviewers: Users or groups to remove as reviewers on a pull request. Space separated. :type reviewers: list of str :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: list of :class:`IdentityRefWithVote <git.v4_0.models.IdentityRefWithVote>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) pr = client.get_pull_request_by_id(pull_request_id) resolved_reviewers = _resolve_reviewers_as_ids(reviewers, team_instance) for reviewer in resolved_reviewers: client.delete_pull_request_reviewer(project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pull_request_id, reviewer_id=reviewer) return client.get_pull_request_reviewers(project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pull_request_id)
def setting_add_or_update(entries, user_scope, team_instance=None, detect=None): team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_settings_client(team_instance) client.set_entries(entries=entries, user_scope=user_scope)
def add_pull_request_work_items(pull_request_id, work_items, team_instance=None, detect=None): """Link one or more work items to a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param work_items: IDs of the work items to link. Space separated. :type work_items: list of int :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: list of :class:`AssociatedWorkItem <git.v4_0.models.AssociatedWorkItem>` """ try: team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) existing_pr = client.get_pull_request_by_id(pull_request_id) if work_items is not None and work_items: work_items = list(set(work_items)) # make distinct wit_client = get_work_item_tracking_client(team_instance) pr_url = 'vstfs:///Git/PullRequestId/{project}%2F{repo}%2F{id}'.format( project=existing_pr.repository.project.id, repo=existing_pr.repository.id, id=pull_request_id) for work_item_id in work_items: patch_document = [] patch_operation = JsonPatchOperation() patch_operation.op = 0 patch_operation.path = '/relations/-' patch_operation.value = WorkItemRelation() patch_operation.value.attributes = {'name': 'Pull Request'} patch_operation.value.rel = 'ArtifactLink' patch_operation.value.url = pr_url patch_document.append(patch_operation) try: wit_client.update_work_item(document=patch_document, id=work_item_id) except VstsClientRequestError as ex: logging.exception(ex) message = ex.args[0] if message != 'Relation already exists.': raise CLIError(ex) refs = client.get_pull_request_work_items( project=existing_pr.repository.project.id, repository_id=existing_pr.repository.id, pull_request_id=pull_request_id) ids = [] for ref in refs: ids.append(ref.id) return wit_client.get_work_items(ids=ids) except Exception as ex: handle_command_exception(ex)
def task_list(team_instance=None, task_id=None, detect=None): """List tasks. :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param str task_id: The UUID of the task. :param detect: Automatically detect values for instance and project. Default is "on". :type detect: str :rtype: [TaskDefinition] """ if task_id is not None and not is_uuid(task_id): raise ValueError("The --id argument must be a UUID.") team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_task_agent_client(team_instance) definition_references = client.get_task_definitions(task_id=task_id) return definition_references
def _update_pull_request_status(pull_request_id, new_status, team_instance=None, detect=None): team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) 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 list_pull_request_reviewers(pull_request_id, team_instance=None, detect=None): """List reviewers of a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: list of :class:`IdentityRefWithVote <git.v4_0.models.IdentityRefWithVote>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) pr = client.get_pull_request_by_id(pull_request_id) return client.get_pull_request_reviewers(project=pr.repository.project.id, repository_id=pr.repository.id, pull_request_id=pull_request_id)
def download_package(feed, name, version, path, team_instance=None, detect=None): """(PREVIEW) Download a package. :param feed: Name or ID of the feed. :type feed: str :param name: Name of the package, e.g. 'foo-package'. :type name: str :param version: Version of the package, e.g. 1.0.0. :type version: str :param path: Directory to place the package contents. :type path: str :param team_instance: VSTS account URL. Example: 'https://myaccount.visualstudio.com'. :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str """ colorama.init() # Needed for humanfriendly spinner to display correctly logger.warning(_UNIVERSAL_PREVIEW_MESSAGE) team_instance = resolve_instance(detect=detect, team_instance=team_instance) artifact_tool = ArtifactToolInvoker(ProgressReportingExternalToolInvoker(), ArtifactToolUpdater()) return artifact_tool.download_universal(team_instance, feed, name, version, path)
def list_projects(team_instance=None, top=None, skip=None, detect=None): """List team projects :param team_instance: The URI for the VSTS account (https://<account>.visualstudio.com) or your TFS project collection. :type team_instance: str :param top: Maximum number of results to list. :type top: int :param skip: Number of results to skip. :type skip: int :param detect: When 'On' unsupplied arg values will be detected from the current working directory's repo. :type detect: str :rtype: list of :class:`<TeamProject> <core.v4_0.models.TeamProject>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) core_client = get_core_client(team_instance) team_projects = core_client.get_projects(state_filter='all', top=top, skip=skip) return team_projects
def update_work_item(work_item_id, title=None, description=None, assigned_to=None, state=None, area=None, iteration=None, reason=None, discussion=None, fields=None, open_browser=False, team_instance=None, detect=None): """Update work items. :param work_item_id: The id of the work item to update. :type work_item_id: str :param title: Title of the work item. :type title: str :param description: Description of the work item. :type description: str :param assigned_to: Name of the person the work item is assigned-to (e.g. fabrikam). :type assigned_to: str :param state: State of the work item (e.g. active). :type state: str :param area: Area the work item is assigned to (e.g. Demos). :type area: str :param iteration: Iteration path of the work item (e.g. Demos\Iteration 1). :type iteration: str :param reason: Reason for the state work item. :type reason: str :param discussion: Comment to add to a discussion in a work item. :type discussion: str :param fields: Space separated "field=value" pairs for custom fields you would like to set. :type fields: [str] :param open_browser: Open the work item in the default web browser. :type open_browser: bool :param team_instance: The URI for the VSTS account (https://<account>.visualstudio.com) or your TFS project collection. :type team_instance: str :param detect: When 'On' unsupplied arg values will be detected from the current working directory's repo. :type detect: str :rtype: :class:`<WorkItem> <work-item-tracking.v4_0.models.WorkItem>` """ try: team_instance = resolve_instance(detect=detect, team_instance=team_instance) patch_document = [] if title is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.Title', title)) if description is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.Description', description)) if assigned_to is not None: # 'assigned to' does not take an identity id. Display name works. if assigned_to == '': resolved_assigned_to = '' else: resolved_assigned_to = _resolve_identity_as_unique_user_id( assigned_to, team_instance) if resolved_assigned_to is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.AssignedTo', resolved_assigned_to)) if state is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.State', state)) if area is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.AreaPath', area)) if iteration is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.IterationPath', iteration)) if reason is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.Reason', reason)) if discussion is not None: patch_document.append( _create_work_item_field_patch_operation( 'add', 'System.History', discussion)) if fields is not None and fields: for field in fields: kvp = field.split('=', 1) if len(kvp) == 2: patch_document.append( _create_work_item_field_patch_operation( 'add', kvp[0], kvp[1])) else: raise ValueError( 'The --fields argument should consist of space separated "field=value" pairs.' ) client = get_work_item_tracking_client(team_instance) work_item = client.update_work_item(document=patch_document, id=work_item_id) if open_browser: _open_work_item(work_item, team_instance) return work_item except VstsServiceError as ex: _handle_vsts_service_error(ex)
def create_project(name, team_instance=None, process=None, source_control='git', description=None, detect=None, open_browser=False): """Create a team project. :param name: Name of the new project. :type name: str :param team_instance: The URI for the VSTS account (https://<account>.visualstudio.com) or your TFS project collection. :type team_instance: str :param process: Process to use. Default if not specified. :type process: str :param source_control: Source control type of the initial code repository created. Valid options: git (the default) and tfvc. :type source_control: str :param description: Description for the new project. :type description: str :param detect: When 'On' unsupplied arg values will be detected from the current working directory's repo. :type detect: str :param open_browser: Open the team project in the default web browser. :type open_browser: bool :rtype: :class:`<TeamProject> <core.v4_0.models.TeamProject>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) team_project = TeamProject() team_project.name = name team_project.description = description # private is the only allowed value by vsts right now. team_project.visibility = 'private' core_client = get_core_client(team_instance) # get process template id process_id = None process_list = core_client.get_processes() if process is not None: process_lower = process.lower() for process in process_list: if process.name.lower() == process_lower: process_id = process.id break if process_id is None: raise CLIError( 'Could not find a process template with name: "{}"'.format( name)) if process_id is None: for process in process_list: if process.is_default: process_id = process.id break if process_id is None: raise CLIError( 'Could not find a default process template: "{}"'.format(name)) # build capabilities version_control_capabilities = { VERSION_CONTROL_CAPABILITY_ATTRIBUTE_NAME: source_control } process_capabilities = { PROCESS_TEMPLATE_CAPABILITY_TEMPLATE_TYPE_ID_ATTRIBUTE_NAME: process_id } team_project.capabilities = { VERSION_CONTROL_CAPABILITY_NAME: version_control_capabilities, PROCESS_TEMPLATE_CAPABILITY_NAME: process_capabilities } # queue project creation operation_reference = core_client.queue_create_project( project_to_create=team_project) operation = wait_for_long_running_operation(team_instance, operation_reference.id, 1) status = operation.status.lower() if status == 'failed': raise CLIError('Project creation failed.') elif status == 'cancelled': raise CLIError('Project creation was cancelled.') team_project = core_client.get_project(project_id=name, include_capabilities=True) if open_browser: _open_project(team_project) return team_project
def setting_remove(key, user_scope, team_instance=None, detect=None): team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_settings_client(team_instance) client.remove_entries(key=key, user_scope=user_scope)
def setting_list(user_scope, key=None, team_instance=None, detect=None): team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_settings_client(team_instance) entries = client.get_entries(user_scope=user_scope, key=key) return entries
def update_pull_request(pull_request_id, title=None, description=None, auto_complete=None, squash=None, delete_source_branch=None, bypass_policy=None, bypass_policy_reason=None, merge_commit_message=None, team_instance=None, detect=None, transition_work_items=None): """Update a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param title: New title for the pull request. :type title: str :param description: New description for the pull request. :type description: 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: str :param squash: Squash the commits in the source branch when merging into the target branch. :type squash: str :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: str :param bypass_policy: Bypass required policies (if any) and completes the pull request once it can be merged. :type bypass_policy: str :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 team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: 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: str :rtype: :class:`GitPullRequest <git.v4_0.models.GitPullRequest>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) existing_pr = client.get_pull_request_by_id(pull_request_id) pr = GitPullRequest(title=title, description=description) if (bypass_policy is not None or 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 = resolve_on_off_switch( 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 = resolve_on_off_switch( delete_source_branch) if squash is not None: completion_options.squash_merge = resolve_on_off_switch(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 = resolve_on_off_switch( transition_work_items) pr.completion_options = completion_options if auto_complete is not None: if resolve_on_off_switch(auto_complete): pr.auto_complete_set_by = IdentityRef( id=resolve_identity_as_id(ME, team_instance)) else: pr.auto_complete_set_by = IdentityRef(id=EMPTY_UUID) 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 remove_pull_request_work_items(pull_request_id, work_items, team_instance=None, detect=None): """Unlink one or more work items from a pull request. :param pull_request_id: ID of the pull request. :type pull_request_id: int :param work_items: IDs of the work items to unlink. Space separated. :type work_items: list of int :param team_instance: VSTS account or TFS collection URL. Example: https://myaccount.visualstudio.com :type team_instance: str :param detect: Automatically detect instance. Default is "on". :type detect: str :rtype: list of :class:`AssociatedWorkItem <git.v4_0.models.AssociatedWorkItem>` """ team_instance = resolve_instance(detect=detect, team_instance=team_instance) client = get_git_client(team_instance) existing_pr = client.get_pull_request_by_id(pull_request_id) if work_items is not None and work_items: work_items = list(set(work_items)) # make distinct wit_client = get_work_item_tracking_client(team_instance) work_items_full = wit_client.get_work_items(ids=work_items, expand=1) if work_items_full: url = 'vstfs:///Git/PullRequestId/{project}%2F{repo}%2F{id}'.format( project=existing_pr.repository.project.id, repo=existing_pr.repository.id, id=pull_request_id) for work_item in work_items_full: if work_item.relations is not None: index = 0 for relation in work_item.relations: if relation.url == url: patch_document = [] patch_test_operation = JsonPatchOperation() patch_test_operation.op = 'test' patch_test_operation.path = '/rev' patch_test_operation.value = work_item.rev patch_document.append(patch_test_operation) patch_operation = JsonPatchOperation() patch_operation.op = 1 patch_operation.path = '/relations/{index}'.format( index=index) patch_document.append(patch_operation) wit_client.update_work_item( document=patch_document, id=work_item.id) else: index += 1 refs = client.get_pull_request_work_items( project=existing_pr.repository.project.id, repository_id=existing_pr.repository.id, pull_request_id=pull_request_id) if refs: ids = [] for ref in refs: ids.append(ref.id) if ids: return wit_client.get_work_items(ids=ids)