Azure Devops: How to set group variable with if statement - azure

I'm trying to set the variable group according to one varible that exists in the pipeline. The yaml looks like this:
But i'm getting the following error when i'm running the pipeline:
If i remove the "- group : QA" or "- group : PROD" the pipeline runs without any problem. What am I doing wrong?

This is slightly different solution but you may achieve your goal - which is if I understood conditional selection of variable group.
You can use runtime parameters:
parameters:
- name: environment
displayName: Environment
type: string
default: QA
values:
- QA
- PROD
stages:
- stage:
displayName: 'Build and Restore'
variables:
- group: ${{ parameters.environment }}
jobs:
- job:
steps:
- script: echo $(name)
than running a build you can select your envrionment:
Note: I have defined two variable groups QA and PROD with variable name in both groups.

Try with below schema:
variables:
isProd: true
stages:
- stage: Test
displayName: Build and restore
variables:
- ${{ if eq(variables['isProd'], 'false') }}:
- group: QA
- ${{ if eq(variables['isProd'], 'true') }}:
- group: PROD
jobs:
- job: A
steps:
- bash: echo $(groupname)
Note: You may receive some red warning when you defining above YAML scipt. Ignore that confused warning and continue to run it.

Related

Variables not getting referenced while calling the shell script in the azure pipelines

This is my first time working with azure pipelines, I started creating my azure-pipeline.yml. I am trying to execute the azure DevOps pipeline. However I am getting to errors where the variable are not referenced as declared.
deploy.sh deploy_azr ${{ variables.subPref }} ${{ variables.rgType }} ${{ variables.location }} ${{ variables.config }}
Here is the start of my template
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
trigger:
branches:
include:
- main
paths:
include:
- 'bicep/*'
- 'azure-pipelines.yml'
exclude:
- '*'
pool:
vmImage: ubuntu-latest
variables:
${{ if eq(variables['Build.SourceBranchName'], 'test_branch') }}:
deployTarget: tst
subscription: testsubscription
subscriptionId: 26455-trt31-******
rgType: tstrg
subPref: *****
config: tstjson
location: eastus2
${{ if eq(variables['Build.SourceBranchName'], 'main') }}:
deployTarget: prd
subscription: prdsub
subscriptionId: ***********************
rgType: prdrg
subPref: ******
config: prd.json
location: eastus2
stages:
- stage: Deploylib
jobs:
- deployment: lib
environment: ${{ variables.subscription }}
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureCLI#2
inputs:
azureSubscription: ${{ variables.subscription }}
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
set -e
set -x
sudo apt install -y gridsite-clients
cd 'bicep'
echo "starting the lib deployment"
deploy.sh deploy_azr ${{ variables.subPref }} ${{ variables.rgType }} ${{ variables.location }} ${{ variables.config }}
any help would be appreciated.
I think the problem is that you need to specify the correct environment name on this line,
jobs:
- deployment: lib
environment: <environment name>
You can create an environment on the DevOps page, see the reference here, then copy the name to the YAML above.
The concept of environment here represents a collection of resources you will deploy your code. Once you have run a deployment, you should be able to see the history of deployment in the target environment.
/azure-pipelines.yml (Line: 42, Col: 22): Unexpected value ''
Test the same YAML sample and reproduce the same issue.
The cause of the issue is that you are using the format: ${{ variables.subscription }} in YAML sample.
The variable will be processed at compile time.
To solve this issue, you can change to use the format: $(subscription)
For example:
jobs:
- deployment: lib
environment: $(subscription)
Result:
For more detailed info, you can refer to this doc: Runtime expression syntax

YAML - Execute template in Deploymentjob

