How to pass a Pipeline variable as boolean to a template? - azure-devops

I am trying to pass a Pipeline variable (enable_datasync_job) that I have defined using the UI:
to a template that is used within my main pipeline azure-pipelines.yml:
name: MyRepo.Deployment.$(date:yy)$(DayOfYear)$(rev:.r)
...
jobs:
- job:
steps:
...
- template: azure-pipelines.yml#Common-YAML
parameters:
...
enable_datasync_job: $(enable_datasync_job)
The Common-YAML template defines that variable as boolean:
parameters:
...
- name: enable_datasync_job
type: boolean
default: false
When I try to run my main pipeline, it currently breaks as it completes that I am not passing a boolean value to my template
I know that all pipeline variables as of type string. How do I convert that string to a boolean so that my template accepts it?

If you define the parameter that is in the azure-pipelines.yml also as boolean you will get a checkbox (boolean) instead of inputbox (string):
You should be able to pass this along the Common-YAML.
Example code
The azure-pipelines.yml:
trigger:
- main
pool:
vmImage: ubuntu-latest
parameters:
- name: enable_datasync_job
type: boolean
default: false
extends:
template: boolean.yml
parameters:
enable_datasync_job: ${{ parameters.enable_datasync_job }}
The azure-pipelines.yml, without extends:
trigger:
- main
pool:
vmImage: ubuntu-latest
parameters:
- name: enable_datasync_job
type: boolean
default: false
steps:
- template: boolean.yml
parameters:
enable_datasync_job: ${{ parameters.enable_datasync_job }}
The boolean.yml (Common-YAML):
parameters:
- name: enable_datasync_job
type: boolean
default: false
steps:
- script: |
echo the value is ${{ parameters.enable_datasync_job }}
The result

Related

Evaluate an expression at template expansion time

I have an azure pipeline template that takes parameters, and I'd like to set one of the parameters based on an expression:
- template: templates/mytemplate.yml
parameters:
TestBackCompat: eq('${{ parameters.CIBuildId }}', 'MasterLatestBuildId')
CreateNupkg: ${{ parameters.CreateNupkg }}
As written, it doesn't work, because the expression isn't evaluated until runtime.
Is there a way to evaluate the expression at compile-time? Simple variable replacement (e.g., the usage of CreateNuPkg in the script above) works OK.
From this official document:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#template-expressions
Template expressions can expand template parameters, and also
variables. You can use parameters to influence how a template is
expanded. The object works like the variables object in an expression.
How the variable object works:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#runtime-expression-syntax
So the usage in your situation should be like this:
give_parameters.yml
trigger:
- none
parameters:
- name: CIBuildId
type: string
default: 'MasterLatestBuildId'
extends:
template: using_parameters.yml
parameters:
TestBackCompat: ${{ eq(parameters.CIBuildId, 'MasterLatestBuildId')}}
using_parameters.yml
parameters:
- name: CIBuildId
type: string
default: 'x'
- name: TestBackCompat
type: string
default: 'x'
variables:
- name: test1
value: ${{ parameters.TestBackCompat}}
- name: test2
value: ${{ parameters.CIBuildId}}
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host $(test1)
Write-Host $(test2)
Write-Host ${{ parameters.TestBackCompat}}
Result:

Azure Pipelines YAML parameter inside parameter name (dynamic parameter name)

I have a YAML template with parameters:
- name: Deploy_Test1
type: boolean
default: false
- name: Tests
type: object
default:
- "Test1"
- "Test2"
After that I iterate the Tests with each:
- ${{ each test in parameters.Tests}}:
Inside the each I can get the test value with ${{test}}.
I want to use the parameter Deploy_Test1 but dynamically, for example:
echo ${{ parameters.Deploy_${{test}} }}
In the above syntax I get an error that is invalid.
Is there is a way or a workaround to do it?
You need to use two loops here and check if you find your key.
parameters:
- name: Deploy_Test1
type: boolean
default: false
- name: Tests
type: object
default:
- "Test1"
- "Test2"
trigger: none
pool:
vmImage: ubuntu-latest
steps:
- ${{ each test in parameters.Tests}}:
- ${{ each parameter in parameters }}:
- ${{ if eq(parameter.key, format('Deploy_{0}', test)) }}:
- script: echo ${{ parameter.value }}
And then you will get:

Dynamic parameters/variables does not work for deployment job in checkout step in template but work directly in pipeline

