Using JSON to declare variables in a YAML - azure-devops

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.

Related

How to do a Foreach loop or Each within Azure Pipeline

I am trying to run an Azure Pipeline that queries an Azure Storage table, I can do this no problem by passing in $AppName from a normal pipeline variable, but id like to loop though multiple apps from an app list within the yaml file.
The yaml file I am using is below:
trigger:
- master
variables:
- name: AppNames
value:
[
"7zip",
"AdobeAcrobatReaderDC",
"CitrixWorkspaceApp",
"GoogleChrome",
"LAPS",
"Mimecast",
"Nessus",
"NotepadPlusPlus",
"MicrosoftWvdRemoteDesktop",
]
- name: baseurl
value: $(NexusProdRepo)
- name: genRepo
value: $(ClientRepo)
- name: APIKey
value: $(PRODAPIKey)
pool:
name: $(PoolName)
demands:
- agentOS -equals $(agentOS)
stages:
- stage: Deployment
jobs:
- job: DeployApps
steps:
- script: echo "Deploying $(AppName)"
env:
AppName: ${{ each.value }}
forEach: ${{ variables.AppNames }}
- stage: QueryAzureTableStorage_Stage
dependsOn:
- ConnectiontoAzure
jobs:
- job: QueryAzureTableStorage_Job
steps:
- task: PowerShell#2
displayName: "Query Azure Table Storage"
name: "Query_Azure_Table_Storage"
inputs:
targetType: filePath
filePath: "$(Build.SourcesDirectory)/GetAndQueryStorageTable.ps1"
arguments: "-StorageAccountName $(StorageAccountName) -ResourceGroupName $(ResourceGroupName) -TableName $(TableName) -AppName $(AppName)"
Is anyone able to correct me on where I'm going wrong regards the foreach loop, or if its even possible?
loop though multiple apps from an app list within the yaml file.
Based on your requirement, I suggest that you can use Parameters and Each expression in YAML Pipeline. Refer to this doc: Each keyword
Here is an example:
parameters:
- name: AppNames
type: object
default: [7zip,AdobeAcrobatReaderDC]
stages:
- ${{ each app in parameters.AppNames }}:
- stage: Deployment_${{ app }}
jobs:
- job: DeployApps
steps:
- script: echo "Deploying "${{ app }}""
Result:

How to convert string variable to object and pass it to another pipeline?

I have two Azure Devops pipelines: 'Starter' and 'Processing'. 'Starter' triggers 'Processing' and passes some parameters to it.
Starter:
trigger: none
pool:
vmImage: 'windows-2019'
stages:
- stage: A
jobs:
- template: Processing.yml
parameters:
products: $(Products)
creds: $(Creds)
Processing:
parameters:
- name: products
type: object
default: []
- name: creds
default: ''
jobs:
- ${{ each product in parameters.products }}:
- task: PowerShell#2
displayName: Importing ${{ product }} solution
inputs:
targetType: 'inline'
script: |
#Code
Key detail here is opportunity to loop through 'products' variable (each product in parameters.products), which must be setted in 'Starter' variables:
In other words, starting my pipeline I must pass list of products as 'string' and then loop through this list in second pipeline. 'Is it generally possible? Maybe products should be another type? I tried some work around but didn't get appropriate solution:
- job: Prepare_Products_Array
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
$productsArray = []
$productsArray = $(Products)
$productsArray = $productsArray.Split(',')
Write-Host ("##vso[task.setvariable variable=productsArray;]$productsArray")
- template: Processing.yml
parameters:
products: $env:productsArray
Exception:
From your yaml sample, you are defining the variable in YAML Pipeline UI and using parameters in YAML Template.
In this case, the variables defined on the UI will be assigned at runtime, but the parameters and expressions in the YAML template will be expanded at compile time.
Therefore, YAML UI variables cannot be passed to the Pipeline YAML Template.
And it will show the error:
Expected a...... Actual value $(Product)
This means that the pipeline variable not expanded at compile time.
I am afraid that there is no such method can pass the UI Pipeline variable to YAML Template.
Here are the workarounds:
Method 1 : You can use parameters in Starter yaml to pass the Object type parameters to YAML template.
Starter:
trigger: none
parameters:
- name: products
type: object
default: []
- name: creds
default: ''
pool:
vmImage: 'windows-2019'
stages:
- stage: A
jobs:
- template: Processing.yml
parameters:
products: ${{ parameters.products }}
creds: ${{ parameters.creds }}
Processing:
parameters:
- name: products
type: object
default: []
- name: creds
default: ''
jobs:
- job: test
steps:
- ${{ each product in parameters.products }}:
- task: PowerShell#2
displayName: Importing ${{ product }} solution
inputs:
targetType: 'inline'
script: |
echo ${{ product }}
Result: You can input the value when you run the pipeline.
Method2: You need to define the variable in Starter pipeline and change the products parameters as String type. Then you can use the expression - ${{ each product in split(parameters.products, ',')}}: to split the string.
Starter:
pool:
vmImage: 'windows-2019'
variables:
products: '1,2,3'
creds: test
stages:
- stage: A
jobs:
- template: Processing.yml
parameters:
products: ${{ variables.products }}
creds: ${{ variables.creds }}
Processing:
parameters:
- name: products
type: string
default: ''
- name: creds
default: ''
jobs:
- job: test
steps:
- ${{ each product in split(parameters.products, ',')}}:
- task: PowerShell#2
displayName: Importing ${{ product }} solution
inputs:
targetType: 'inline'
script: |
echo ${{ product }}

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

How to Pass Azure Devops Parameters to pscore script

parameters:
- name: BlobURL
type: string
default: ""
stages:
- stage: ProcessMetaDataFile
displayName: 'Process'
jobs:
- job: Upload
displayName: upload
steps:
- checkout: self
- pwsh: ./psscript.ps1
env: { Cont: "my Test",BlobURL: ???BlobURL }
Above is the script:
I want to pass yaml parameter to pwsh script.
tried ${{parameters.BlobURL}} ${parameters.BlobURL}
$[parameters.BlobURL] '${parameters.BlobURL}'
None worked so far
Tried this as well https://daniel-krzyczkowski.github.io/Parameters-In-Azure-DevOps-Pipelines/ but no success
Both '${{ parameters.BlobURL }}' and "${{ parameters.BlobURL }}" are correct. Just make sure the expression is inside of a string.
Also check your indentation: "steps" needs to be on the same column as "displayName":
parameters:
- name: BlobURL
type: string
default: ""
stages:
- stage: ProcessMetaDataFile
displayName: 'Process'
jobs:
- job: Upload
displayName: upload
steps:
- checkout: self
- pwsh: ./psscript.ps1
env: { Cont: "my Test", BlobURL: '${{ parameters.BlobURL }}' }

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.