I'm currently trying to setup my complete build/release pipeline with yaml files.
First I tried with different stages (dev/staging/prod) and it worked.
Now I wanted to add an approval that the deploy doesn't not happen automatically on each system.
Therefore I added an environment in the TFS with an approval check.
But when I try to setup the yaml file I always get an error.
I don't know how to setup this properly.
This is my main yaml file called release-pipeline.yaml
trigger:
- master
pool:
name: POOL
stages:
- stage: BuildSolution
jobs:
- job: BuildSolutionJob
displayName: Build
workspace:
clean: all
steps:
- template: yaml/BuildSolution.yml
- template: yaml/CopyFiles.yml
- template: yaml/PublishArtifact.yml
- stage: DeployOn_STAGING_System
dependsOn: BuildSolution
jobs:
- job: Deploy_STAGING
- template: yaml/Deploy.yml
parameters:
Environment: 'SITE'
Staging: 1
- stage: Deploy_DEV_System
dependsOn: BuildSolution
jobs:
- deployment: Deploy_DEV
environment: ENVCHECK_DEV
strategy:
runOnce:
deploy:
steps:
- template: yaml/Deploy.yml
parameters:
Environment: 'SITE'
ViewDeploy: 1
This is my Deploy.yml file which i want to execute (only some snips):
parameters:
- name: Environment
type: string
- name: ProdSystem
type: number
default: 0
- name: Staging
type: number
default: 0
- name: ViewDeploy
type: number
default: 0
jobs:
- job:
variables:
artifactName: $[stageDependencies.BuildSolution.BuildSolutionJob.outputs['SetVariables.artifactName']]
version: $[stageDependencies.BuildSolution.BuildSolutionJob.outputs['SetVariables.version']]
steps:
- task: PowerShell#2
displayName: Display given parameters
inputs:
targetType: inline
script: >
Write-Host "ArtifaceName: " $(artifactName)
Write-Host "Environment for Deploy: " ${{ parameters.Environment }}
Write-Host "##vso[task.setvariable variable=isStaging]${{ parameters.Staging }}"
failOnStderr: true
When I try to execute I get the following error:
/release-pipeline.yml: Unexpected value 'parameters'.
How do I need to change this that it will work with the template in both cases, with and without the environment approval check?
I tried https://samlearnsazure.blog/2020/02/05/approvals-in-environments/
and of course different structure for the calling. But nothing helped.
In the tutorials they always have steps below the "deploy" but because I have different sites and environments I want/need the template file to save work.
I found another post which goes in the same direction.
I reworked my complete template so that I can use the approach of this: DevOps template with conditional manual approval job
It's not the same as I wanted, but it works.
My goal was that I don't want to create a environment if I have no checks on this site. Only for sites where I wanted the approval check.
With the above mentioned solution I need to create an environment for each site, independent if I have checks or not.

How to send different parameters to Azure pipeline templates based on the System.PullRequest.TargetBranch variable

I have a pipeline template that should receive a different input based on the Pull Request Target Branch.
Template:
parameters:
- name: BUILD_FOLDER
type: string
steps:
- script: |
echo "Build folder: ${{ parameters.BUILD_FOLDER }}"
displayName: 'Echo Build folder'
Pipeline YAML.
trigger: none
pr:
branches:
include:
- '*'
pool:
vmImage: ubuntu-latest
steps:
- template: templates/template.yml
parameters:
${{ if contains(variables['System.PullRequest.TargetBranch'], 'master') }}:
BUILD_FOLDER: base
${{ if not(contains(variables['System.PullRequest.TargetBranch'], 'master')) }}:
BUILD_FOLDER: $(System.PullRequest.TargetBranch)
I tried doing it like this but always it goes with ${{ if not(contains(variables['System.PullRequest.TargetBranch'], 'master')) }}: even the target branch is master in the Pull Request. Is there another way to do this?
Also the repository is in GitHub.
Thanks in advance.
I can reproduce the same issue. It is because the predefined variable System.PullRequest.TargetBranch cannot be evaluated at the compile time. It can be evaluated at run time (wrapped in $())without any problem. Expression wrapped in ${{}} will be evaluated at the build compile time. See Runtime expression syntax.
These variables that are marked not available in template in document cannot be parsed at compile time. The document causes little confusion, because it doesnot clearly state those variables cannot be parsed at compile time.
Since the template is evaluated at compile time. So the variable System.PullRequest.TargetBranch wrapped ${{}} is evaluated to an empty string.
I tested with below yaml. And the powershell task got executed:
- ${{ if eq(variables['System.PullRequest.TargetBranch'], '') }}:
- powershell: echo "i will out put empty"
The workaround for this is to set the variable value by script in an additional powershell task, as mentioned by Krzysztof Madej. I changed your yaml file a little bit. See below:
trigger: none
pr:
branches:
include:
- '*'
pool:
vmImage: ubuntu-latest
steps:
- powershell: |
$targetBranch = "$(System.PullRequest.TargetBranch)"
if($targetBranch -eq "master"){
Write-Host "##vso[task.setvariable variable=BUILD_FOLDER;]base"
}
if($targetBranch -ne "master"){
Write-Host "##vso[task.setvariable variable=BUILD_FOLDER;]$targetBranch"
}
- template: templates/template.yml
parameters:
BUILD_FOLDER: $(BUILD_FOLDER)
Some of variables can't be used in expressions like this. It is shown in the last column Available in templates? on this page
What you can do is move this to the template itself like this:
parameters:
- name: BASE_BUILD_FOLDER
type: string
default: base
steps:
- pwsh: |
$targetBranch = '$(System.PullRequest.TargetBranch)'
$buildFolder = '${{ parameters.BASE_BUILD_FOLDER }}'
if (!($targetBranch -like "*master")){
$buildFolder = $targetBranch
}
Write-Host "##vso[task.setvariable variable=BUILD_FOLDER;]$buildFolder"
- script: |
echo "Build folder: $(BUILD_FOLDER)"
displayName: 'Echo Build folder'
and then you can call it
trigger: none
pr:
branches:
include:
- '*'
pool:
vmImage: ubuntu-latest
steps:
- template: templates/template.yml

