How to prevent multiple runs of same pipeline due to multiple build completion check? - azure

I am trying to run a pipeline based on build completion trigger. There are 4 build completion triggers enabled. Hence, the pipeline runs 4 times.
I have enabled "Batch changes while a build is in progress".
How do I make it run a single time once all build completion is complete?

Batch changes while a build is in progress only for CI builds. You can not apply it to build completion triggers. However, you can use PowerShell to run another pipeline: How to trigger a build from another build pipeline in azure devops
Just check active pipelines to skip many triggers. Here is example:
$user = ""
$token = $env:SYSTEM_ACCESSTOKEN
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$orgUrl = "$env:SYSTEM_COLLECTIONURI"
$teamProject = "$env:SYSTEM_TEAMPROJECT"
$currentBuildDefId = "$env:SYSTEM_DEFINITIONID"
$buildBodyTemplate = "{`"definition`": {`"id`": <build_id>}}"
$restApiQueueBuild = "$orgUrl/$teamProject/_apis/build/builds?api-version=6.0"
$restApiGetBuilds = "$orgUrl/$teamProject/_apis/build/builds?definitions=$currentBuildDefId&statusFilter=inProgress,notStarted&api-version=6.0"
function InvokeGetRequest ($GetUrl)
{
return Invoke-RestMethod -Uri $GetUrl -Method Get -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
}
function InvokePostRequest ($PostUrl, $body)
{
return Invoke-RestMethod -Uri $PostUrl -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body
}
function RunBuild($buildId)
{
$buildBody = $buildBodyTemplate.Replace("<build_id>", $buildId)
Write-Host $buildBody
$buildresponse = InvokePostRequest $restApiQueueBuild $buildBody
Write-Host $buildresponse
}
$resBuild = InvokeGetRequest $restApiGetBuilds
if ($resBuild.count -gt 1)
{
Write-Host $resBuild.count " builds in progress, skip the second build"
return
}
RunBuild SECOND_BUILD_DEF_ID

Related

Azure devops release edit bulk 110

