azure-devops/azext_devops/dev/pipelines/build.py (106 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.devops_sdk.v5_0.build.models import Build, DefinitionReference, AgentPoolQueue
from azext_devops.dev.common.git import resolve_git_ref_heads
from azext_devops.dev.common.identities import resolve_identity_as_id
from azext_devops.dev.common.services import (get_build_client,
resolve_instance_and_project)
from azext_devops.dev.common.uri import uri_quote
from .build_definition import get_definition_id_from_name
logger = get_logger(__name__)
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:
refs/heads/master or master or refs/pull/1/merge or refs/tags/tag
: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
def build_show(id, open=False, organization=None, project=None, detect=None): # pylint: disable=redefined-builtin
"""Get the details of a build.
:param id: ID of the build.
:type id: int
:param open: Open the build results page in your web browser.
:type open: bool
:rtype: :class:`<Build> <v5_0.build.models.Build>`
"""
organization, project = resolve_instance_and_project(
detect=detect, organization=organization, project=project)
client = get_build_client(organization)
build = client.get_build(build_id=id, project=project)
if open:
_open_build(build, organization)
return 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 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> <v5_0.build.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 build_cancel(build_id, open=False, organization=None, project=None, detect=None): # pylint: disable=redefined-builtin
"""Cancels if build is running.
:param build_id: ID of the build.
:type build_id: int
:param open: Open the build results page in your web browser.
:type open: bool
:rtype: :class:`<Build> <v5_0.build.models.Build>`
"""
organization, project = resolve_instance_and_project(
detect=detect, organization=organization, project=project)
client = get_build_client(organization)
build = Build(status="Cancelling")
build = client.update_build(build=build, project=project, build_id=build_id)
if open:
_open_build(build, organization)
return build
def add_build_tags(build_id, tags, organization=None, project=None, detect=None):
"""Add tag(s) for a build.
:param build_id: ID of the build.
:type build_id: int
:param tags: Tag(s) to be added to the build. [Comma separated values]
:type tags: str
:rtype: list of str
"""
organization, project = resolve_instance_and_project(detect=detect,
organization=organization,
project=project)
client = get_build_client(organization)
tags = list(map(str, tags.split(',')))
if len(tags) == 1:
tags = client.add_build_tag(project=project, build_id=build_id, tag=tags[0])
else:
tags = client.add_build_tags(tags=tags, project=project, build_id=build_id)
return tags
def delete_build_tag(build_id, tag, organization=None, project=None, detect=None):
"""Delete a build tag.
:param build_id: ID of the build.
:type build_id: int
:param tag: Tag to be deleted from the build.
:type tag: str
:rtype: list of str
"""
organization, project = resolve_instance_and_project(detect=detect,
organization=organization,
project=project)
client = get_build_client(organization)
tags = client.delete_build_tag(project=project, build_id=build_id, tag=tag)
return tags
def get_build_tags(build_id, organization=None, project=None, detect=None):
"""Get tags for a build
:param build_id: ID of the build.
:type build_id: int
:rtype: list of str
"""
organization, project = resolve_instance_and_project(detect=detect,
organization=organization,
project=project)
client = get_build_client(organization)
tags = client.get_build_tags(build_id=build_id, project=project)
return tags
def _open_build(build, organization):
"""Open the build results page in your web browser.
:param :class:`<Build> <v5_0.build.models.Build>` build:
:param str organization:
"""
# https://dev.azure.com/OrgName/ProjectName/_build/index?buildId=1234
project = build.project.name
url = organization.rstrip('/') + '/' + uri_quote(project) + '/_build/index?buildid='\
+ uri_quote(str(build.id))
logger.debug('Opening web page: %s', url)
open_new(url=url)