How to get status of the release (success, failure) with powershell using Azure DevOps Rest API - powershell

I am using post method to create release in Azure DevOps:
$url = "https://vsrm.dev.azure.com/"+$organization+"/"+$project+"/_apis/release/releases?api-version=5.1"
$body = #{definitionId = 9} | ConvertTo-Json -Depth 4
Invoke-RestMethod -Uri $url -Method POST -Body $body -ContentType "application/json" -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
My pipeline is simple with single stage which executes automatically. Release creation and execution works fine.
But how to get status of my stage/s using powershell and REST API. I need to keep executing script while Release is in progress and initiate script failure if any of the stages fails.
Any ideas?

Using DefinitionID and EnvironmentIDs (you will get this from your initial POST response), you can query the last release and check for "deploymentStatus" value in intervals and exit when the status changes to "succeeded/failed/cancelled".
(collectionURL)/(teamproject)/_apis/Release/deployments?definitionId="+RELEASE_DEFINITIONID+"&definitionEnvironmentId="+RELEASE_DEFINITIONENVIRONMENTID?api-version=1.0

Related

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 can I read the PR tag inside a pipeline triggered by another pipeline?

I had my first question answered here Is it possible to read the PR tag on a pipeline task? but my scenario is a little bit different. I need to read the PR tag from a pipeline that was triggered by another pipeline.
PR triggers the CI which checks if everything's ok for merge. If it is, the CI triggers the CD which will in turn read the PR tag.
PR -> CI -> CD (access the tag here)
I have a PowerShell task named Get PR tag with the following script (courtesy of Lance):
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/git/repositories/$($env:BUILD_REPOSITORY_NAME)/pullRequests/$($env:SYSTEM_PULLREQUEST_PULLREQUESTID)/labels?api-version=5.1-preview.1"
$response = Invoke-RestMethod -Uri $url -Method Get -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "##vso[task.setvariable variable=PullRequestTag;isOutput=true]$($response.value.name)"
But I keep getting "The request is invalid.":
========================== Starting Command Output ===========================
/usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command . '/home/vsts/work/_temp/74b14931-e33a-4389-b19f-3db7faa53e8d.ps1'
Invoke-RestMethod: /home/vsts/work/_temp/74b14931-e33a-4389-b19f-3db7faa53e8d.ps1:3
Line |
3 | $response = Invoke-RestMethod -Uri $url -Method Get -Headers #{
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"count":1,"value":{"Message":"The request is invalid."}}
##[error]PowerShell exited with code '1'.
Finishing: Get PR tag
My agent job is set to use the OAuth token:
Update
In release pipeline, the variable name is not the same as the variable name in build, we need update the url info in the script, we can also check the release pipeline variable in the Initialize job log.
Steps:
a. Configure branch policy and add the policy Build Validation-> add build pipeline A
b. Create release->select the build A as the Source type->Enable the feature Pull request trigger->open Pre-deployment conditions and enable the option Pull request deployment
c. Open the release->enable the feature Allow scripts to access the OAuth token (Click Agent Job Name=>Additional options) add task powershell and enter the script below
$url = "$($env:SYSTEM_TASKDEFINITIONSURI)$env:BUILD_PROJECTID/_apis/git/repositories/$($env:BUILD_REPOSITORY_NAME)/pullRequests/$($env:BUILD_PULLREQUEST_ID)/labels?api-version=5.1-preview.1"
$response = Invoke-RestMethod -Uri $url -Method Get -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "##vso[task.setvariable variable=PullRequestTag;isOutput=true]$($response.value.name)"
d. Configure the Reference name as PS and add task cmd to output the tags.
CMD script:
echo $(PS.PullRequestTag)
e. Create pull request and add tags
Result:
Update2
The pull request triggers the CI build pipeline(power shell), after the build pipeline is completed, another build pipeline(power shell test) will be triggered.
b. Open the build pipeline power shell test and add a new variable PullRequestID and grant test Build Service (xxx) account the Edit build pipeline permission. (open the build pipeline(power shell test)--> ... --> Security --> Edit build pipeline set to Allow)
c. enable the feature Allow scripts to access the OAuth token (Click Agent Job Name=>Additional options) add task powershell(Get the tag value) and enter the script below. click the powershell task->Output Variables->enter PS->add a task cmd and use the code echo $(PS.PullRequestTag) to output the tag value
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/git/repositories/$($env:BUILD_REPOSITORY_NAME)/pullRequests/$(PullRequestID)/labels?api-version=5.1-preview.1"
$response = Invoke-RestMethod -Uri $url -Method Get -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "##vso[task.setvariable variable=PullRequestTag;isOutput=true]$($response.value.name)"
d. Open build pipeline power shell, enable the feature Allow scripts to access the OAuth token (Click Agent Job Name=>Additional options) add task powershell and enter the script below to update the pipeline(power shell test) variable PullRequestID value.
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/55?api-version=5.1"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
# Update an existing variable named PullRequestID to its new value pull request ID
$pipeline.variables.PullRequestID.value= $($env:SYSTEM_PULLREQUEST_PULLREQUESTID)
####****************** 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 $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'PullRequestID ' is updated to" $updatedef.variables.PullRequestID.value
write-host "=========================================================="

