I have below main.yml build pipeline,
parameters:
- name: ListOfEnvironments
type: object
default:
- dev
- tst
- acc
- prd
stages:
- ${{ each value in parameters.ListOfEnvironments }}:
- template: templates/stage.yml
parameters:
environment_name: ${{ value }}
Now above template works and able to call different env specific stage.yml templates.
now inside stage.yml I have the below structure:
stages:
- stage: deploy_to_env
displayName: Deploy
jobs:
- job: deploy
displayName: Deploy
variables:
- name: environment
value: ${{ parameters.environment_name }}
steps:
${{ if eq(parameters.environment_name, "dev") }}:
template: ../steps_templates/dev_steps.yml
${{ if eq(parameters.environment_name, "acc") }}:
template: ../steps_templates/acc_steps.yml
I'm not able to call steps template based on the conditions. Also, I tried to do like below
${{ if eq(parameters.environment_name, "dev") }}:
steps:
- template: ../steps_templates/dev_steps.yml
${{ if eq(parameters.environment_name, "acc") }}:
steps:
- template: ../steps_templates/acc_steps.yml
It's not working, does anyone have any idea how to call steps based on the conditional parameters.
UPDATE:
I finally managed to go further like this, where it recognized the env variable but now it complains Unrecognized value: '"dev"'. Located at position 33 within expression: eq(parameters.environment_name, dev)
steps:
- ${{ if eq(parameters.environment_name, "dev") }}:
- template: ../steps_templates/dev_steps.yml
- ${{ if eq(parameters.environment_name, "acc") }}:
- template: ../steps_templates/acc_steps.yml
it's working now, after changing " to ' . It's all good now.
May be someone will find this helpful:
The below layout will work fine:
steps:
- ${{ if eq(parameters.environment_name, 'dev') }}:
- template: ../steps_templates/dev_steps.yml
- ${{ if eq(parameters.environment_name, 'acc') }}:
- template: ../steps_templates/acc_steps.yml
Related
I would like to have a iterate over a list of environments that I would use in various places rather than copying and pasting the same code for each environment.
I get the following error:
Encountered error(s) while parsing pipeline YAML: file.yml (Line: 14, Col: 7): Unexpected symbol: 'env'. Located at position 8 within expression: eq(${{ env. For more help, refer to
I see several examples of something like this such as here:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#conditional-insertion
How can I get this to work?
parameters:
- name: environments
type: object
default: ['dev'] # e.g. for multiple envs: ['dev','stage','prd','etc']
stages:
- ${{ each env in parameters.environments }}:
- stage: Deploy_${{ env }}
dependsOn:
- 'Build'
pool:
vmImage: 'windows-latest'
variables:
${{ if eq(${{ env }}, 'prd') }}:
environment: 'ADO Environment'
${{ else }}:
environment: 'ADO Environment - Dev'
azureServiceConnection: 'ServiceConnection - ${{ env }}'
jobs:
- deployment: 'Deploy_${{ env }}'
environment: ${{ variables.environment }}
strategy:
runOnce:
deploy:
steps:
- template: deploy.yml
parameters:
azureServiceConnection: '${{ variables.azureServiceConnection }}'
environment: ${{ variables.environment }}
According to your YAML file, I can reproduce your problem. Parameters are expanded just before the pipeline runs so that values surrounded by ${{ }} are replaced with parameter values
Because the ${{}} is a runtime expression, I tried to use the env in the "if" condition and it works as expected.
YAML like:
variables:
${{ if eq(env, 'prd') }}:
environment: 'ADO Environment'
${{ else }}
environment: 'ADO Environment - Dev'
Is there a way to reference a job parameter's name in an Azure DevOps YAML template? I know that I could pass in the job name as its own string parameter, but I was hoping for something that's a little less clumsy.
template.yml
parameters:
- name: MyJob
type: job
jobs:
- ${{ parameters.MyJob }}
- job: Job2
dependsOn: # How to make this depend on MyJob?
azure-pipelines.yml
stages:
- stage: Stage1
jobs:
- template: template.yml
parameters:
MyJob:
job: SomeJobName
steps:
- script: echo Hello
I tried accessing ${{ parameters.MyJob.name }} but it doesn't appear to exist.
I've figured out, though it took a lot of trial and error to get the exact syntax and spacing right. The docs aren't super clear about spacing and expressions, and when to lead with a dash.
parameters:
- name: MyJob
type: job
jobs:
- ${{ parameters.MyJob }}
- job: Job2
${{ each pair in parameters.MyJob }}:
${{ if eq(pair.key, 'job') }}:
dependsOn: ${{ pair.value }}
steps:
...
Can't comment, but as you see in previous answer, the property is not "name", but "job". You don't need the foreach then:
parameters:
- name: MyJob
type: job
jobs:
- ${{ parameters.MyJob }}
- job: Job2
dependsOn: ${{ parameters.MyJob.job }}
steps:
...
I'm creating a template in which I pass a job list. In this template, I add a "pre" job to the job list, and then add all jobs. I'd like to be able to add a dependency on the "pre" job to all jobs in the job list, without breaking any dependencies between the jobs in the joblist parameter. My template looks something like this:
parameters:
- name: Jobs
type: jobList
jobs:
- job: prejob
steps:
- powershell: |
Write-Host "This is my prejob"
- ${{ each job in parameters.Jobs }}:
- ${{ each pair in job }}:
${{ if and(ne(pair.key, 'steps'),ne(pair.key, 'dependsOn')) }}:
${{ pair.key }}: ${{ pair.value }}
dependsOn: 'prejob'
steps:
- ${{ job.steps }}
now this of course overwrites the dependsOn of the jobs passed.
What can I change in the template so I can join the passed job dependencies with the prejob job? The join expression joins 2 arrays, but my prejob text is not an array, and I'm not sure the dependsOn property of a job is always an array.
Please try this:
parameters:
- name: Jobs
type: jobList
jobs:
- job: prejob
steps:
- powershell: |
Write-Host "This is my prejob"
- ${{ each job in parameters.Jobs }}:
- ${{ each pair in job }}:
${{ if and(ne(pair.key, 'steps'),ne(pair.key, 'dependsOn')) }}:
${{ pair.key }}: ${{ pair.value }}
dependsOn:
- 'prejob'
- ${{ if job.dependsOn }}:
- ${{ job.dependsOn }}
steps:
- ${{ job.steps }}
In that way you should be able to make dependency to prejob and keep dependencies from jobs.
I'm trying to pass stage list from azure pipeline shown below
# File: azure-pipelines.yml
trigger:
- master
extends:
template: start_stage.yml
parameters:
cdstages:
- stage: secure_buildstage
pool: Hosted VS2017
jobs:
- job: secure_buildjob
steps:
- bash: echo This happens before code
displayName: 'Base: Pre-build'
- bash: echo Building
displayName: 'Base: Build'
- bash: echo This happens after code
displayName: 'Base: Signing'
- stage: secure_deploystage
pool: Hosted VS2017
jobs:
- job: secure_deployjob
steps:
- bash: echo This happens before code
displayName: 'Base: Pre-build'
- bash: echo Building
displayName: 'Base: Build'
- script: echo This happens after code
displayName: 'Base: Signing'
to extend template shown below
parameters:
- name: cdstages # the name of the parameter is buildSteps
type: stageList # data type is StepList
default: [] # default value of buildSteps
stages:
- ${{ each stage in parameters.cdstages }}:
- ${{ each job in stage.jobs }}:
- ${{ each step in job.steps }}:
- ${{ each pair in step }}:
${{ if ne(pair.value, 'CmdLine#2') }}:
${{ pair.key }}: ${{ pair.value }}
${{ if eq(pair.value, 'CmdLine#2') }}:
'${{ pair.value }}': error
The goal is to take stage list and validate if users are only running steps approved by firm's compliance team.
I'm getting error
[][1
not sure why getting "task" error, there are no task keywords used anywhere.
Any help?
Based on my test , it seems that the stagelist in start_stage.yml doesn't support to add eachdirective to get deeper content (e.g. job and steps).
When you use the stagelist, it could get the stage and use it for comparison.
For example:
parameters:
- name: cdstages # the name of the parameter is buildSteps
type: stageList # data type is StepList
default: [] # default value of buildSteps
stages:
- ${{ each stage in parameters.cdstages }}:
- ${{ each pair in stage }}:
${{ if ne(pair.value, 'abc') }}:
${{ pair.key }}: ${{ pair.value }}
${{ if eq(pair.value, 'abc') }}:
'${{ pair.value }}': error
This Yaml template could work.
But when I add the each directive behind the stage to get the jobs. The jobs are is not available.
parameters:
- name: cdstages
type: stageList
default: []
stages:
- ${{ each stage in parameters.cdstages }}:
- ${{ each job in stage.jobs }}:
- ${{ each pair in job }}:
${{ if ne(pair.value, 'abc') }}:
${{ pair.key }}: ${{ pair.value }}
${{ if eq(pair.value, 'abc') }}:
'${{ pair.value }}': error
According to your requirements, you need to get the build step and use it for comparison.
You could try to directly use the steplist type.
Here is an example about steplist, you could refer to it.
Hope this helps.
I initially wanted to define pipeline variables in my azure-pipelines.yml that I can optionally set at queue time, but it seems that this is not supported at the moment: variables that can be set at queue time can only be defined in the Designer. This variable (comma-separated) is named nx_versions and will be used to build a matrix strategy. Here's a minimal example:
# azure-pipelines.yml
jobs:
- template: job-template.yml
parameters:
nx_versions: $(nx_versions)
and
# job-template.yml
parameters:
nx_versions:
- 1
jobs:
- job: build
strategy:
matrix:
${{ each nxver in parameters.nx_versions }}:
NX_${{ nxver }}:
NXVersion: ${{ nxver }}
steps:
- powershell: echo $(NXVersion)
Queuing the build with nx_versions = 2,3 (value doesn't actually matter) results in an error:
/job-template.yml (Line: 9, Col: 9): Expected a sequence or mapping. Actual value '$(nx_versions)'
Is this even possible? I also tried using ${{ nx_versions }} and ${{ variables.nx_versions }} to no avail.
This is possible with a full Designer solution.
The trivial pipeline (not referencing templates, but could be extended easily to do so)
parameters:
- name: nx_versions
type: object
default:
- 1
- 4
jobs:
- job: build
strategy:
matrix:
${{ each nxver in parameters.nx_versions }}:
NX_${{ nxver }}:
NXVersion: ${{ nxver }}
steps:
- powershell: echo $(NXVersion)
Expands to
parameters:
- name: nx_versions
type: object
default:
- 1
- 4
stages:
- stage: __default
jobs:
- job: build
strategy:
matrix:
NX_1:
NXVersion: 1
NX_4:
NXVersion: 4
steps:
- task: PowerShell#2
inputs:
targetType: inline
script: echo $(NXVersion)
If you go to queue a build for that, you get a parameters page with the defaults:
that you can override:
which results in:
I am running into the same issue. I don't think this is currently possible. I believe this is being worked on https://github.com/Microsoft/azure-pipelines-yaml/pull/129