I'm building a variable made of array of objects and can somehow pass it to another job from another stage, and can even print its value. But it seems I'm not passing it properly as a parameter to the template and I'm getting this error:
/templates/process-apps-template.yml (Line: 16, Col: 3): Expected a sequence or mapping. Actual value '$(apps)'
And here are my codes
# applications-pipeline.yml
stages:
- stage: Initialize
displayName: Initialize
jobs:
- task: Bash@3
name: Applications
inputs:
targetType: inline
workingDirectory: '$(System.DefaultWorkingDirectory)/01_applications'
script: |
# simplified code, the actual one was very long
applications=(
'{"application": "app1", "environments": ["dev", "test", "production"]}'
'{"application": "app2", "environments": ["dev", "staging"]}'
)
echo "##vso[task.setvariable variable=apps;isOutput=true]${applications[@]}"
- stage: ProcessApps
dependsOn: [Initialize]
variables:
- name: apps
value: $[ stageDependencies.Initialize.AppsList.outputs['Applications.apps'] ]
jobs:
- template: templates/process-apps-template.yml
parameters:
apps: $(apps)
# templates/process-apps-template.yml
parameters:
- name: apps
type: object
default: []
jobs:
- job: PaceholderJob
- ${{ each app in parameters.apps }}:
- job: ProcApp
steps:
- task: Bash@3
inputs:
targetType: inline
script: |
echo ${{ app.application }}
Also, how to append the "app.application" to the name and display name of the job "ProcApp"?
/templates/process-apps-template.yml (Line: 16, Col: 3): Expected a sequence or mapping. Actual value '$(apps)'
The cause of the issue is that the variable: $(apps) is Runtime variable(Expand at Runtime) and the template will read the variable at compile time. In this case, the Runtime variable value can not be read by the YAML template.
I am afraid that your requirement can not be achieved in a single pipeline.
how to append the "app.application" to the name and display name of the job "ProcApp"?
To meet your requirement, you can split the two stages into two pipelines. One is used to run Initialize stage. It will set the Pipeline variable and trigger the other pipeline with the required array. The other pipeline is used to run ProcessApps stage and it will collect the array object.
Here is an example:
Pipeline One:
stages:
- stage: Initialize
displayName: Initialize
jobs:
- job: AppsList
steps:
- task: Bash@3
name: Applications
inputs:
targetType: inline
script: |
applications=(
'{"application": "app1", "environments": ["dev", "test", "production"]},'
'{"application": "app2", "environments": ["dev", "staging"]}'
)
echo "##vso[task.setvariable variable=apps;isOutput=true]${applications[@]}"
- task: Bash@3
inputs:
targetType: 'inline'
script: |
az pipelines run --id {PipelineID} --organization $(System.CollectionUri) --project {ProjectName} --parameters Passapps="[$(Applications.apps)]"
env:
AZURE_DEVOPS_EXT_PAT: $(PAT)
Note: You can use the following format to set the variable value:
applications=(
'{"application": "app1", "environments": ["dev", "test", "production"]},'
'{"application": "app2", "environments": ["dev", "staging"]}'
)
Pipeline Two:
Main YAML:
pool:
vmImage: ubuntu-latest
parameters:
- name: Passapps
type: object
default: []
stages:
- stage: ProcessApps
jobs:
- template: templates/process-apps-template.yml
parameters:
apps: ${{parameters.Passapps}}
Template:
parameters:
- name: apps
type: object
default: []
jobs:
- job: PaceholderJob
- ${{ each app in parameters.apps }}:
- job: ${{ app.application }}
steps:
- task: Bash@3
inputs:
targetType: inline
script: |
echo ${{ app.application }}
Result:
Here is the doc related to Azure DevOps CLI trigger Pipeline: az pipelines run