Azure cli: clone pipeline - azure-devops

Looking at az pipelines documentation it seems it's not possible to clone a pipeline using cli.
I've looked at getting the yaml (az pipelines show -name=x > x_orig.yaml) and then trying to change json and create pipeline from modified yaml, but that feels like a lot of work that could break after next update.
Is there a way to clone a pipline without going the the Web UI?

Currently, there indeed is not available Azure CLI that can clone or export/import a pipeline to create a new pipeline.
I also searched and tried the Azure DevOps REST API for Pipelines, but did not find the available API.
Ideally, the Azure CLI "az pipelines create" can provide an input parameter that allows users specify an existing pipeline as a starting point for the new pipeline.
If your projects really need this feature, I recommend that you can directly report a feature request on the "Azure/azure-cli" repository to ask adding the parameter like as above mentioned. That will allow you directly interact with the appropriate engineering team, and make it more convenient for the engineering team to collect and categorize your suggestions.

As a workaround, we could clone the build definition via power shell script to call REST API.
Note: We need to change the original build definition name.
REST API
Get build definition:
GET https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0
Create build definition
POST https://dev.azure.com/{organization}/{project}/_apis/build/definitions?api-version=6.0
Power shell script
$connectionToken="{pat}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$BuildDefinitionInfoURL = "https://dev.azure.com/{org name}/{project name}/_apis/build/definitions/386"
$BuildDefinitionInfo = Invoke-RestMethod -Uri $BuildDefinitionInfoURL -Headers #{authorization = "Basic $base64AuthInfo"} -Method Get
Write-Host $BuildDefinitionInfo.name
$BuildDefinitionInfo.name = $BuildDefinitionInfo.name +" clone"
Write-Host $BuildDefinitionInfo.name
$body = $BuildDefinitionInfo | ConvertTo-Json -Depth 99
$createBuildDefinitionURL = "https://dev.azure.com/{org name}/{project name}/_apis/build/definitions?api-version=6.0"
$response = Invoke-RestMethod -Uri $createBuildDefinitionURL -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
Write-Host $response.id
Result:

Related

Managing branches with Azure DevOps Classic Build Pipelines and TFVC

How do you manage building from branches when using Azure DevOps Classic Build Pipelines and TFVC?
I believe that the only viable option is to copy the build pipeline with a new name and update the source code mapping to point to the new TFVC branch.
I see the ADO web UI provides the option to clone an individual build definition, yet as I have over 200+ build pipelines to clone whenever I branch is there a more efficient way to do this? Or is the only option to write a custom tool to leverage the ADO REST Api?
Since you need to clone pipelines in batches, using scripts to run the Rest API will be a reasonable method. As far as I know, there is no easy way out of the box other than this.
You could try the following PowerShell Script Sample:
$DefinitionIds = "PipelineIDs" #InPut All Pipelineids(e.g. "324,323,xxx" )
$DefinitionId = $DefinitionIds.split(",");
$token = "PAT Token"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
foreach ($i in $DefinitionId)
{
echo $i
$url="https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/build/definitions/$($i)?api-version=6.0"
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
Write-Host "$($response | ConvertTo-Json -Depth 100)"
$response.repository.properties.tfvcMapping= '{"mappings":[{"serverPath":"$/TFVCBranchName","mappingType":"map","localPath":"\\"}]}' # ServerPath is the Branch name
$response.repository.name = "TFVCRepoName" #Repo Source Name
$response.name = "Pipeline $i Clone" # Cloned PipelineName
echo $response.name
$url1= "https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/build/definitions?api-version=6.0"
$json = #($response) | ConvertTo-Json -Depth 100
$response1 = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Post -Body $json -ContentType application/json
}
Here are the Two Rest APIs used in the Script:
Definitions - Get
Definitions - Create
Result:
The cloned Pipeline will be set to the new TFVC branch and Build definition name.

Azure DevOps Server - pause/resume all pipelines during maintenance window