Create an automatic PR and complete it Azure DevOps

I'm trying to create a flow where when a PR from branch a -> b is completed, an automatic PR from branch c -> d is created and completed.
I looked in this question but it doesn't mention auto complete
CI/CD pipelines Azure devops automatic merge after deploy release
Also, can I set a specific policy to the automated PR so it would be auto complete?
Update
I tried using the following call:
https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull%20requests/update?view=azure-devops-rest-5.1
But I got the error:
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Invalid argument value.\r\nParameter name: Invalid
pull request auto complete set by id. Valid values are either the current user identity id, or an empty guid (to unset
auto complete)."
I tried to get the creator ID from the response but it's empty.
I tried to assign Project Collection Build Service (msazure) like I saw here:
https://developercommunity.visualstudio.com/content/problem/298596/autocompletesetby-ignored-in-pull-request-rest-api.html
But I'm getting the error.
After you create the PR you can get the creator ID:
$response = Invoke-RestMethod -Uri $url -Method Post -Headers $head -Body $jsonBody -ContentType "application/json;charset=UTF-8"
$currentUserId = $response.createdBy.id
And send him in the update json body:
$body = #{
autoCompleteSetBy = #{ id = "$buildUserId" }
completionOptions = ""
}
$response = Invoke-RestMethod -Uri $url -Method Patch -Headers $head -Body $jsonBody -ContentType application/json
Here after creation of PR, run the update operation to set Autocomplet. Check the below link
https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull%20requests/update?view=azure-devops-rest-5.1

Capture commit count per pull request in Azure DevOps

I would like to get info on the number of commits per pull request. For now, semi-automated would be fine. Just looking for a simple approach, say, a PowerShell script. I'll likely need to create similar types of reports with different data in the future.
Does any approach lend itself to such a quick and dirty approach with Azure DevOps data?
There is a special Rest API for this: Pull Request Commits - Get Pull Request Commits:
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/pullRequests/{pullRequestId}/commits?api-version=5.1
So, simple PowerShell script:
$pat = "YOUR-PERSONAL-ACCESS-TOKEN"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,"$pat")))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$url = "https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/pullRequests/{pullRequestId}/commits?api-version=5.1"
$commitsCount = (Invoke-RestMethod -Method Get -Uri $url -Headers $headers -Body $jsonBody -ContentType 'application/json').count

Azure DevOps pipelines: Cancel multiple pending jobs in queue

In Azure DevOps pipelines, How do I cancel all pending jobs for a job pool. I've got lots queued and couldn't see where I can cancel all the jobs I have waiting.
Azure devops doesnot yet have this feature to cancel all the pending jobs in batch from the UI partal.
You can write scripts to call rest api to cancel all the pending jobs as walkaround. Check out below steps:
First, use list build rest api to get all the pending jobs.
https://dev.azure.com/{organization}/{project}/_apis/build/builds?statusFilter=notStarted&api-version=5.1
Then, use update build api to cancel the pending jobs:
PATCH https://dev.azure.com/{organization}/{project}/_apis/build/builds/{buildId}?api-version=5.1
See below powershell scripts for reference:
Check here to get a Personal access token that will be used in below scripts.
$url= "https://dev.azure.com/{organization}/{project}/_apis/build/builds?statusFilter=notStarted&api-version=5.1"
$pat="Personal Access Token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$pendingJobs=Invoke-RestMethod -Uri $url-Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)} -Method get -ContentType "application/json"
$jobsToCancel = $pendingJobs.value
#Pending jobs donot consume the job agents in the agent pool. To filter the definition name to cancel pending jobs for a particular pipeline, you can use below filter criteria.
#$jobsToCancel = $pendingJobs.value | where {$_.definition.Name -eq "{Name of your pipeline }"}
#call update api to cancel each job.
ForEach($build in $jobsToCancel)
{
$build.status = "Cancelling"
$body = $build | ConvertTo-Json -Depth 10
$urlToCancel = "https://dev.azure.com/{organization}/{project}/_apis/build/builds/$($build.id)?api-version=5.1"
Invoke-RestMethod -Uri $urlToCancel -Method Patch -ContentType application/json -Body $body -Header #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
}
You can also submit a new feature request(Click Suggest a feature and choose azure devops) to Microsoft development team for supporting cancelling pending jobs in batch. Hopefully they will consider adding this feature in the future sprint.
I find that using v6 of the api works, but instead of PATCH use DELETE.
(Reusing some of the code from #Levi Lu-MSFT)
$url= "https://dev.azure.com/{organization}/{project}/_apis/build/builds?statusFilter=notStarted&api-version=6.0-preview"
$pendingJobs=Invoke-RestMethod -Method GET -UseDefaultCredentials -Uri $url -ContentType "application/json"
$jobsToCancel = $pendingJobs.value
#$jobsToCancel = $pendingJobs.value | Where {$_.definition.Name -eq "{Name of your pipeline }"}
ForEach($build in $jobsToCancel)
{
$urlToCancel = "https://dev.azure.com/{organization}/{project}/_apis/build/builds/$($build.id)?api-version=6.0-preview"
Invoke-RestMethod -Uri $urlToCancel -Method DELETE -UseDefaultCredentials -ContentType application/json -Body $body
}