TLDR; This bash script will allow you to start and approve (multiple) Azure DevOps pipelines from the terminal.
Introduction
If you are using Azure DevOps Pipelines (similar to Github Actions) you might be going to the browser, navigating to the list of pipelines, selecting one, and clicking on the "Run pipeline" + "Run" buttons. If you want to start 10 pipelines (e.g. for 10 microservices) at once, you need to do the above clicking 10x2 times.
Once the builds have reached a stage guarded by an approval, you have to go into the build, click the "Review" + "Approve" buttons ... which would be another 10x2 clicks.
Wouldn't it be better to trigger the above from the terminal/CLI? You are happy to find the az pipelines run
az cli extension command, however things become very tricky when it comes to the approvals ...
The rest of this post is referring to a pipeline with 3 Stages - Build, Deploy to test and Deploy to prod
The az rest .. --resource ..
command
Before we get to solving the approval problem, there is one very useful command that will help us immensely - az rest
. This command allows us to invoke various Azure DevOps (and probably other) APIs without any personal access tokens (PATs) or similar. The important attribute to pass is --resource "https://management.core.windows.net/"
, which reuses our Azure DevOps session.
For example, a much faster alternative to az pipelines run
is the following command:
az rest --uri "https://dev.azure.com/$org/$project/_apis/pipelines?api-version=7.1" --resource "https://management.core.windows.net/"
Pretty neat solution to the generally very nasty authentication topic, which usually requires some awkward token handling!
Resource Model and Relations, or how to find the Approval
In order to implement the approval action, one has to first understand how to get to it, which requires navigation through a couple of Azure DevOps resources, namely:
- Pipeline
- Last Build
- Build Timeline and 3 specific records
- Approval
Pipeline
So first we find the pipelineId
by pipeline name:
pipelineId=$(az rest --uri "$adoBaseUrl/pipelines?api-version=7.1" --resource $resource | jq -c ".value.[] | select( .name == \"$pipeline\" ).id")
where adoBaseUrl=https://dev.azure.com/$org/$project/_apis/
and resource=https://management.core.windows.net/
Last Build
Next we find the last build for this pipeline:
build=$(az rest --uri "$adoBaseUrl/build/builds?api-version=7.1&definitions=$pipelineId&queryOrder=startTimeDescending&\$top=1" --resource $resource)
and from it we extract the timeline url:
timelineUrl=$(echo $build | jq -r '.value[0]._links.timeline.href')
Build Timeline
Getting the contents of the pipeline is easy:
timeline=$(az rest --uri "$timelineUrl" --resource $resource)
however it contains tons of records - depending on the pipeline definition, each one having parent record. We need to find the record corresponding to the approval stage, and for that we need to traverse (at least in my particular case) 3 records:
- deploy Stage record
- Checkpoint record
- Checkpoint.Approval record
This is done in the following way:
deployStageRecordId=$(echo $timeline | jq -r ".records[] | select( .identifier == \"$deployStageRecordIdentifier\" and .type == \"Stage\" ).id")
checkpointRecordId=$(echo $timeline | jq -r ".records[] | select( .parentId == \"$deployStageRecordId\" and .type == \"Checkpoint\" ).id")
approvalId=$(echo $timeline | jq -r ".records[] | select( .parentId == \"$checkpointRecordId\" and .type == \"Checkpoint.Approval\" ).id")
The last one gives us the approvalId
!
Approval
Once we have the approvalId
we can get for example its status
, so that we approve only if the status
is pending
:
approvalStatus=$(az rest --uri "$adoBaseUrl/pipelines/approvals/$approvalId?api-version=7.1" --resource $resource | jq -r ".status")
Finally, approve!
Once the approvalId is found, the following POST command must be issued to Review/Approve it:
az rest --method PATCH --uri "$adoBaseUrl/pipelines/approvals?api-version=7.1" --resource $resource --body "[ { \"approvalId\":\"$approvalId\", \"comment\":\"cli\", \"status\":\"approved\" } ]"
The full script can be found at https://github.com/deyanp/adopipelines/blob/main/pipeplines.sh
References
- https://stackoverflow.com/questions/77522387/approving-pipeline-stage-azure-devops-via-api?noredirect=1&lq=1
- https://stackoverflow.com/questions/71237839/approving-azure-pipeline-using-api
- https://learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/?view=azure-devops-rest-7.1
- https://learn.microsoft.com/en-us/rest/api/azure/devops/approvalsandchecks/?view=azure-devops-rest-7.1
Top comments (0)