We have an Azure DevOps Server (on prem) and different build/release pipelines.
A build/release is depending to other systems. Now if we plan to do maintenance work on this other systems, no Azure build/release pipeline should be run during this time because of the dependency of this systems.
We can go to every pipeline and set the pipeline to "pause". This is working well for a small numbers of build/release pipelines, but if we have a lot of pipelines this would be time-consuming to enabled-disable all pipelines.
Is there any way to pause/resume all Azure Pipelines at the same time? (e.g. TeamCity has a simple flag to pause/resume the whole queue).
I checked the API, but there is also no way to disable the queue itself (change setting on the build/release pipeline). It this would be possible, we could loop through every pipeline definition and pause/resume the queue.
You can disable the agents to prevent the pipeline from running.
Go the Agent Pools under Pipelines in Project settings-->Select the agent pool -->Go to Agents tab-->Disable all the agents.
You can also use rest api to pause the build pipeline mentioned in the comments. See below example in powershell scripts: See here to get a personal access token.
$PAT="Personal Access Token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
#list build definiations api
$url = "https://dev.azure.com/org/proj/_apis/build/definitions?api-version=6.1-preview.7"
#list all build definitions
$AllDefinitons = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = ("Bearer {0}" -f $base64AuthInfo)} -Method get
#get all the definition ids
$Ids = $AllDefinitons.value | select id
foreach($id in $Ids){
$definitionUrl="https://dev.azure.com/org/proj/_apis/build/definitions/$($id.id)?api-version=6.1-preview.7"
#get the definition of each build pipeline
$definiton = Invoke-RestMethod -Uri $definitionUrl-Headers #{Authorization = ("Bearer {0}" -f $base64AuthInfo)} -Method get
#set queueStatus to paused
$definiton.queueStatus= "paused"
#update the definition
Invoke-RestMethod -Uri $definitionUrl-Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)} -Method put -Body (ConvertTo-Json $definiton-Depth 100) -ContentType "application/json"
}

How to get Releases Pipelines pre-deployment gates status through REST API in Azure DevOps

