I have a main pipeline which is downloading pipeline artifact from a specific pipeline.
- task: DownloadPipelineArtifact@2
inputs:
source: specific
project: ABC
pipeline: 1
runVersion: latestFromBranch
runBranch: $(Build.SourceBranch)
artifact: artifact-abc
targetPath: $(Pipeline.Workspace)
I need to do a prerequisite check if artifact exists for the specific pipeline for the branch if not then run the specific pipeline. How to achieve this? Can we make use of a python script to invoke REST API to check and trigger the pipeline run?
You could use the Builds - List API to retrieve a list of builds, then loop through those results and check if the artifact exists.
- task: PowerShell@2
displayName: Locate existing artifact
inputs:
targetType: inline
script: |
$project = "ABC"
$pipeline = "1"
$branch = "$(Build.SourceBranch)"
$artifact = "artifact-abc"
$baseUrl = "$(System.CollectionUri)/$project"
$headers = @{ Authorization = "Bearer $(System.AccessToken)" }
$url = $baseUrl + `
"/_apis/build/builds?definitions=$pipeline" + `
"&branchName=$branch" + `
"&resultFilter=succeeded" + `
"&statusFilter=completed" + `
"&queryOrder=queueTimeDescending" + `
"&api-version=7.1"
# obtain list of build candidates
$result = Invoke-RestMethod `
-Method Get `
-Uri $url `
-Headers $headers `
-UseBasicParsing
# loop through builds to find artifact
$builds = $result.value
if $(builds) {
$builds | ForEach-Object {
$buildId = $_.id
$artifactUrl = $baseUrl + `
"_apis/build/builds/$pipeline/artifacts" + `
"?artifactName=$artifact" + `
"&api-version=7.1"
# check if artifact exists
try {
$result = Invoke-RestMethod `
-Method Get `
-Uri $artifactUrl `
-Headers $headers `
-UseBasicParsing
if ($result.name -eq $artifact) {
# artifact found!
Write-Output "##vso[task.setvariable variable=artifactExists]true"
break
}
}
catch {}
}
}
Write-Host "Artifact not found."
Then you can use the Pipeline - Run API to queue the pipeline. You'd then have to query the pipeline using Runs - Get until it's completed. This isn't an ideal, because you're using your build agent to monitor another build. If you only have a single build agent, this obviously won't work.
- task: PowerShell@2
displayName: Invoke build
condition: ne(variables['artifactExists'], 'true')
inputs:
targetType: inline
script: |
$branch = "$(Build.SourceBranch)"
$project = "ABC"
$pipeline = "1"
$baseUrl = "$(System.CollectionUri)/$project"
$headers = @{ Authorization = "Bearer $(System.AccessToken)" }
$invokeUrl = $baseUrl + `
"/_apis/pipelines/$pipeline/runs" + `
"?api-version=7.1"
$invokeBody = @{
resources = @{
repositories = @{
self = @{
refName = $branch
}
}
}
} | ConvertTo-Json -Depth 10
# queue the build
$result = Invoke-RestMethod `
-Method POST `
-Body $invokeBody `
-Uri $invokeUrl `
-Headers $headers
$runId = $result.id
# Monitor the build
$monitorUrl = $baseUrl + `
"/_apis/pipelines/$pipeline/runs/$runId?api-version=7.1"
$done = false
while (!$done) {
Start-Delay -Seconds 60
$result = Invoke-RestMethod `
-Method Get `
-Uri $monitorUrl `
-Headers $headers
$done = $result.state -eq "completed"
}