The dynamic variables with the checkout step do not work with the template.
The same works without a template.
#- checkout: git://MY_PROJ/MY_REPO#refs/tags/${{parameters.tag_name}} ## DOES NOT WORK
Getting below error while running pipeline:
"ERROR: An item with the same key has already been added"
Working:
my_pipeline.yml without template works
parameters:
- name: RELEASE_TAG
displayName: Enter The Master Release Tag Name Example 1.0.0-RELEASE
default: 1.0.0-RELEASE
type: string
trigger:
- none
variables:
db_resource_path: '$(System.DefaultWorkingDirectory)/resources/db'
pipeline_environment_name: 'PROD_ENV'
db_env_name: 'prod'
stages:
- stage: "PROD_DB_DEPLOYMENT"
displayName: "PROD DB Deployment"
pool:
name: $(param.agent.pool.name)
variables:
- group: PROD_VG
jobs:
- job:
steps:
- script: |
echo param release tag: ${{parameters.RELEASE_TAG}}
- deployment: Deploy
environment: PROD_ENV
strategy:
runOnce:
deploy:
steps:
- checkout: git://MY_PROJ/MY_REPO#refs/tags/${{parameters.RELEASE_TAG}} ## WORKS
#- checkout: git://MY_PROJ/MY_REPO#refs/tags/${{variables.tag_name}} ## WORKS WITH VAR ALSO
Not Working:
Gives ERROR: An item with the same key has already been added.
my azure-pipelines.yml is:
parameters:
- name: RELEASE_TAG
displayName: Enter The Master Release Tag Name Example 1.0.0-RELEASE
default: 1.0.0-RELEASE
type: string
resources:
repositories:
- repository: templates
type: git
name: MY_PROJECT/MY_TEMPLATE_REPO
trigger:
- none
variables:
tagName: '${{ parameters.RELEASE_TAG }}'
stages:
- stage: "PROD_DB_DEPLOYMENT"
displayName: "PROD DB Deployment"
variables:
- group: PROD_VG
jobs:
- template: my_template.yml#templates
parameters:
tag_name: $(tagName)
db_env_name: 'prod'
agent_pool_name: $(param.agent.pool.name)
db_resource_path: $(System.DefaultWorkingDirectory)/resources/db
pipeline_environment_name: PROD_ENV
is_release: 'true'
My Template is:
parameters:
- name: 'agent_pool_name'
type: string
- name: 'db_resource_path'
type: string
- name: 'pipeline_environment_name'
type: string
- name: 'db_env_name'
type: string
- name: 'is_release'
type: string
default: 'false'
- name: 'tag_name'
type: string
default: '1.0.0-RELEASE'
jobs:
- job:
pool:
name: ${{parameters.agent_pool_name}}
steps:
- script: |
echo param tag_name: ${{parameters.tag_name}}
echo var tag_name: $(tagName)
- deployment: Deploy
pool:
name: ${{parameters.agent_pool_name}}
environment: ${{parameters.pipeline_environment_name}}
strategy:
runOnce:
deploy:
steps:
- checkout: self
- ${{ if eq(parameters.is_release, true) }}:
#- checkout: git://MY_PROJ/MY_REPO#refs/tags/1.0.0-RELEASE ## WORKS
#- checkout: git://MY_PROJ/MY_REPO#refs/tags/$(tag_name) ## DOES NOT WORK
#- checkout: git://MY_PROJ/MY_REPO#refs/tags/${{parameters.tag_name}} ## DOES NOT WORK
Tried below variable option also but get error:Unexpected value 'variables'
Any suggestion, please.
This is due to that you passed $(var) as parameters of the template.
You can pass ${{variables.tagName}} instead.
checked on my side screenshot
In a pipeline, template expression variables (${{ variables.var }}) get processed at compile time, before runtime starts. Macro syntax variables ($(var)) get processed during runtime before a task runs.
Because templates are expanded before the pipeline execution gets planned, so you cannot pass $(var) as parameter to the template.
Please check official doc for the variable syntax.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#understand-variable-syntax
Edit: for error "Unexpected value 'variables'":
Move variables to stage scope: my yaml here
My template here

azure devOps yml pipeline: pass Boolean value to task prisma-cloud-compute-scan#2 written in template

I want to send Boolean value to task 'prisma-cloud-compute-scan#2' written in a template file.
It always gives below error.
Error: The 'prisma_continue_on_error' parameter value '$(prismaContinueOnError)' is not a valid Boolean.
Main pipeline abc.yml
resources:
repositories:
- repository: templates
type: git
name: my_projects/my-build-templates
ref: refs/heads/features/add-build-template
variables:
name: prismaContinueOnError
value: false
isMainBranch: $[eq(variables['Build.SourceBranch'], 'refs/heads/master')]
stages:
- stage: "Build"
displayName: Build
jobs:
- template: my_build_stage/my_template.yml#templates
parameters:
prisma_continue_on_error: $(prismaContinueOnError)
Template my_template.yml
parameters:
- name: prisma_continue_on_error
type: boolean
default: false
- name: pool_name
type: string
default: abc_pool
jobs:
- job: Build
pool:
name: ${{parameters.pool_name}}
steps:
- task: prisma-cloud-compute-scan#2
inputs:
scanType: 'images'
twistlockService: 'SERVICE_CONNECTIONM_NAME'
artifact: ...
continueOnError: ${{parameters.prisma_continue_on_error}}
You mixed syntaxes here
variables:
name: prismaContinueOnError
value: false
isMainBranch: $[eq(variables['Build.SourceBranch'], 'refs/heads/master')]
it should be:
variables:
prismaContinueOnError: false
isMainBranch: $[eq(variables['Build.SourceBranch'], 'refs/heads/master')]
But this will not solve the issue, because variables are just string. You can't have variable of type boolean. You need to pass there runtime expression which delay type evaluation:
stages:
- stage: "Build"
displayName: Build
jobs:
- template: my_build_stage/my_template.yml#templates
parameters:
prisma_continue_on_error: ${{ variables.prismaContinueOnError }}

