Pass pipeline variable from Designer to YAML job template - azure-devops

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

Related

How to create Azure Pipeline Template to run a jobList all on the same agent?

I am trying to make a pipeline template that takes a JobList a parameter and runs all the jobs, while ensuring that they run on the same agent every time. Basically the approach I've been taking is to try to adapt this answer into a genericized template format.
This is what I have so far, and I've tried a lot of slight tweaks of this with nothing passing the Validate test on the pipeline that calls it.
parameters:
- name: jobsToRun
type: jobList
- name: pool
type: string
default: Default
- name: demands
type: object
default: []
jobs:
- job:
steps:
- script: echo "##vso[task.setvariable variable=agentName;isOutput=true;]$(Agent.Name)"
pool:
name: ${{ parameters.pool }}
demands:
- ${{ each demand in parameters.demands }}:
${{ demand }}
- ${{ each j in parameters.jobsToRun }}:
${{ each pair in j }}:
${{ pair.key }} : ${{ pair.value }}
pool:
name: Default
demands:
- Agent.Name -equals $(agentName)
What am I doing wrong here? It seems like it should be possible if that answer I reference is correct, but it seems like I'm just a bit off.
Name missing on the job.., example below.
- job: 'test-Name'
Steps need a associated job and pool to run is declared inside
jobsToRun:
- job: sample_job1
displayName: "sample_job1"
pool:
name: "your_PoolName"
steps:
- script: |
echo "Hi"
On this bottom pool declaration...
pool:
name: Default
demands:
- Agent.Name -equals $(agentName)
i am not sure but i have tried this many times but i think this can't be included separate to the job since each individual job is passed as parameter. pool definition needs to be inside the job or inside the job template if you are using templates..
example:
jobsToRun:
- job: output_message_job1
displayName: "in pipe Output Message Job"
pool:
name: "your_PoolName"
steps:
- script: |
echo "Hi"

YAML Extend Stage Template

Looking to try and get some help figuring out a solution to what seems like a simple task. I am trying to develop some extend YAML templates for security within our ADO pipelines but first I have to get passed this error I am experiencing.
The error being returned by ADO when I try to validate or run the pipeline is
/ADO_Stage_Restrictions_Dev.yml#AdoRestrictions (Line: 7, Col: 3): Unexpected value job
Working Extend Template YAML
This template validates and executes without issue, which to me means I am successfully passing the stages object into the extends template
parameters:
- name: stageObjs
type: stageList
default: []
stages:
- ${{ each stage in parameters.stageObjs }}:
${{ stage }}
Broken Extend Template YAML
This template does not validate and throws the 'Unexpected value job' exception. based on the stage schema I would assume that I would be able to loop the jobs property within the stage.
parameters:
- name: stageObjs
type: stageList
default: []
stages:
- ${{ each stage in parameters.stageObjs }}:
- ${{ each job in stage.jobs }}:
${{ job }}
Build YAML
The main yaml file that extends stages
resources:
repositories:
- repository: self
type: git
ref: refs/heads/Development
- repository: AdoRestrictions
type: git
name: utl-yaml-templates
ref: refs/heads/main
trigger: none
pool:
name: PROD
extends:
template: ADO_Stage_Restrictions_Dev.yml#AdoRestrictions
parameters:
stageObjs:
- stage: 'BuildStage'
displayName: 'Build Test'
jobs:
- job: 'BuildJob'
displayName: 'Build'
steps:
- task: PowerShell#2
displayName: 'Hello World'
inputs:
targetType: inline
script: |
Write-Host "Hello World"
There's nothing in your yaml which defines the start of the stage, or declares the start of the list of jobs; that's why it wasn't expecting to find 'job' there. You can add those parts in, like this:
parameters:
- name: stageObjs
type: stageList
default: []
stages:
- ${{ each stage in parameters.stageObjs }}:
- stage: ${{ stage.stage }}
displayName: ${{ stage.displayName }}
jobs:
- ${{ each job in stage.jobs }}:
${{ job }}

