azure-devops/azext_devops/dev/pipelines/build_definition.py (80 lines of code) (raw):
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from webbrowser import open_new
from knack.log import get_logger
from azext_devops.dev.common.services import (get_build_client, get_git_client,
resolve_instance_and_project,
resolve_instance_project_and_repo)
from azext_devops.dev.common.uri import uri_quote
from azext_devops.dev.common.uuid import is_uuid
logger = get_logger(__name__)
def build_definition_list(name=None, top=None, organization=None, project=None, repository=None,
repository_type=None, detect=None):
"""List build definitions.
:param name: Limit results to definitions with this name or starting with this name. Examples: "FabCI" or "Fab*"
:type name: bool
:param top: Maximum number of definitions to list.
:type top: int
:param repository: Limit results to definitions associated with this repository.
:type repository: str
:param repository_type: Limit results to definitions associated with this repository type.
It is mandatory to pass 'repository' argument along with this argument.
:type repository_type: str
:rtype: [BuildDefinitionReference]
"""
organization, project, repository = resolve_instance_project_and_repo(
detect=detect, organization=organization, project=project, repo=repository)
client = get_build_client(organization)
query_order = 'DefinitionNameAscending'
repository_type = None
if repository is not None:
if repository_type is None:
repository_type = 'TfsGit'
if repository_type.lower() == 'tfsgit':
resolved_repository = _resolve_repository_as_id(repository, organization, project)
else:
resolved_repository = repository
if resolved_repository is None:
raise ValueError("Could not find a repository with name '{}', in project '{}'."
.format(repository, project))
else:
resolved_repository = None
definition_references = client.get_definitions(project=project, name=name, repository_id=resolved_repository,
repository_type=repository_type, top=top,
query_order=query_order)
return definition_references
def build_definition_show(id=None, name=None, open=False, organization=None, project=None, # pylint: disable=redefined-builtin
detect=None):
"""Get the details of a build definition.
:param id: ID of the definition.
:type id: int
:param name: Name of the definition. Ignored if --id is supplied.
:type name: str
:param open: Open the definition summary page in your web browser.
:type open: bool
:rtype: BuildDefinitionReference
"""
organization, project = resolve_instance_and_project(
detect=detect, organization=organization, project=project)
client = get_build_client(organization)
if id is None:
if name is not None:
id = get_definition_id_from_name(name, client, project)
else:
raise ValueError("Either the --id argument or the --name argument must be supplied for this command.")
build_definition = client.get_definition(definition_id=id, project=project)
if open:
_open_definition(build_definition, organization)
return build_definition
def _open_definition(definition, organization):
"""Opens the build definition in the default browser.
:param :class:`<BuildDefinitionReference> <v5_0.build.models.BuildDefinitionReference>` definition:
:param str organization:
"""
# https://dev.azure.com/OrgName/ProjectName/_build/index?definitionId=1234
project = definition.project.name
url = organization.rstrip('/') + '/' + uri_quote(project) + '/_build/index?definitionId='\
+ uri_quote(str(definition.id))
logger.debug('Opening web page: %s', url)
open_new(url=url)
def fix_path_for_api(path):
# Path with no preceeding '\' is not correctly interpreted so hack to add it.
if path:
if path.startswith('/'):
path = path[1:]
if not path.startswith('\\'):
path = '\\' + path
return path
def get_definition_id_from_name(name, client, project, path=None):
path = fix_path_for_api(path)
definition_references = client.get_definitions(project=project, name=name, path=path)
if len(definition_references) == 1:
return definition_references[0].id
if len(definition_references) > 1:
if is_uuid(project):
project = definition_references[0].project.name
message = 'Multiple definitions were found matching name "{name}" in project "{project}". Try '\
+ 'supplying the definition ID or folder path to differentiate.'
raise ValueError(message.format(name=name, project=project))
raise ValueError('There were no build definitions matching name "{name}" in project "{project}".'
.format(name=name, project=project))
def _resolve_repository_as_id(repository, organization, project):
if is_uuid(repository):
return repository
git_client = get_git_client(organization)
repositories = git_client.get_repositories(project=project, include_links=False, include_all_urls=False)
for found_repository in repositories:
if found_repository.name.lower() == repository.lower():
return found_repository.id
return None