1
votes

Am triggering a build Pipeline from a release Pipeline as a first task through an API call and that doesn't have any Issue.

Second Task - Pipeline needs to wait Until the triggered Pipeline from the first task is completed and then go to Third Task. How do i achieve It ?

I have tried below in a powershell task to get the Build ID from the running pipeline and tried to wait through a loop, but am unable to get the Build Id

First Task to trigger a Build Pipeline

curl -L -X POST 'https://dev.azure.com/Org/project/_apis/build/builds?definitionId-1549&api-version=6.1-preview.6' -H 'Authorization: $(ADO_BASIC_AUTH)' -H 'Content-Type: application/json' --data '{"definition": {"id": 1549}}'

Second Task as you Suggested

   $B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$(ADO_BASIC_AUTH)"))

$header = @{ Authorization = "Basic $B64Pat" }


$continueCurrent = $true
$uriGetActiveBuilds1 = "https://dev.azure.com/org/project/_apis/build/builds?definitions=1549&statusFilter=inProgress,notStarted&api-version=5.1"
    
do
{
    $continueCurrent = $true

    $resultStatus = Invoke-RestMethod -Uri $uriGetActiveBuilds1 -Method Get -ContentType "application/json" -Headers $header
    

    if ($resultStatus.count -gt 0)
    {
        $continueCurrent = $false
        Write-Host " . "
        Start-Sleep -s 10
    }

}while($continueCurrent -eq $false)

Write-Host "Continue task"

The Second keeps waiting even If the Build Pipeline triggered from the First Task is completed

Output of my Pipeline

Output with empty Build ID

3

3 Answers

1
votes

How do I get Build ID of an In progress Pipeline in Azure DevOps

The idea to solve this request can be:

  1. Add a task to get the latest build id of the build pipeline before the first task of the release pipeline (triggering a build pipeline)
  2. Then get latest Id of the build pipeline again in the second task after executing the first task.
  3. If it is the same as the previous one, it means that the build pipeline has not been running. Wait for 30 seconds.
  4. If the ID is different, it means that the newly triggered build pipeline has started running. We only need to determine whether the status of the latest pipeline is complete

The REST API scripts to get the latest build id before your first task:

$connectionToken="$(PAT)"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))

$BuildPipelineUrl = "https://dev.azure.com/<YourOrganization>/<YourProject>/_apis/build/builds?definitions=173&`$top=1&api-version=6.0" 

Write-Host "URL: $BuildPipelineUrl"

$BuildPipelineInfo = (Invoke-RestMethod -Uri $BuildPipelineUrl -Method Get -UseDefaultCredential -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}) 


$LatestBuldId = $BuildPipelineInfo.value.id

Write-Host "LatestBuldId = $LatestBuldId"

Write-Host "##vso[task.setvariable variable=OldBuldPipelineId]$LatestBuldId"

The REST API scripts to get the latest build id and check the build status after your second task:

    $connectionToken = "$(PAT)"
    $base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
    $success = $false
    $count = 0
do{
    try{
    $Secondurl = "https://dev.azure.com/<YourOrganization>/<YourProject>/_apis/build/builds?definitions=173&`$top=1&api-version=6.0"
    $NewBuildPipelineInfo = Invoke-RestMethod -Method Get -ContentType application/json -Uri $Secondurl -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}
  
    $NewBuildPipelineId = $NewBuildPipelineInfo.value.id

    $NewBuildPipelinestatus = $NewBuildPipelineInfo.value.status

    write-output $NewBuildPipelineId | ConvertTo-Json -Depth 100

    write-output $NewBuildPipelinestatus | ConvertTo-Json -Depth 100

    
 
       if($NewBuildPipelineId -eq '$(OldBuldPipelineId)') {           
            Write-output "Wait for new piepine trigger in 30 seconds"
            Start-sleep -Seconds 30         
      } else {           
            Write-Host "New Pipeline was triggered"
            if($NewBuildPipelinestatus -ne '"completed"') {
            Write-output "wait forpipeline complete,Next attempt in 30 seconds"
            Start-sleep -Seconds 30
            }
            else{
            write-output "Pipeline complete"
            $success = $true     
            }     
      }


    }
    catch{
        Write-output "catch - Next attempt in 30 seconds"
        write-output "1"
        Start-sleep -Seconds 30
    }
   
    $count++
   
}until($count -eq 2000 -or $success)
if(-not($success)){exit}

The test result:

enter image description here

Update:

enter image description here

1
votes

You can use another way. Add to your release a new variable:

enter image description here

Then use it in the script to define the build Id and get the status only of the queued build.

Run the build and pass build id:

$user = ""
$token = "<pat>"

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

$orgUrl = "https://dev.azure.com/<org>"
$teamProject = "<team_project>"
$buildDefId = <build_definition_id>

$body = '{"definition":{"id":<dev_id>}}' -replace "<dev_id>", $buildDefId

$uriRunBuild = "$orgUrl/$teamProject/_apis/build/builds?api-version=5.1"

    
$resultQueue = Invoke-RestMethod -Uri $uriRunBuild -Method Post -ContentType "application/json" -Body $body -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$buildId = $resultQueue.Id

Write-Host "Build Id: $buildId"
Write-Host "##vso[task.setvariable variable=Custom.BuildId]$buildId"

Then use the build id to get the build status:

$user = ""
$token = "<pat>"

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

$orgUrl = "https://dev.azure.com/<org>"
$teamProject = "<team_project>"

$uriGetBuild = "$orgUrl/$teamProject/_apis/build/builds/$(Custom.BuildId)?api-version=5.1"

$uriGetBuild

$buildStatus = ""
    
do
{
    $buildResult = Invoke-RestMethod -Uri $uriGetBuild -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

    $buildStatus = $buildResult.status

    if ($buildStatus -ne "completed")
    {
        Write-Host " . "
        Start-Sleep -s 2
    }

}while($buildStatus -ne "completed")

Write-Host "Continue task"
0
votes

One way

What do you see when you call Write-Host $result.latestBuild.id?

The Other way

You can add the status filter = inProgress

Small example:

First task. Run build:

$user = ""
$token = "<pat>"

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

$orgUrl = "https://dev.azure.com/<org>"
$teamProject = "<team_project>"
$buildDefId = <build_definition_id>

$body = '{"definition":{"id":<dev_id>}}' -replace "<dev_id>", $buildDefId

$continueCurrent = $true
$uriRunBuild = "$orgUrl/$teamProject/_apis/build/builds?api-version=5.1"

    
$resultQueue = Invoke-RestMethod -Uri $uriRunBuild -Method Post -ContentType "application/json" -Body $body -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

Write-Host "Build Id" $resultQueue.Id

Second task. Wait for build of some build definition

$user = ""
$token = "<pat>"

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

$orgUrl = "https://dev.azure.com/<org>"
$teamProject = "<project>"
$buildDefId = <build_definition_id>

$continueCurrent = $true
$uriGetActiveBuilds = "$orgUrl/$teamProject/_apis/build/builds?definitions=$buildDefId&statusFilter=inProgress,notStarted&api-version=5.1"

    
do
{
    $continueCurrent = $true

    $resultStatus = Invoke-RestMethod -Uri $uriGetActiveBuilds -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

    #$resultStatus.value

    if ($resultStatus.count -gt 0)
    {
        $continueCurrent = $false
        Write-Host " . "
        Start-Sleep -s 2
    }

}while($continueCurrent -eq $false)

Write-Host "Continue task"