Hello I have 145 releases
And I have to do an equal action for everyone for example add a certain variable and edit a certain line.
Is there a way to control everyone with a script?
I checked for a template, but it creates the release from 0 and does not edit it.
Can a script in PS or Python be a solution? I did not find any information on Google about it, other than an export release template.
Azure devops release edit bulk 110
You could use the REST API Definitions - Update to update the release pipeline:
PUT https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions/{DefinitionsId}?api-version=6.0
And if we want to batch modify the release pipeline, we need to get each ID of the release pipeline with REST API Definitions - List:
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions?api-version=6.0
Then we could iterate through each Rlease ID obtained.
I provide a rough code for your better reading:
$connectionToken="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$ReleasePipelineUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions?api-version=6.0"
Write-Host "URL: $ReleasePipelineUrl"
$ReleasePipelines = (Invoke-RestMethod -Uri $PipelineUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$ReleasePipelinesId = $ReleasePipelines.value.id
Write-Host "ReleasePipelinesId = $ReleasePipelinesId"
ForEach ($Pt in $ReleasePipelinesId)
{
$baseUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions/$($Pt)?api-version=6.0"
$pipeline = (Invoke-RestMethod -Uri $baseUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
Write-Host "URL: $baseUrl"
$pipeline.variables.TestValue.value = "$buildNumber"
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
Write-Host "URL: $json "
$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 'TestValue' is updated to" $updatedef.variables.TestValue.value
}

Azure devops build pipeline depends on other build pipeline

I have four projects. One is a common project for other three projects.
Other three project build pipeline are depend on common build pipeline. When common build pipeline is in progress, other three build pipeline should be wait until common build complete. How to achive this in on premise azure devops?
How to achive this in on premise azure devops?
You could add a PowerShell task at the beginning of the other three pipelines.
Here is Powershell script sample:
$token = "PAT"
$url="https://{instance}/{collection}/{project}/_apis/build/definitions/{definitionId}?includeLatestBuilds=true&api-version=5.1"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$buildid = $response.latestBuild.id
$success = $false
do{
try{
$Buildurl2 = "https://{instance}/{collection}/{project}/_apis/build/builds/$($buildid)?api-version=5.0"
$Buildinfo2 = Invoke-RestMethod -Method Get -ContentType application/json -Uri $Buildurl2 -Headers #{Authorization=("Basic {0}" -f $token)}
$BuildStatus= $Buildinfo2.status
$result = $Buildinfo2.result
echo $result
echo $BuildStatus
if($BuildStatus -eq "completed") {
write-output "No Running Pipeline, starting Next Pipeline"
$success = $true
} else {
Write-output "Pipeline Build In Progress, Waiting for it to finish!"
Write-output "Next attempt in 30 seconds"
Start-sleep -Seconds 30
}
}
catch{
Write-output "catch - Next attempt in 30 seconds"
write-output "1"
Start-sleep -Seconds 30
# Put the start-sleep in the catch statemtnt so we
# don't sleep if the condition is true and waste time
}
$count++
}until($count -eq 2000 -or $success -eq $true )
if ($result -ne "succeeded")
{
echo "##vso[task.logissue type=error]Something went very wrong."
}
if(-not($success)){exit}
Explanation:
This powershell script runs the following two Rest APIs:
Definitions - Get
Builds - Get
The script checks the status of the pipeline(by polling) that is in process. If the pipeline is completed and the result is successful, it will run the other three pipelines. Or it will wait for the pipeline finishing the build.
Result Sample:

Check if my test plan has a failed test case in the pipeline execution

How can I check if I have any test cases failing within my test plan when executing my pipeline in azure devops?
How can I check if I have any test cases failing within my test plan when executing my pipeline in azure devops?
In Test Plan, the test case has no outcome state(e.g. fail pass ..). The outcome state is for Test points in Test Plan -> Execute tab.
To check if there are failed test points in Test Plan, you could use PowerShell Task to run the Rest API: Test Point - Get Points and Test Suites - Get Test Suites For Plan.
$token = "PAT"
$url1 = " https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/test/Plans/{TestPlanId}/suites?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response1 = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$i = 0
ForEach ($SuitId in $response1.value.id )
{
$url="https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/testplan/Plans/{TestPlanName}/Suites/$($SuitId)/TestPoint?api-version=6.0-preview.2"
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach( $outcome in $response.value.results.outcome )
{
echo $outcome
if($outcome -eq "failed")
{
$i ++
}
}
}
echo $i
if ($i -eq 0)
{
echo "No error"
}
else
{
echo "##vso[task.logissue type=warning]the error value is $i"
}
Result:

How to trigger a build from another build pipeline in azure devops

I have two build pipeline for two different projects.One is for building the actual project and another build pipeline for test automation. I want to automatically trigger the build pipeline of test automation once the actual project build succeed.
does there any possible way can i add one more task down to the actual build to trigger the test automation build, or suggest a possible way for the same.
Answers are much appreciable!!
You can use the "Build Completion" trigger in your second pipeline:
Additionally, you can add PowerShell script to queue another build from the parent build. Example:
$user = ""
$token = $env:SYSTEM_ACCESSTOKEN
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$orgUrl = "$env:SYSTEM_COLLECTIONURI"
$teamProject = "$env:SYSTEM_TEAMPROJECT"
$buildBodyTemplate = "{`"definition`": {`"id`": <build_id>}}"
$restApiQueueBuild = "$orgUrl/$teamProject/_apis/build/builds?api-version=6.0"
function InvokePostRequest ($PostUrl, $body)
{
return Invoke-RestMethod -Uri $PostUrl -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body
}
function RunBuild($buildId)
{
$buildBody = $buildBodyTemplate.Replace("<build_id>", $buildId)
Write-Host $buildBody
$buildresponse = InvokePostRequest $restApiQueueBuild $buildBody
Write-Host $buildresponse
}
RunBuild SECOND_BUILD_ID
Update SECOND_BUILD_ID to ID of your build definition with tests. Additionally, add access to the security token in the parent build:

