YAML pipeline : How to disable a template depending on variable - azure-devops

I have a yaml pipeline calling a step AndroidSigning#3 which needs apksignerKeystoreFile input. I want to disable this step depending on a variable in the pipeline's library.
I get this error when starting the pipeline :
/build/pipelines/build-mobile-android.yml (Line: 42, Col: 14): Unexpected value 'ne(, 'release')'
Any help is appreciated
- group: variables-group
stages:
- stage: build
jobs:
- job: buil_app
steps:
- task: AndroidSigning#3
enabled: ne(${{ variables.env }}, 'release')
inputs:
apkFiles: 'blabla'
apksign: true

Looking at YAML schema reference it looks that this is not possible here
steps:
- script: string # contents of the script to run
displayName: string # friendly name displayed in the UI
name: string # identifier for this step (A-Z, a-z, 0-9, and underscore)
workingDirectory: string # initial working directory for the step
failOnStderr: boolean # if the script writes to stderr, should that be treated as the step failing?
condition: string
continueOnError: boolean # 'true' if future steps should run even if this step fails; defaults to 'false'
enabled: boolean # whether to run this step; defaults to 'true'
enabled must be boolean. You may use condition and then ne( variables['env'], 'release') it should do the job.

steps:
- task: AndroidSigning#3
condition: eq(variables['env'], 'release')
displayName: AndroidSigning - enabled
enabled: true
inputs:
apkFiles: 'blabla'
apksign: true
- task: AndroidSigning#3
condition: ne(variables['env'], 'release')
displayName: AndroidSigning - disable
enabled: false
inputs:
apkFiles: 'blabla'
apksign: true

Related

Using JSON to declare variables in a YAML

I have a JSON called config.json and I would like to use the values it has to shit variables in a YML.
This is the format of the JSON
{
"config":
{
"ruta": "releases/package.xml",
"testLevel": "--testlevel NoTestRun",
"destroy": "false"
}
}
I need to get the value of "destroy" and load it into a variable in a YML.
Here I have a breakthrough and I need to use that variable in the next stage called "Validation" so that the condition is met.
stages:
- stage: LoadEnv
displayName: Load environment variables
jobs:
- job:
variables:
- name: DESTROY
value: false
steps:
- task: FileTransform#1
inputs:
folderPath: '$(System.DefaultWorkingDirectory)'
targetFiles: 'azure/config.json'
fileType: 'json'
- script: echo ${{variables.DESTROY}}
- stage: Validation
displayName: Validate environment
condition: eq( dependencies.LoadEnv.outputs['Load.variables.DESTROY'], 'false')
jobs:
- job: Validation
.......
I know things are missing but any help is welcome.

Azure devops: How to add a parameter to a step in a steplist

I have a template which takes a steplist which will only be ran in a certain scenario. In part of the template the stepList can be used as is, but in another part I need to add a condition so it doesn't run if not applicable. What I have tried is (condition is more complicated actually but I've tried this too):
- ${{ each step in parameters.preDeleteSteps }}:
- ${{ each pair in step }}:
${{ pair.key }}: ${{ pair.value }}
condition: succeeded()
But this fails with:
/steps/terraform.yml#templates (Line: 132, Col: 7): Expected a mapping
/steps/terraform.yml#templates (Line: 131, Col: 7): Expected at least one key-value pair in the mapping
/steps/terraform.yml#templates: Unexpected state while attempting to read the mapping end. State:
MappingState:
IsStart: True
Index: 0
IsKey: False
IsEnd: False
SequenceState:
IsStart: False
Index: 2
IsEnd: False
IfExpressionState:
IsSequenceInsertion: True
IsStart: False
MappingState:
IsStart: False
Index: 0
IsKey: True
IsEnd: False
SequenceState:
IsStart: False
Index: 6
IsEnd: False
MappingState:
IsStart: False
Index: 0
[...]
I have tried various approaches like putting the condition in [{}], putting a dash in front of it, putting it first after the each step but all seem to end in error. Does anyone know how to do this?
EDIT: Removed the actual condition I'm using as it's not relevant. I've tried with the condition above and that fails with the same error.
trigger:
- none
pool:
vmImage: ubuntu-latest
parameters:
- name: mySteplist
type: stepList
default:
- task: PowerShell#2
name: test1
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "Hello World1"
- task: PowerShell#2
name: test2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "Hello World2"
jobs:
- job:
displayName: testjobname
steps:
- ${{ each step in parameters.mySteplist }}: # Each step
- ${{ each pair in step }}:
${{ pair.key }}: ${{ pair.value }}
condition: eq(1,2) # contional expression here
And this works on my side:

Azure Yaml DevOps variable handling

