1
votes

For a release pipeline I want to get the consumed pipeline artifacts from a build artifact via REST API (or a task).

Background: I have a release pipeline in azure devops that consumes one main artifact, the setup. The setup packs several binaries in a certain version inside. In the release pipeline I want to find the system tests that fit to the binaries that were packed in the setup. These system tests are published as artifact together with the binaries.

I have the following piplines, that are triggered one after another:

  1. BinaryPipeline -> publish artifacts: "binaries", "system tests"
  2. SetupPipeline -> consumes artifact "binaries" from BinaryPipeline, publish artifacts: "setup",
  3. Release pipeline -> consumes artifact "setup" from setup pipline, consumes "system tests" from BinaryPipeline

Problem: The release pipeline should consume the artifact "system tests" from the same build (of BinaryPipeline) that was consumed to build the setup.

I tried to solve the problem with the REST API, but

https://dev.azure.com/<company>/<project>/_apis/build/builds/<buildid>/artifacts

returns only the produced artifacts, not the consumed.

I see the following workarounds, still I don't like them:

  1. Publish a text file that contains version information -> Best workaround. I don't like that I have to rely on a special file in artifacts.
  2. Set build properties (although I didn't find out how to set the properties during build) -> Didn't find out how
  3. Republish the system tests in my setup build -> Bad pactrice to copy artifacts
  4. Parse the logs -> Bad because I've to rely on title names of tasks

How can I get the consumed pipeline artifacts from a build via REST API in Azure Devops?

2
My solution for now: Trigger the release build from the setup pipeline with the correct artifact combination in the REST request.BlackTuareg
You may add a reply and Accept it as an Answer, this can be beneficial to other community members reading this thread.Cece Dong - MSFT

2 Answers

1
votes

After getting (private) help from Visual Studio Community on my request Trigger release with defined artifacts it turns out that there is no built-in and comfortable way to get the consumed artifacts. Solution 4) (see above) was one proposal from the VSCommunity.

My solution I have now in production: On the publishing build (SetupPipeline):

  1. Create BuildInfo.XML file with information on the consumed builds

    [xml]$Doc = New-Object System.Xml.XmlDocument
    $dec = $Doc.CreateXmlDeclaration("1.0","UTF-8",$null)
    $doc.AppendChild($dec)
    $root = $doc.CreateNode("element","ConsumedBuilds",$null)
    $build = $doc.CreateNode("element", "Build", $null)
    $build.SetAttribute("BuildVersion", "$(RESOURCES.PIPELINE.build.RUNNAME)")
    $build.SetAttribute("BuildId", "$(RESOURCES.PIPELINE.build.RUNID)")
    $root.AppendChild($build)
    $Doc.AppendChild($root)
    $doc.Save("$BuildInfoXml")
    
  2. Publish BuildInfo.XML as separate artifact (so you can download it separately)

On the release pipeline:

  • Download artifact with BuildInfo.xml

  • Parse XML in powershell

    $ovf = New-Object System.XML.XMLDocument
    $ovf.Load("$($BuildInfoXmlPath.FullName)")
    $build= $ovf.ConsumedBuilds.Build | Where { ... }
    
  • Download artifact version via REST and powershell (because the Download Pipeline Artifact tasks cannot be parameterized)

    $artifactUri = ("https://dev.azure.com/{organization}/{0}/_apis/build/builds/{1}/artifacts?artifactName={2}&api-version=4.1" -f $azureProjectName, $buildId, $artifactName)
    $artifact = Invoke-RestMethod -Uri "$artifactUri"  -Method get -Headers $AzureDevOpsAuthenicationHeader -ContentType 'application/zip' 
    $downloadUrl = "$($artifact.resource.downloadUrl)"
    $wc = New-Object System.Net.WebClient
    $wc.Headers.Add('Authorization','Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($accessToken)")) )
    $file = $wc.DownloadFile("$downloadUrl", $outputFile)
    

Since the latter is not very transparent, because the downloaded artifact doesn't show up as consumed in the release pipeline (it was downloaded by a powershell script):

  • Create a trigger Pipeline that is triggered by SetupPipeline, waits a moment and then queues a new release in the ReleasePipeline with the artifacts from the XML. Note: you can't trigger a release pipeline from a build that is not suceeded and (complelty) finished.

Here some powershell code to trigger the release pipeline:

  $AzureDevOpsAuthenicationHeader = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($accessToken)")) }
  $createReleaseBody = 
  @"
  {
      "definitionId": $(ReleasePipelineDefinitionId),
      "description": "...",
      "artifacts": [
      {
            "alias": "buildName",
            "instanceReference": {
            "id": "$($build.BuildId)",
            "name": "$($build.BuildVersion)"
            }
        },
      {
         ...
      }
      ],
     "isDraft": false,
     "reason": "none",
     "manualEnvironments": null
  }
  "@
  Invoke-RestMethod -Uri "https://vsrm.dev.azure.com/{org}/{project}/_apis/release/releases?api-version=5.0" -Method post -Headers $AzureDevOpsAuthenicationHeader -Body $createReleaseBody -ContentType 'application/json' 
0
votes

When you download artifact using DownloadBuildArtifacts task, you could specify which version of the build to download:

enter image description here