Trigger Azure DevOps pipeline from another pipeline

I was looking at the azure triggers documentation and still not able to find an appropriate solution.
How during the execution of pipeline 1 can you trigger pipeline 2, wait for it to successfully finish or fail, and based on pipeline 2 results either continue execution of pipeline 1 or fail?
How during the execution of pipeline 1 can you trigger pipeline 2, wait for it to successfully finish or fail, and based on pipeline 2 results either continue execution of pipeline 1 or fail?
Trigger one pipeline after another, it will run your pipeline upon the successful completion of the triggering pipeline. We cannot use it to trigger pipeline 1 in the execution of pipeline 1.
As a workaround:
a. We can add task power shell and add script to call the REST API to queue the build.
$connectionToken="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$PipelineUrl = "https://dev.azure.com/{Org name}/{project name}/_apis/pipelines/{Pipeline ID}/runs?api-version=6.0-preview.1"
$body ="{
`"resources`":{
`"repositories`":{
`"self`":{`"refName`":`"refs/heads/master`"
}
}
}
}"
$Pipelines = Invoke-RestMethod -Uri $PipelineUrl -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
b. Add task power shell and enter the code Start-Sleep -Seconds 1000 to sleep the pipeline 1
c. Add the task power shell in the pipeline 1 to get the pipeline 2 build result via the REST API, and set the result as env variable.
d. Configure the condition in the next task to check the env variable value. If the value is succeeded, continue run the pipeline 1
You are probably looking for something like this.
# this is being defined in app-ci pipeline
resources:
pipelines:
- pipeline: securitylib # Name of the pipeline resource
source: security-lib-ci # Name of the pipeline referenced by the pipeline resource
trigger:
branches:
- releases/*
- master
its right there in the link, you have linked, but in the sibling section of the docs. I am surprised you missed it.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/pipeline-triggers?view=azure-devops&tabs=yaml
So here is my solution based on the suggestion above:
- task: PowerShell#2
displayName: Running second pipeline
inputs:
targetType: 'inline'
script: |
Write-Host "Triggering pipeline..."
$connectionToken= "$(PAT)"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$PipelineUrl = "https://dev.azure.com/YourOrganization/yourProject/_apis/pipelines/${{ parameters.pipelineId }}/runs?api-version=6.0-preview.1"
Write-Host "Pipeline url: $PipelineUrl"
$body ="{
`"resources`":{
`"repositories`":{
`"self`":{`"refName`":`"refs/heads/${{ parameters.branch }}`"
}
}
}
}"
$response = Invoke-RestMethod -Uri $PipelineUrl -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
Write-Host "Response: $response"
$BuildUrl = "https://dev.azure.com/YourOrganization/yourProject/_apis/build/builds/$($response.Id)?api-version=6.1-preview.6"
Write-Host $BuildUrl
$TimeoutAfter = New-TimeSpan -Minutes 15
$WaitBetweenPolling = New-TimeSpan -Seconds 10
$Timeout = (Get-Date).Add($TimeoutAfter)
do
{
$Response = Invoke-RestMethod -Uri $BuildUrl -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Write-Host $Response.status
Start-Sleep -Seconds $WaitBetweenPolling.Seconds
}
while ((($Response.status -eq "notStarted") -or ($Response.status -eq "inProgress")) -and ((Get-Date) -lt $Timeout))
if ($Response.result -ne "succeeded")
{
Write-Host $Response.result
exit 1
}
parameter for pipeline id: pipelineId: $(resources.pipeline.resource.pipelineId)
If you're ok with using extensions, the Trigger Build Task you can get in the marketplace should support all of your requirements.
It lets you trigger another pipeline, with an option to wait for it, and options about how to treat failures of that pipeline if you do wait. So you can use that to trigger a build, wait for it, and succeed / fail based on if the build succeeds / fails.

Resources