В Azure DevOps Pipeline как передать массив объектов из выходной переменной в шаблон в качестве параметра?

Вопрос или проблема

Я создаю переменную, состоящую из массива объектов, и могу как-то передать её в другую задачу из другой стадии, и даже вывести её значение. Но, похоже, я не правильно передаю её в качестве параметра в шаблон, и получаю эту ошибку:

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

Примечания

  1. Обратите внимание на форматирование: Когда вы передаёте массив объектов в качестве параметра в другой pipeline, убедитесь, что он сериализуется корректно. В данном случае используются двойные кавычки и запятые для отделения объектов.

  2. Именование заданий: Чтобы дополнительно настроить название и отображаемое имя задания ProcApp, применяется выражение format, что позволяет динамически формировать название на основе значения app.application.

  3. CLI для Azure DevOps: Для срабатывания второго pipeline вы можете использовать команду CLI Azure, что позволяет авторизовать и вызывать другой pipeline с нужными параметрами.

Этот подход должен помочь вам корректно передать массив объектов между этапами и получить необходимый результат в вашем сценарии.

Оцените материал
Добавить комментарий

Капча загружается...