Conditional Default-Value in Azure Pipeline DevOps

I use Azure Pipelines to Build my solution. When building manually the user can decide which Build Configuration to use. Now I want the default value (and so the value when triggered automatically) to be different according to the branch. This is my (non-working) approach:
name: PR-$(Build.SourceBranchName)-$(Date:yyyyMMdd)$(Rev:.r)
trigger:
- develop
- test
- master
pool:
vmImage: 'windows-latest'
parameters:
- name: BuildConfiguration
displayName: Build Configuration
${{ if eq(variables['Build.SourceBranch'], 'refs/heads/develop') }}:
default: Debug
${{ if eq(variables['Build.SourceBranch'], 'refs/heads/test') }}:
default: Release
${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}:
default: Release
values:
- Debug
- Release
The conditional part (${{...}) simply does not work. (*"A template expression is not allowed in this context")
Is there any other approach to make this happen?
This is not posssible to use expressins to select default value for paramataers.
Paramaters alco can't be optionla:
Parameters must contain a name and data type. Parameters cannot be optional. A default value needs to be assigned in your YAML file or when you run your pipeline. If you do not assign a default value or set default to false, the first available value will be used.
What you can do is use parameters and variables:
name: PR-$(Build.SourceBranchName)-$(Date:yyyyMMdd)$(Rev:.r)
trigger:
- develop
- test
- master
pool:
vmImage: 'windows-latest'
parameters:
- name: BuildConfiguration
displayName: Build Configuration
default: Default
values:
- Debug
- Release
- Default
variables:
- name: buildConfiguration
${{ if and(eq(variables['Build.SourceBranch'], 'refs/heads/develop'), eq(parameters.BuildConfiguration, 'Default')) }}:
value: Debug
${{ elseif and(eq(variables['Build.SourceBranch'], 'refs/heads/test'), eq(parameters.BuildConfiguration, 'Default')) }}:
value: Release
${{ elseif and(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(parameters.BuildConfiguration, 'Default')) }}:
value: Release
${{ else }}:
value: ${{parameters.BuildConfiguration}}
steps:
- script: |
echo $(buildConfiguration)
echo $(Build.SourceBranch)

Reference a pipeline job name in a YAML template

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:
...

Extend YAML pipeline example validate step

the extend template example shared by MSFT in documentation suppose to fail the step but it's not failing it.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#extend-from-a-template
can anyone share a working example of this.
I want to to validate user yaml in extend template and fail the build in case of steps used that are not allowed as per firm policies.
The document here provides the confused direction. You can try to download your build log which does not action like you expect, then analyze the initializeLog.txt file contents. All of key evaluating expression are list there.
Try with below sample:
start.yml
# File: start.yml
parameters:
- name: buildSteps # the name of the parameter is buildSteps
type: stepList # data type is StepList
default: [] # default value of buildSteps
stages:
- stage: secure_buildstage
pool: Hosted VS2017
jobs:
- job: secure_buildjob
steps:
- script: echo This happens before code
displayName: 'Base: Pre-build'
- script: echo Building
displayName: 'Base: Build'
- ${{ each step in parameters.buildSteps }}:
- ${{ each pair in step }}:
${{ if ne(pair.value, 'CmdLine#2') }}:
${{ pair.key }}: ${{ pair.value }}
${{ if eq(pair.value, 'CmdLine#2') }}:
'${{ pair.value }}': error
- script: echo This happens after code
displayName: 'Base: Signing'
azure-pipelines.yml
trigger:
- master
extends:
template: start.yml
parameters:
buildSteps:
- bash: echo Test #Passes
displayName: succeed
- bash: echo "Test"
displayName: succeed
- script: echo "Script Test"
displayName: Fail
Then you will see the pipeline failed because of the script step detected out:
Note: This validation is, once template detect out there has one CmdLine#2 step was passed from azure-pipeline.yml, it will fail the current pipeline instead of one specified step.