So I have a YAML file where I am trying to do something like the following:
# top of the file, declare global variables
variables:
- name: MyName
value: 'apple'
...
parameters:
- name: SwitchName
type: boolean
default: false
...
stages:
- stage: Build
displayName: 'Build'
...
jobs:
variables:
- ${{ if eq(parameters.SwitchName, true) }}:
- name: MyName
value: '$(MyName)_pie'
...
steps:
- task: PowerShell#1
inputs:
scriptType: inlineScript
inlineScript: |
Write-Output $(MyName)
...
#end of script
The goal is to control the pipeline to print apple in default run and apple_pie when the user selects that parameter in the UI to be true.
I understand that parameters are compile-time and variables are run-time. I know that to overwrite a global variable you can create a variable at a job level and change it as yo see fit. Sadly, the way how template works do not let me redeclare that variable properly and I end up with $(MyName)_pie. For some reason, Yaml fails to see that inside that template there is a runtime variable that is needed to be defined.
What are my options here to achieve desired behavior?
Anything missing in my understanding here?
You can change to use the ${{ variables.MyName }} to call the variable in root level.
For example:
variables:
- name: MyName
value: 'apple'
parameters:
- name: SwitchName
type: boolean
default: false
stages:
- stage: Build
displayName: 'Build'
jobs:
- job: A
variables:
- ${{ if eq(parameters.SwitchName, true) }}:
- name: MyName
value: '${{ variables.MyName }}_pie'
steps:
- script: "echo $(MyName)"
Result:
Since you used an if expression to reassign value, the variable will be assigned at compile time.
Refer to this doc: Runtime expression syntax
You can use the template expression format: ${{ variables.var }}

AzureDevops set variables based on parameter and pass to template at next stage

In Azure DevOps, I'm trying to create a pipeline which offers a simple selection of pre-set options to the user running it. These options will be converted into different combinations of parameters as specified by a templated stage (the definition of which, I have no control over). The idea of my pipeline is that frequently-used build configurations are easy to select correctly, rather than having to manually set 3 or 4 different parameters.
I need the "Build.Setup" from immutable_pipeline to print config_one, profile_one when the first radio is selected (buildType=type1), config_two, profile_two when buildType=type2, and so on.
Unfortunately I'm really struggling to get any variable value into the templated stage other than the defaults. Are ADO variables even mutable variables at all - or just constants?
I've read the MS docs extensively and understand the meaings of the different macro declaration types. I've tried many different combinations of syntaxes ${{...}}, $(...) and $[...], all behave differently but none seems able to deliver what's needed. Is this even possible? Is there a simple solution someone can suggest?
Pipeline:
name: $(Date:yyyyMMdd).$(Rev:r)
parameters:
- name: buildType
displayName: 'Type of build'
type: string
default: 'type3'
values: ['type1', 'type2', 'type3']
pool:
name: default
variables:
- name: config
value: 'defaultConfig'
- name: profile
value: 'defaultProfile'
stages:
- stage: Stage1
displayName: Prepare build config
jobs:
- job: Job1_1
steps:
- checkout: none
- task: Bash#3
name: SetVariables
inputs:
targetType: inline
script: |
p1='${{ parameters.buildType }}'
v1='$(config)'
v2='$(profile)'
echo -e "BEFORE: p1='${p1}'\n v1='${v1}'\n v2='${v2}'"
case ${p1} in
type1)
v1='config_one'
v2='profile_one'
;;
type2)
v1='config_two'
v2='profile_two'
;;
type3)
v1='config_three'
v2='profile_three'
;;
esac
echo -e "AFTER: p1='${p1}'\n v1='${v1}'\n v2='${v2}'"
echo "##vso[task.setvariable variable=config]${v1}"
echo "##vso[task.setvariable variable=profile;isOutput=True]${v2}"
- job: Job1_2
dependsOn: Job1_1
variables:
- name: variable1
value: $(config)
- name: variable2
value: $[ dependencies.Job1_1.outputs['SetVariables.profile']]
steps:
- task: Bash#3
name: GetVariables2
inputs:
targetType: inline
script: |
echo -e 'SAME STAGE: v1="$(variable1)"\n v2="$(variable2)"'
# Next stage - use computed values for "config" and "profile"
- template: templates/immutable_pipeline.yml
parameters:
config: $(config)
profile: ${{ variables.profile }}
templates/immutable_pipeline.yml:
Note that I don't have access to change this, I can't make it dependsOn: Stage1.Job1_1.
parameters:
- name: config
displayName: 'Config'
type: string
default: 'unset'
- name: profile
displayName: 'Profile'
type: string
default: 'unset'
stages:
- stage: Build
displayName: Templated build
jobs:
- job: Setup
pool:
name: default
demands:
- Agent.OS -equals Linux
steps:
- checkout: none
- script: |
echo '##[info] parameters.config=${{ parameters.config }}'
echo '##[info] parameters.profile=${{ parameters.profile }}'
I just found one solution (which is arguably simpler than using variables) using the ${{ if eq(...) }}: syntax:
name: $(Date:yyyyMMdd).$(Rev:r)
parameters:
- name: buildType
displayName: 'Type of build'
type: string
default: 'type3'
values: ['type1', 'type2', 'type3']
pool:
name: default
stages:
- template: templates/immutable_pipeline.yml
${{ if eq(parameters.buildType, 'type1') }}:
parameters:
config: config_one
profile: profile_one
${{ if eq(parameters.buildType, 'type2') }}:
parameters:
config: config_two
profile: profile_two
${{ if eq(parameters.buildType, 'type3') }}:
parameters:
config: config_three
profile: profile_three
Still interested in whether the original approach of setting variables is even possible, if only beause I've spent so much time on it.

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 }}