Conditional Default-Value in Azure Pipeline DevOps - azure-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)

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"

How to use variable from variable group in conditional insertion expression in Azure DevOps pipeline

My aim is to use a variable group to hold global configuration settings which apply to all pipelines. Specifically, I want the ability to flip a switch in a variable value to switch from using hosted build agents to using private build agents instead.
I have a variable group named my-variable-group which contains a variable named UseHostedAgents. I can toggle its value between true and false.
The pipeline:
variables:
- group: my-variable-group
stages:
- stage: deploy
pool:
${{ if eq(variables['UseHostedAgents'], 'true') }}:
vmImage: ubuntu-latest
${{ else }}:
name: private-pool
jobs:
...
I can't figure out how to get this to work. It seems as though the variable group variable values aren't available in the conditional insertion expression. I've tried everything I can think of to no avail. Any ideas?
You could use a variable/parameter to store whether you want to run on custom agent pool or shared and use it.
Example with parameters:
parameters:
- name: environment
type: string
default: private-pool
variables:
${{ if eq(parameters.environment, 'private-pool') }}:
buildPoolName: private-pool
${{ else }}:
buildPoolName: ubuntu-latest
And then on your job you should use the buildPoolName
- job: 'Job 1'
displayName: 'Build'
pool:
name: $(buildPoolName)
steps:
I think it's just the syntax error, can you try this?
variables:
- group: my-variable-group
stages:
- stage: deploy
pool:
${{ if eq(variables.UseHostedAgents, true) }}:
vmImage: ubuntu-latest
${{ else }}:
name: private-pool
jobs:
...

Switch between Hosted and Scaleset agents in Azure Devops during runtime

I have scaleset agents configured and working fine. But i would also like to take advantage of Microsoft Hosted agents whenever possible. So i added a parameter to the pipeline to choose which agent pool to use for that particular pipeline run.
I manged to set the pool/image variables based on the chosen parameter but unable to make a container job use the selected pool due to a difference in syntax as shown below.
Is there a way to modify the schema of yaml template based on the user selected parameter.
I think we need to not display vmImage property conditionally. I tried below snippet but it doesn't work. vmImage property is always missing.
pool:
${{ if ne(parameters.pool, 'Azure Pipelines') }}:
name: ${{ parameters.pool }}
${{ if eq(parameters.pool, 'Azure Pipelines') }}:
vmImage: 'ubuntu-latest'
UPDATED:
parameters:
- name: pool
displayName: Agent Pool
type: string
default: Scalesets
values:
- Scalesets
- Hosted
jobs:
- deployment: '${{ parameters.jobName }}'
displayName: ${{ coalesce(parameters.jobDisplayName, 'Deploy Infrastructure') }}
${{ if parameters.dependsOn }}:
dependsOn: '${{ parameters.dependsOn }}'
${{ if parameters.condition }}:
condition: '${{ parameters.condition }}'
pool:
name: ${{ parameters.pool }}
vmImage: 'ubuntu-latest'
container:
image: '${{ parameters.image }}'
endpoint: 'Container Registry - Prd'
environment: ${{ parameters.environment }}
variables:
- name: 'Release-Tag'
value: '${{ parameters.release }}'
- name: 'Layer'
value: '${{ parameters.environmentLayer }}'
strategy:
runOnce:
deploy:
steps:
- script: |
echo $(Release-Tag) $(Layer)
displayName: 'Show release condidate'
You can set the data type of your parameters as object. The value of object type can be any YAML structure. Please find more details about data types of parameters in this document.
Here is my sample:
parameters:
- name: pool
type: object
default:
pool:
vmImage: ubuntu-latest
jobs:
- job: build
pool: ${{ parameters.pool }}
steps:
- script: echo Hello, world!
You can also choose the job to run based on the value of your parameters:
trigger: none
parameters:
- name: type
type: string
values:
- Scalesets
- Hosted
jobs:
- ${{ if eq(parameters.type, 'Scalesets') }}:
- job: Scalesets
pool: Default
steps:
- script: echo Scalesets
- ${{ if eq(parameters.type, 'Hosted') }}:
- job: Hosted
pool:
vmImage: ubuntu-latest
steps:
- script: echo Hosted

