Azure DevOps Pipeline Blueprints - Exploring the info-version.yml template


Posted by Willy-Peter Schaub on Fri 24 January 2025

Drilling Deeper: A Closer Look at the Blueprint info-version.yml Template.

We continue our deep dive into the details of our AzureDevOps.Automation.Pipeline.Templates.v2 open source blueprint repo. Today we are going to explore the templates/utilities/info-version.yml template, designed to capture and present detailed information about the pipeline instance, facilitating security reviews and enabling future analysis.

drilling

Also refer to:


Today's topic - info-version.yml

Today we peek into the templates/utilities/info-version.yml template which has one purpose - capture information about the pipeline instance for future reference.

# --------------------------------------------------------------------------
# info-version Template
# --------------------------------------------------------------------------
# See https://aka.ms/yaml for Azure DevOps Pipeline documentation
# 
# --------------------------------------------------------------------------

parameters:
# mandatory parameters
- name:     modeElite
  type:     boolean
- name:     applicationBlueprint
  type:     string
- name:     applicationType
  type:     string
# default parameters
- name:     vGuid
  type:     string
  default:  '__TODO_ADD_UNIQUE_GUID__HERE__'
- name:     vVersion
  type:     string
  default:  '2.0'

steps:
    - script: echo "${{parameters.modeElite}}:${{parameters.applicationBlueprint}}:${{parameters.applicationType}}:${{parameters.vGuid}}:${{parameters.vVersion}}
      name:         BootstrapInfo
      displayName:  Bootstrap Info
    - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
          Write-Host "##vso[task.setvariable variable=bootStrapModeElite;isOutput=true]${{parameters.modeElite}}"
          Write-Host "##vso[task.setvariable variable=bootStrapBlueprint;isOutput=true]${{parameters.applicationBlueprint}}"
          Write-Host "##vso[task.setvariable variable=bootStrapType;isOutput=true]${{parameters.applicationType}}"
          Write-Host "##vso[task.setvariable variable=bootStrapGuid;isOutput=true]${{parameters.vGuid}}"
          Write-Host "##vso[task.setvariable variable=bootStrapVersion;isOutput=true]${{parameters.vVersion}}"
        failOnStderr: true
        pwsh: true
      name:         BootstrapVars
      displayName:  Bootstrap Vars

# --------------------------------------------------------------------------
# Generate pipeline info and save it to a JSON file
# --------------------------------------------------------------------------
    - task: PowerShell@2
      displayName:  Bootstrap generate pipeline info
      inputs:
        targetType: 'inline'
        pwsh: true
        script: |
          $variablesData = [PSCustomObject]@{
              bootStrapModeElite = "${{parameters.modeElite}}"
              bootStrapBlueprint = "${{parameters.applicationBlueprint}}"
              bootStrapType = "${{parameters.applicationType}}"
              bootStrapGuid = "${{parameters.vGuid}}"
              bootStrapVersion = "${{parameters.vVersion}}"
          }

          $json = $variablesData | ConvertTo-Json
          $jsonFilePath = "$(Agent.TempDirectory)/pipe-info.json"
          $json | Out-File -FilePath $jsonFilePath
          Write-Host "JSON file saved to $jsonFilePath"

    # Publish pipeline info
    - task: PublishBuildArtifacts@1
      displayName: Bootstrap publish pipeline info
      inputs:
        PathtoPublish: "$(Agent.TempDirectory)/pipe-info.json"
        ArtifactName: 'pipe-info'

Drill-down

The second step is a PowerShell command sets five variables in an Azure DevOps pipeline to make them available for subsequent tasks.

    - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
          Write-Host "##vso[task.setvariable variable=bootStrapModeElite;isOutput=true]${{parameters.modeElite}}"
          Write-Host "##vso[task.setvariable variable=bootStrapBlueprint;isOutput=true]${{parameters.applicationBlueprint}}"
          Write-Host "##vso[task.setvariable variable=bootStrapType;isOutput=true]${{parameters.applicationType}}"
          Write-Host "##vso[task.setvariable variable=bootStrapGuid;isOutput=true]${{parameters.vGuid}}"
          Write-Host "##vso[task.setvariable variable=bootStrapVersion;isOutput=true]${{parameters.vVersion}}"
        failOnStderr: true
        pwsh: true
      name:         BootstrapVars
      displayName:  Bootstrap Vars

For example:

  • ##vso[task.setvariable variable=bootStrapModeElite;isOutput=true] is an Azure DevOps-specific logging command to set a variable that can be accessed by other tasks in the pipeline.
  • bootStrapModeElite is the name of the variable being set. In this case it is the variable that defines whether we are serious about quality (true) or noe (false).
  • isOutput=true makes the variable available as an output variable for other pipeline jobs.
  • parameters.modeElite is a reference to a parameter that is passed around the templates.

alert

Refer to Gotchas when sharing variables with Azure DevOps stages and jobs if you are planning to share the variables amongst jobs and stages.

While these variables work seamlessly for reuse within YAML-based pipelines or across different jobs, we encountered an issue with our classic Azure Pipelines, which consist of a YAML-based continuous integration (CI) pipeline and an older, classic release pipeline for continuous delivery. The variables did not flow between the new and legacy environments, and modifying thousands of legacy release pipelines was simply not feasible.

This brings us to the second half of the template, which creates a json file with the variables and their values, and publishes them to the Azure Pipeline artifacts. The Powershell task runs an inline script that creates a PowerShell custom object $variablesData with properties that are populated using template parameters.

The scripts last four steps performs the following:

  • Converts the $variablesData object to JSON format.
  • Defines the file path for the JSON file in the agent's temporary directory.
  • Writes the JSON content to the specified file.
  • Outputs a message indicating the file path where the JSON file was saved.
    - task: PowerShell@2
      displayName:  Bootstrap generate pipeline info
      inputs:
        targetType: 'inline'
        pwsh: true
        script: |
          $variablesData = [PSCustomObject]@{
              bootStrapModeElite = "${{parameters.modeElite}}"
              bootStrapBlueprint = "${{parameters.applicationBlueprint}}"
              bootStrapType = "${{parameters.applicationType}}"
              bootStrapGuid = "${{parameters.vGuid}}"
              bootStrapVersion = "${{parameters.vVersion}}"
          }

          $json = $variablesData | ConvertTo-Json
          $jsonFilePath = "$(Agent.TempDirectory)/pipe-info.json"
          $json | Out-File -FilePath $jsonFilePath
          Write-Host "JSON file saved to $jsonFilePath"

Lastly, the template publishes the pipe-info.json file located in the agent's temporary directory as a build artifact named pipe-info. Going forward, our quality and security automation, as well as the 2AM incident root cause analysis, can find the pipeline information such as how serious we were about quality, the application-type blueprints used, the suggested application type, and the blueprint template version.

    # Publish pipeline info
    - task: PublishBuildArtifacts@1
      displayName: Bootstrap publish pipeline info
      inputs:
        PathtoPublish: "$(Agent.TempDirectory)/pipe-info.json"
        ArtifactName: 'pipe-info'

That is it for today!


Questions

For my team

  • Q1: What other information should we save in the pipe-info artifact?

For you

  • Q2: What other information is important for your CI/CD pipelines to track quality and governance?

Any questions or suggested improvements?