Azure Devops: Template use sequence typed parameter to generate jobs and stages

It seems the template variable does not support sequence type but the template parameter does support it(called object type in Microsoft doc), together with JobList type and StageList type, but they seem to be just sequences with defined schema.
When iterating through object-typed parameter to generate step I didn't meet any problem, but I got error called 'A sequence was not expected' when I was trying to do such to generate jobs and stages.
So the result have to be like this:
# main.yml:
trigger: none
extends:
template: template.yml
parameters:
PROJECTNAME: foo.bar
DEPLOYMENTTARGETS:
- stage:
jobs:
- deployment:
environment:
name: TEST
tags: Web # tag must be comma separated string which is also kinda weird
- stage:
jobs:
- deployment:
environment:
name: PROD
tags: Web
# template.yml:
parameters:
- name: PROJECTNAME
type: string
default: ""
- name: DEPLOYMENTTARGETS
type: stageList # I was expecting object to be working
default: []
variables:
- group: LoginSecrets
stages:
- ${{ each deploymentTarget in parameters.DEPLOYMENTTARGETS }}: # iterating through an object here will result in error: 'A sequence was not expected', iterating through a StageList is OK
- stage: Deploy_${{replace(parameters.PROJECTNAME,'.','_')}}_${{replace(deploymentTarget.jobs[0].environment.name,'-','')}}_${{replace(replace(deploymentTarget.jobs[0].environment.tags,',','_'),'-','')}}_Stage # assuming each stage contains only one deployment job. We also iterate through jobs here if required.
dependsOn: BuildAndPublish_${{replace(parameters.PROJECTNAME,'.','_')}}_Stage
jobs:
- deployment: Deploy_${{replace(parameters.PROJECTNAME,'.','_')}}_Job
environment:
name: ${{deploymentTarget.jobs[0].environment.name}}
resourceType: VirtualMachine
tags: ${{deploymentTarget.jobs[0].environment.tags}}
strategy:
runOnce:
deploy:
steps:
- pwsh: $(Pipeline.Workspace)/${{parameters.PROJECTNAME}}/pipelineRelease.ps1
env:
LOGINNAME: $(loginName)
LOGINPASSWORD: $(loginPassword)
PROJECTNAME: ${{parameters.PROJECTNAME}}
But I was expecting something like this to be working:
# main.yml:
trigger: none
extends:
template: template.yml
parameters:
PROJECTNAME: foo.bar
DEPLOYMENTTARGETS:
- EnvName: TEST
Tags: Web
- EnvName: PROD
Tags: Web
# template.yml:
parameters:
- name: PROJECTNAME
type: string
default: ""
- name: DEPLOYMENTTARGETS
type: object # instead of StageList, I passed an object here
default: []
variables:
- group: LoginSecrets
stages:
- ${{ each deploymentTarget in parameters.DEPLOYMENTTARGETS }}: # error here
- stage: Deploy_${{replace(parameters.PROJECTNAME,'.','_')}}_${{replace(deploymentTarget.EnvName,'-','')}}_${{replace(replace(deploymentTargetTags,',','_'),'-','')}}_Stage
dependsOn: BuildAndPublish_${{replace(parameters.PROJECTNAME,'.','_')}}_Stage
jobs:
- deployment: Deploy_${{replace(parameters.PROJECTNAME,'.','_')}}_Job
environment:
name: ${{deploymentTarget.EnvName}}
resourceType: VirtualMachine
tags: ${{deploymentTarget.Tags}}
strategy:
runOnce:
deploy:
steps:
- pwsh: $(Pipeline.Workspace)/${{parameters.PROJECTNAME}}/pipelineRelease.ps1
env:
LOGINNAME: $(loginName)
LOGINPASSWORD: $(loginPassword)
PROJECTNAME: ${{parameters.PROJECTNAME}}
Azure Devops: Template use sequence typed parameter to generate jobs and stages
I am afraid we have to use the stageList instead of object to transfer two-dimensional arrays.
That because the parameters is defined as two-dimensional arrays in the main.yml, But if we define this arrays as object in the template.yml file. In this case, we could not loop the object in the template file.
You could check the document Loop through parameters for some more details.
Also, you could check the similar thread for some details.