I am using Azure DevOps (ADO) REST APIs to build dashboards on Power BI. I wanted to query whether the releases pipelines of all projects in my organization have pre-deployment gates of "SonarCloud Quality Gate status" by using the REST APIs invocation.
I have tried this API (Releases - List) GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases?api-version=5.1. I am reading the MS docs and thought this particular GateStatuswill be useful for my needs, but this GateStatus does not show up when I am testing on my pipelines that have pre-deployment gates of "SonarCloud Quality Gate status" configured.
I found this API (Release - Get Release) GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases/{releaseId}?api-version=5.1 with MS docs. That preDeploymentGates shows the information I want when I am testing in POSTMAN. But, the problem is it requires releaseId in each query which is troublesome for me since my ultimate goal is to have a list of ALL releases in multiple projects of multiple organizations.
Thanks.
since my ultimate goal is to have a list of ALL releases in multiple projects of multiple organizations.
Since you want to get the Pipelines pre-deployment gates status for ALL releases in multiple projects of multiple organizations, so we use the API (Release - Get Release) to get the gates status, then loop this API in the all Release pipelines in one project, next, loop the all projects in one ORG, latest, loop all ORGs.
First, We need to create a All accessible organization PAT:
Because we need access multiple organizations.
Second, set a array to store the multiple organization names:
$ORGNames=#("Organization1","Organization2")
Then using following powershell scripts to loop the API (Release - Get Release):
$connectionToken="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$ORGNames=#("Organization1","Organization2")
ForEach ($ORGName in $ORGNames[0,1])
{
$ProjectUrl = "https://dev.azure.com/$($ORGName)/_apis/projects?api-version=5.1"
Write-Host "URL: $ProjectUrl"
$Projects = (Invoke-RestMethod -Uri $ProjectUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$ProjectId = $projects.value.id
Write-Host "Projects = $ProjectId"
ForEach ($Pt in $ProjectId)
{
$baseUrl = "https://vsrm.dev.azure.com/$($ORGName)/$($Pt)/_apis/release/releases?api-version=5.1"
$ReleaseId = (Invoke-RestMethod -Uri $baseUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$ReleaseIds = $ReleaseId.value.id
Write-Host "ReleaseID = $ReleaseId"
foreach($ReleaseID in $ReleaseIds){
$url = "https://vsrm.dev.azure.com/$($ORGName)/$($Pt)/_apis/release/releases/$($ReleaseID)?api-version=5.1"
$GatesStatus = (Invoke-RestMethod -Uri $url -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
Write-Host "GatesStatus For ORGName $ORGName Project $Pt And Release ID $ReleaseID= $($GatesStatus.environments.deploySteps.preDeploymentGates.status | ConvertTo-Json -Depth 100)"
}
}
}
The test result:
Hope this helps.

How to access Workitem Fields in azure devops (Like Development ,deployment,link fields)

Can anybody tell me how to GET the fields associated to workitem
Like Development field in azure devops.
OR
How to fetch the links associated to workitems in azure devops.
You can call Work item rest api to get the links associated to workitems by adding the `$expand=relations to the api string..
GET https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{id}?`$expand=relations&api-version=5.0
You can check below example in powershell script.
$url = "https://dev.azure.com/<Org>/<Proj>/_apis/wit/workitems/5?`$expand=All&api-version=5.0"
$connectionToken = "<PAT>"
$base64AuthInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$result = Invoke-RestMethod -Uri $url -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method get
Then you can get the associated linked in the relations property.

Store result of Azure CLI task into release variable

I have a release pipeline with multiple jobs.
On the first agent job there is an Azure CLI task that retrieves the keys of a storage account on azure.
The command it executes is :
az storage account keys list --account-name "$(diagnosticsStorageAccountName)" --resource-group "$(resourceGroup)"
What I want to do is store the result of this command and utilize it in a task that is running under a deployment group job.
I've already looked into these resource :
Set Output Variable in Azure CLI task on VSTS
How to modify Azure DevOps release definition variable from a release task?
I've tried the first one but I didn't get it working.
I didn't bothered with the second because it seems way to hacky.
Is there any way do achieve this that isn't hacky ?
The output values didn't get stored properly.
The output of az storage account keys list --account-name "$(diagnosticsStorageAccountName)" --resource-group "$(resourceGroup)"is spread over multiple lines when you use the following syntax:
echo "##vso[task.setvariable variable=testvar;]%myvar%"
So one of the problems was that only the first line of the JSON array was being stored into the variable.
I solved this problem in the following way:
keys=`az storage account keys list --account-name "$(diagnosticsStorageAccountName)" --resource-group "$(resourceGroup)"`
taskvariable="##vso[task.setvariable variable=_[tempVariable];]"
echo $taskvariable$keys
According to documentation echo "##vso[task.setvariable variable=testvar output=true;]%myvar% should make the variable available for the whole release. Unfortunately I had no luck with this.
I overcame this using a Powershell task under the same Agent Job (Ubuntu 16.0) :
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.1"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $(System.AccessToken)"
}
#Parsing JSON string from previous task
$keys = $(#"
$(_tempVariable)
"# | ConvertFrom-Json)
# Assignment of variable value
$pipeline.variables.[variableName].value = $keys[0].value
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $(System.AccessToken)"}
write-host "=========================================================="
Write-host "The value of Variable '[variableName]' is updated to" $updatedef.variables.[variableName].value
write-host "=========================================================="
Please note that in order to get this working there are a couple of things you need to do.
First you need to allow access to the OAuth token on the Agent Job.
On top of that you need to give the "Project Collection Build Service".
Click on security on the release and click on the "Project Collection Build Service" user.
Change the values for the "Edit release" and "Manage release" to allow and save the changes.