Different agent pool or demands for the same Azure Pipeline based on trigger

I have an Azure Pipeline written in YAML which runs from a CI trigger whenever changes are made to the master branch. It can also be manually triggered from Pull Requests or by users against any branch.
Due to the use of a number of licensed components, the build from master needs to run on a specific agent. The other builds do not, and in fact I would rather they run on other agent(s).
So my question is, is there any way to specify a different agent/pool within the YAML pipeline based on what triggered the build, or what branch the build is building? I'd like this to be behaviour which is configured in the pipeline permanently, rather than requiring users to update the YAML on each branch they wish to build elsewhere.
I can't see anything obvious in the sections of the documentation on the pool/demands/condition keywords.
I solved this by putting the steps for the job into a template, and then creating a set of jobs in the pipeline with different condition entries, so that we can set demands based on those conditions.
A skeleton version looks like this:
- stage: Build
jobs:
- job: TopicBranchAndPullRequestBuild
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/heads/topic'), startsWith(variables['Build.SourceBranch'], 'refs/pull'))
displayName: 'Build topic Branch or Pull Request'
pool:
name: the-one-and-only-pool
demands:
- HasLicensedComponents -equals false
steps:
- template: build-template.yml
- job: MasterAndReleaseBranchBuild
condition: or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release'))
displayName: 'Build master or release Branch'
pool:
name: the-one-and-only-pool
demands:
- HasLicensedComponents -equals true
steps:
- template: build-template.yml
Obviously the values given here are for example only, but otherwise this is what I have working.
Could you try expressions? I've used this with success on variable groups so it might work on agent pools.
- ${{ if eq(variables['build.SourceBranchName'], 'prod') }}:
- pool: Host1
- ${{ if eq(variables['build.SourceBranchName'], 'staging') }}:
- pool: Host2
- ${{ if not(and(eq(variables['build.SourceBranchName'], 'staging'), eq(variables['build.SourceBranchName'], 'prod'))) }}:
- pool: Host3
Credit for original workaround for dynamically pulling variable groups here: https://github.com/MicrosoftDocs/vsts-docs/issues/3702#issuecomment-574278829
The pool keyword specifies which pool to use for a job of the pipeline. A pool specification also holds information about the job's strategy for running. You can specify a pool at the pipeline, stage, or job level. The pool specified at the lowest level of the hierarchy is used to run the job.
is there any way to specify a different agent/pool within the YAML
pipeline based on what triggered the build, or what branch the build
is building?
For this issue , you can create different yaml files for different branches, specify different agent pools in the corresponding yaml file.
You can switch to the yaml file of different branches in pipeline with the option shown below:
parameters:
- name: self_hosted_agent
displayName: Choose your pool agent
type: string
default: windows-latest
values:
- windows-latest
- self-hosted
- name: agent_name
displayName: Choose your agent
type: string
default: 'Laptop Clint'
values:
- 'Laptop Clint'
- 'Laptop Eastwood'
variables:
- name: pool_agent_key
${{ if eq(parameters.self_hosted_agent, 'windows-latest') }}:
value: vmImage
${{ if eq(parameters.self_hosted_agent, 'self-hosted') }}:
value: name
- name: pool_agent_value
${{ if eq(parameters.self_hosted_agent, 'windows-latest') }}:
value: windows-latest
${{ if eq(parameters.self_hosted_agent, 'self-hosted') }}:
value: Iot-Windows
- name: agent_name
value: ${{ parameters.agent_name }}
stages:
- stage: build
displayName: Build
pool:
${{ variables.pool_agent_key }}: ${{ variables.pool_agent_value }}
${{ if eq(parameters.self_hosted_agent, 'self-hosted') }}:
demands:
- agent.name -equals ${{ variables.agent_name }}

Pass pipeline variable from Designer to YAML job template

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