Sometimes when building Azure Pipelines in YAML you want to create a template with optional parameters and then test those parameters have a value.
For a string value this is straight forward e.g.
parameters:
- name: project
type: string
default: ''
${{ if eq(parameters.project, '') }}:
or
${{ if ne(parameters.project, '') }}:
When it comes to objects or arrays, creating the optional parameter is still straight forward e.g.
parameters:
- name: projects
type: object
default: []
- name: envs
type: object
default: {}
However, testing if they are empty is not quite so simple as you cannot just do an equality test like with string parameters e.g.
${{ if eq(parameters.envs, {}) }}:
or
${{ if ne(parameters.envs, {}) }}:
${{ if eq(parameters.projects, []) }}:
or
${{ if ne(parameters.projects, []) }}:
To get around this we can do a bit of trickery using convertToJson to provide a string representation of the object or array e.g.
${{ if eq(convertToJson(parameters.envs), '{}') }}:
or
${{ if ne(convertToJson(parameters.envs), '{}') }}:
${{ if eq(convertToJson(parameters.projects), '[]') }}:
or
${{ if ne(convertToJson(parameters.projects), '[]') }}:
Now this technique all sounds good but what about a real world example where it might be useful
So, I have a shared .NET build template (build-code.yml) and for some projects the dotnet test run requires some environment variables. We can pass the required environment variables in using the normal YAML object syntax e.g.
- template: build-code.yml
parameters:
version: '6.0.x'
envs:
appEndpoint: $(appEndpoint)
databaseEndpoint: $(databaseEndpoint)
apiEndpoint: $(apiEndpoint)
These are then used in build-code.yml template e.g.
parameters:
- name: version
type: string
default: ''
- name: artifactName
type: string
default: 'code'
- name: publishWebProjects
type: boolean
default: true
- name: zipAfterPublish
type: boolean
default: false
- name: envs
type: object
default: {}
variables:
buildConfiguration: 'Release'
steps:
- task: UseDotNet@2
displayName: 'Use .NET version'
inputs:
packageType: 'sdk'
${{ if ne(parameters.version, '') }}:
version: '${{ parameters.version }}'
${{ if eq(parameters.version, '') }}:
useGlobalJson: true
- task: DotNetCoreCLI@2
displayName: 'Restore Packages'
inputs:
command: restore
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'Build Projects'
inputs:
command: 'build'
projects: '**/*.csproj'
arguments: '--no-restore --configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
displayName: 'Run Tests'
inputs:
command: test
projects: '**/*Tests.csproj'
arguments: '--no-restore --no-build --configuration $(buildConfiguration)'
${{ if ne(convertToJson(parameters.envs), '{}') }}:
env:
${{ parameters.envs }}
If the environment variables are not needed for a project then they can be simply omitted e.g.
- template: build-code.yml
parameters:
version: '6.0.x'
I don’t like to use too many optional parts in a template as it can get very complex but for this usage it works quite well