Using a YAML pipeline paramter in a PowerShell task is straight forward for types such as string. For example, if there is a YAML pipeline parameter named env of type string, we can read it in PowerShell task with $envName = '${{ parameters.env }}; without any issue. However, if the parameter is type of object we cannot read, the paramter the same way we do with string parameters. If we try to read object parameter named apps, $apps = '${{ parameters.apps}}; , there will be an YAML validation error staring the pipeline such as below.
/azure-pipelines.yml (Line: 57, Col: 23): Unable to convert from Array to String. Value: Array
Even if we try to use below it will be same issue.
[String[]]$apps = '${{ parameters.apps}};
[PSObject[]]$apps = '${{ parameters.apps}};
Let's explore the issueand solution in detail.
The issue in detail
Consider below two parameters defined in a YAML pipeline.
parameters:
- name: env
displayName: 'Select environment'
type: string
default: dev
values:
- dev
- qa
- prod
- name: apps
displayName: 'Apps to deploy'
type: object
default: [
'customer_api',
'invoice_api',
'order_api',
'payment_api',
'order_eventhandler',
'invoice_eventhandler',
'customer_eventhandler'
]
The parameter env is type of string and it can be used in a PowerShell task without any issue as shwon below,
- task: PowerShell@2
displayName: 'Read parameter 2'
inputs:
targetType: 'inline'
script: |
$envName = '${{ parameters.env }}';
Write-Host ($envName);
However, if we try to use the apps parameter, which is type of object we will get the error below, when starting the pipeline.
- task: PowerShell@2
displayName: 'Read parameter 2'
inputs:
targetType: 'inline'
script: |
$envName = '${{ parameters.env }}';
Write-Host ($envName);
$apps = '${{ parameters.apps}}';
The Solution
There are two ways to fix this issue. One is to use an env variable setup and join object type contents with a seperator such as ;. Then in PowereShell we can split it and obtain an array. This works fine for the parmeter apps we have used in this example.
- task: PowerShell@2
displayName: 'Read parameter 1'
env:
APP_NAMES: ${{ join(';', parameters.apps) }}
inputs:
targetType: 'inline'
script: |
$envName = '${{ parameters.env }}';
Write-Host ($envName);
$apps = $env:APP_NAMES -split ";"
foreach($app in $apps)
{
Write-Host ($app);
}
However, if the parameter is more complex object such as below the above solutioon will fail.
parameters:
- name: complexparam
type: object
default:
this_is:
a_complex: object
with:
- one
- two
To obtain a complex object paramter to a PSObject, we can use syntax below, in a PowerShell task.
$apps = '${{ convertToJson(parameters.apps) }}' | ConvertFrom-Json; converts complex YAML parameter to json representation and the convert it from json to PSObject, which we can use in PowerShell to read through the complex object.
- task: PowerShell@2
displayName: 'Read parameter 2'
inputs:
targetType: 'inline'
script: |
$envName = '${{ parameters.env }}';
Write-Host ($envName);
$apps = '${{ convertToJson(parameters.apps) }}' | ConvertFrom-Json;
foreach($app in $apps)
{
Write-Host ($app);
}
The full test pipline YAML code is as below.
parameters:
- name: env
displayName: 'Select environment'
type: string
default: dev
values:
- dev
- qa
- prod
- name: apps
displayName: 'Apps to deploy'
type: object
default: [
'customer_api',
'invoice_api',
'order_api',
'payment_api',
'order_eventhandler',
'invoice_eventhandler',
'customer_eventhandler'
]
trigger: none
stages:
- stage: YAML_Params
displayName: "YAML Params"
jobs:
- job: YAML_Params
displayName: YAML Params
pool:
vmImage: ubuntu-latest
steps:
- checkout: none
- task: PowerShell@2
displayName: 'Read parameter 1'
env:
APP_NAMES: ${{ join(';', parameters.apps) }}
inputs:
targetType: 'inline'
script: |
$envName = '${{ parameters.env }}';
Write-Host ($envName);
$apps = $env:APP_NAMES -split ";"
foreach($app in $apps)
{
Write-Host ($app);
}
- task: PowerShell@2
displayName: 'Read parameter 2'
inputs:
targetType: 'inline'
script: |
$envName = '${{ parameters.env }}';
Write-Host ($envName);
$apps = '${{ convertToJson(parameters.apps) }}' | ConvertFrom-Json;
foreach($app in $apps)
{
Write-Host ($app);
}
No comments:
Post a Comment