Azure yaml pipeline using "extends"

I am trying to use extends as part of my pipeline. I am trying to get the first basic step working from Azure docs ie
# pythonparameter-template.yml
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}
- ${{ step }}
# azure-pipelines.yml
trigger: none
resources:
repositories:
- repository: CI-CD-Templates
type: git
name: /CI-CD-Templates
ref: refs/heads/master
extends:
template: /pythonparameter-template.yml#CI-CD-Templates
parameters:
usersteps:
- script: echo This is my first step
- script: echo This is my second step
I keep getting the below error:
The directive 'each' is not allowed in this context. Directives are not supported for expressions that are embedded within a string. Directives are only supported when the entire value is an expression
Unexpected value '${{ each step in parameters.usersteps }} - ${{ step }}'
Also after I extend from a template can azure-pipelines.yml also have it's own custom steps ie
# azure-pipelines.yml
resources:
repositories:
- repository: templates
type: git
name: MyProject/MyTemplates
ref: tags/v1
extends:
template: template.yml#templates
parameters:
usersteps:
- script: echo This is my first step
- script: echo This is my second step
steps:
- template: /validation-template.yml#CI-CD-Templates
parameters:
commitMessage: $(commitMessage)
- template: /shared-template.yml#CI-CD-Templates
parameters:
buildArtifactDir: $(buildArtifactDir)
Update
Please refer the response in this DC link-- Yaml extends feature erroring out when looping through steps.
​The YAML has a validation task in #pythonparameter-template.yml
Comment out these 2 lines and your YAML will succeed. The template shown here is preventing any tasks to be used. This could be a scenario for someone with specific security requirements.
${{ if eq(pair.key, 'task') }}:
'${{ pair.value }}': error
Are you trying to combine two yml pythonparameter-template.yml azure-pipelines.yml in the same file? It's not supported.
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}
- ${{ step }}
According to the error Directives are not supported for expressions that are embedded within a string. Directives are only supported when the entire value is an expression Unexpected value '${{ each step in parameters.usersteps }} - ${{ step }}'
You maybe use the wrong format. About the formats you could refer our official doc here--
Template types & usage
Besides, you can make azure-pipelines.yml also have it's own custom steps. But you need to put them under parameters in the pipeline, not like the way you use.
azure-pipelines.yml
trigger:
- master
extends:
template: pythonparameter-template.yml
parameters:
buildSteps:
- bash: echo Test #Passes
displayName: succeed
- bash: echo "Test"
displayName: succeed
- script: echo "Script Test"
displayName: Fail

How to pass a list of string parameters to an Azure DevOps template

In a previous SO question, I was trying to get create an Azure DevOps template.
Now that I know how to do that, I'm trying to pass in a list of strings to the template and use them in the template, like so:
azure_pipelines.yml
extends:
template: AzurePipelines/job.yml
parameters:
projects:
- FirstProject.csproj
- SecondProject.csproj
and in this template...
job.yml
steps:
(for each projectFileName in projects)
- bash echo $(projectFileName)
- run code in the build.yml template using $(projectFileName)
- run code in the test.yml template using $(projectFileName)
- run code in the publish.yml template using $(projectFileName)
So for each project name handed into the template, run the template steps.
I'm not sure how to pass in an array of strings and how to test that it works?
It seems you are looking for each function:
# my-template.yml
parameters:
- name: 'projects'
type: projectList
default: []
steps:
- ${{ each project in parameters.projects }}:
- task: PublishBuildArtifacts#1
displayName: 'Publish ${{ project }}'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/${{ project }}.zip'
# ci.yml
steps:
- template: my-template.yml
parameters:
projects:
- test1
- test2
The easiest way I found to accomplish the use of templates is by using the templates from within the main yaml file pipeline. This way you will have access to all the variables and variable groups defined in the main template. Using this architecture you will be able to bundle several steps into a template then run it from the main yaml file. Eg:
azure_pipelines.yml
variables:
- name: projectFileName
value: "Variable 1 value"
- name: VAR2
value: "Variable 2 value"
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
steps:
- template: templates/job.yml
- template: templates/test.yml
templates/job.yml
steps:
- task: Bash#3
displayName: 'Run Bash Command'
inputs:
targetType: 'inline'
script: |
print "Variable value: " $(projectFileName)
Hope it helps

Resources