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.
Related
Hi There I have been asked to modify all current CI yml pipelines to fail if the C# API or WEB app has any warning, also it needs to be in its own stage in the process.
I have been looking on the net and can't find any code please can someone help with the code needed
thanks
There are two options for your reference.
1.You could add a PowerShell task in the stage, and then run the Rest API: Timeline - Get to traverse the warning messages in the previous task. And use logging commands to control the results.
PowerShell script:
$token = "PAT"
$url="https://dev.azure.com/{OrgName}/{ProjName}/_apis/build/builds/$(build.buildid)/timeline?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$count = 0
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach( $issues in $response.records.issues )
{
if($issues.type -eq "warning")
{
echo $issues.Message
$count ++
}
}
echo $count
if($count -ne 0 )
{
Write-Host "##vso[task.complete result=Failed;]"
}
Pipeline Output:
2.Using Extension task: Build Quality Checks is another option.
Add this task to your target stage to check the warnings.
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:
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
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:
The code below is an API call that will run an azure pipeline but the only problem I am having is I am unable to run it on custom branches and I have tried az commands but with az commands, you can't pass though parameters. My goal is basically I have a pipeline A and I want to run Pipeline B which isn't mind so I can't edit it but Pipeline B takes in a parameter called Tag and I want to pass that though from Pineline A but struggling to do so.
$token = -join("$Username", ":", "$PAT")
$headers = #{
Authorization = "Basic "+ [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($token))
'Content-Type' = "application/json"
}
$uri = "https://dev.azure.com/{$Company}/{$Team}/_apis/pipelines/{$ProjectID}/runs/?api-version=6.0-preview.1"
$pipelineBody=#{
resources=#{
repositories=#{
self=#{
ref="$Branch"
}
}
}
templateParameters=#{
Tag="$Tag"
}
} | ConvertTo-Json
$result = Invoke-WebRequest -Uri $uri `
-Headers $headers `
-Body "$pipelineBody" `
-Method Post `
#-SkipCertificateCheck `
#-SkipHttpErrorCheck `
#-ErrorAction Stop
if($result.StatusCode -ne "200")
{
throw $result
}
return ($result.Content | ConvertFrom-Json).url
You can closely (not directly what you want) achieve this by following below steps:
Create single pipeline for Pipeline A (Stage 1) and Pipeline B(Stage 2).
Add a dependency of Pipeline A(Stage 1) on Pipeline B(Stage 2) that it runs only when Pipeline A succeeds.
Use Powershell script in Stage 1 to set a pipeline variable to a value you trying to set for Stage 2 - using out variable in Powershell script task of ADO.
Consume the pipeline variable set above in the desired step (of Pipeline B).