Passing dynamically sized object parameters to Azure DevOps Pipeline templates
The Problem
I have an Azure DevOps YAML template that does some deployment actions using PowerShell. This template is used multiple locations. The problem is that the PowerShell step within the template needs a variable number of environment variables, set from values stored in an Azure DevOps variable Group. The number of variables is not fixed because they depend on the underlying commands the PowerShell script is triggering to do the deployment.
Hence, the problem was how to pass the values of these variables to the template in a way that was easy to maintain and understand, as this is not something that is well documented.
The Solution
The solution, as you might expect if you have used YAML templates, is to use the object
type for the parameter in the template. This allows you to pass a single object to the template that contains all the values you need.
This can be seen in this simple example
parameters:
- name: envparams
type: object
default:
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Get-ChildItem -Path Env:
env: ${{ parameters.envparams }}
The question then becomes, how to you wire this up in the calling pipeline?
The answer is you pass a JSON block to the template. Just make sure you get the escaping correct, I have found this is the most common reason for a pipeline to fail to run.
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
# Link to the variable group
- group: ExpandTest
steps:
- template: base.yml
parameters:
# match the variable group values with name of the environment variables you wish to create
envparams: {
'MY-PARAM1': '$(MY-PARAM1)',
'MY-PARAM2': '$(MY-PARAM2)'
}
For the original version of this post see Richard Fennell's personal blog at Passing dynamically sized object parameters to Azure DevOps Pipeline templates