Вопрос или проблема
Я создаю переменную, состоящую из массива объектов, и могу как-то передать её в другую задачу из другой стадии, и даже вывести её значение. Но, похоже, я не правильно передаю её в качестве параметра в шаблон, и получаю эту ошибку:
/templates/process-apps-template.yml (Строка: 16, Столбец: 3): Ожидался последовательность или отображение. Фактическое значение ‘$(apps)’
А вот мой код
# applications-pipeline.yml
stages:
- stage: Initialize
displayName: Initialize
jobs:
- task: Bash@3
name: Applications
inputs:
targetType: inline
workingDirectory: '$(System.DefaultWorkingDirectory)/01_applications'
script: |
# упрощенный код, фактический был очень длинным
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 }}
Также, как добавить “app.application” к имени и отображаемому имени задачи “ProcApp”?
/templates/process-apps-template.yml (Строка: 16, Столбец: 3): Ожидался последовательность или отображение. Фактическое значение ‘$(apps)’
Причина проблемы в том, что переменная: $(apps) является переменной времени выполнения (расширяется во время выполнения), а шаблон будет считывать переменную во время компиляции. В данном случае, значение переменной времени выполнения не может быть прочитано YAML-шаблоном.
Боюсь, что ваша задача не может быть выполнена в одной пайплайн.
как добавить “app.application” к имени и отображаемому имени задачи “ProcApp”?
Чтобы удовлетворить вашу задачу, вы можете разделить две стадии на два пайплайна. Один используется для выполнения стадии Initialize. Он установит переменную пайплайна и вызовет другой пайплайн с необходимым массивом. Другой пайплайн используется для выполнения стадии ProcessApps и соберет объект массива.
Вот пример:
Первый пайплайн:
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)
Примечание: Вы можете использовать следующий формат для установки значения переменной:
applications=(
'{"application": "app1", "environments": ["dev", "test", "production"]},'
'{"application": "app2", "environments": ["dev", "staging"]}'
)
Второй пайплайн:
Основной 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}}
Шаблон:
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 }}
Результат:
Вот документ, связанный с триггером Azure DevOps CLI Pipeline: az pipelines run
Ответ или решение
В Azure DevOps Pipeline, передача массива объектов из выходной переменной в шаблон как параметра может вызвать некоторые трудности, особенно если требуется передать его между разными этапами. Давайте рассмотрим, как правильно реализовать этот сценарий.
Проблема
Ваша ошибка связана с тем, что переменная $(apps)
является переменной времени выполнения (Runtime variable), и шаблон не может её интерпретировать на этапе компиляции. Чтобы обойти это ограничение, вам следует разбить процесс на два разных pipeline.
Решение
Pipeline One (инициализация переменной)
Создайте первый pipeline, который будет содержать стадию Initialize
, где будет устанавливаться выходная переменная. Затем этот pipeline запускает второй pipeline с необходимыми параметрами.
# applications-pipeline.yml
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)
Pipeline Two (обработка)
Создайте второй pipeline, который будет обрабатывать параметры, переданные из первого pipeline.
# main-pipeline.yml
pool:
vmImage: ubuntu-latest
parameters:
- name: Passapps
type: object
default: []
stages:
- stage: ProcessApps
jobs:
- template: templates/process-apps-template.yml
parameters:
apps: ${{ parameters.Passapps }}
Шаблон
Ваш шаблон также должен быть определён для обработки параметра apps
:
# templates/process-apps-template.yml
parameters:
- name: apps
type: object
default: []
jobs:
- job: PlaceholderJob
- ${{ each app in parameters.apps }}:
- job: ${{ app.application }}
displayName: ${{ format('Job for {0}', app.application) }}
steps:
- task: Bash@3
inputs:
targetType: inline
script: |
echo ${{ app.application }}
Примечания
-
Обратите внимание на форматирование: Когда вы передаёте массив объектов в качестве параметра в другой pipeline, убедитесь, что он сериализуется корректно. В данном случае используются двойные кавычки и запятые для отделения объектов.
-
Именование заданий: Чтобы дополнительно настроить название и отображаемое имя задания
ProcApp
, применяется выражениеformat
, что позволяет динамически формировать название на основе значенияapp.application
. -
CLI для Azure DevOps: Для срабатывания второго pipeline вы можете использовать команду CLI Azure, что позволяет авторизовать и вызывать другой pipeline с нужными параметрами.
Этот подход должен помочь вам корректно передать массив объектов между этапами и получить необходимый результат в вашем сценарии.