Динамическое заполнение DependsOn в задании Yaml Azure DevOps

Конвейеры YAML не поддерживают утверждения до и после развертывания, которые можно добавлять динамически. Я нашел способ частично добиться этого, см. последнее обновление моего предыдущего вопроса ТАК. В итоге; Я создал шаблон YAML с 3 заданиями; первое и последнее задания — это условные задания, в которых используется ManualValidation@0 в зависимости от переменной в группе переменных, а второе задание — это фактическое развертывание веб-приложения.

Следующий шаг — сделать этот подход более общим, представив шаблон YAML, который принимает jobList в качестве параметра и условно вставляет задание перед развертыванием и после развертывания. Этот шаблон выглядит как

# File: deploy.yml
parameters:
- name: preDeployApprovers
  type: string
  default: ''
- name: postDeployApprovers
  type: string
  default: ''
- name: deployJobs
  type: jobList
  default: []

jobs:
  - ${{ if ne(parameters.preDeployApprovers, '')}}:
    - template: wait-for-manual-approval.yml
      parameters:
        jobName: AwaitPreDeployApproval
        approvers: ${{parameters.preDeployApprovers}}
        instructions: Approve or reject.
        dependsOn:
    
    # Inspired by 
    # https://stackoverflow.com/questions/63256692/is-it-possible-to-pass-a-template-with-a-list-of-jobs-to-a-joblist-type-param
  - ${{ each job in parameters.deployJobs }}:  
    - ${{ each pair in job }}:
        ${{ if ne(pair.key, 'steps') }}:
          ${{ pair.key }}: ${{ pair.value }}
      ${{ if ne(parameters.preDeployApprovers, '')}}:
        dependsOn: [AwaitPreDeployApproval] # POI 1
      steps:
      - ${{ job.steps }} 
      
  - ${{ if ne(parameters.postDeployApprovers, '')}}:
    - template: wait-for-manual-approval.yml
      parameters:
        jobName: AwaitPostDeployApproval
        approvers: ${{parameters.postDeployApprovers}}
        instructions: Approve or reject.
        dependsOn: ${{join(',',parameters.deployJobs)}} # POI 2. Current solution does NOT work

который ссылается на файл wait-for-manual-approval.yml:

#File: wait-for-manual-approval.yml
parameters:
  - name: jobName
    type: string
  - name: approvers
    type: string
    default: ''
  - name: instructions
    type: string
    default: 'Approve or reject'
  - name: dependsOn
    type: object
    default: []
  
jobs:
  - job: ${{parameters.jobName}}
    ${{ if parameters.dependsOn }}:
      dependsOn: ${{ parameters.dependsOn }}
    displayName: Wait for manual approval after deployment
    pool: server
    timeoutInMinutes: 240 #4 hours. 
   
    steps:
    - task: ManualValidation@0        
      condition: ne(variables['${{parameters.approvers}}'], '')
      inputs:
        notifyUsers: |
          $(${{parameters.approvers}})
        instructions: ${{parameters.instructions}}
        onTimeout: reject

Точки интереса (POI)

  • POI 1. В зависимости от параметра preDeployApprovers одобрение предварительного развертывания будет добавлено в развернутый шаблон. Если этот параметр имеет значение, отличное от значения по умолчанию, фактические задания развертывания должны дождаться завершения утверждения предварительного развертывания («AwaitPreDeployApproval»), следовательно, существует условие dependsOn. Этот подход основан на ответе на другой ТАК вопрос.
  • POI 2: Для всех остальных заданий необходимо дождаться утверждения после развертывания.

Способ предоставления dependsOn в качестве параметра для файла wait-for-manual-approval.yml во многом основан на этом посте.

Точка интереса 2 — источник моей головной боли, она не работает. В загруженном мной расширенном шаблоне нет оператора dependsOn для задания после развертывания. Я попробовал жестко запрограммировать имя одного из заданий, и это сработало, но чтобы такой шаблон был полезен, мне нужен способ извлечения названий заданий, которые находятся в параметрах deployJobs. Какие-либо предложения?

Привет, Саймон! Когда задание зависит от нескольких заданий, свойство dependsOn должно быть массивом [], а не строкой 'job1,job2'

Alvin Zhao - MSFT 25.06.2024 14:18

И все расширенные deployJobs могут работать параллельно и должны зависеть от [AwaitPreDeployApproval], верно?

Alvin Zhao - MSFT 25.06.2024 14:23

@AlvinZhao-MSFT, ваше предположение верно, все задания в DeployJobs могут выполняться параллельно. Что касается другого вашего комментария, когда я меняю de dependsOn на dependsOn: '[${{join(',',parameters.deployJobs)}}]', VS Code говорит: «плохой отступ записи сопоставления»

SimonAx 25.06.2024 14:39

@SimonAx, вы используете неправильный синтаксис для преобразования parameters.deployJobs в массив. Пожалуйста, проверьте мой ответ.

Rui Jarimba 25.06.2024 14:40

Привет @SimonAx, я считаю, что решение RUI по использованию dependsOn: ${{ parameters.deployJobs.*.job }} для AwaitPostDeployApproval работы должно подойти вам. См. документ Фильтрованный массив.

Alvin Zhao - MSFT 25.06.2024 14:46

Исправлена ​​проблема «плохого отступа» путем добавления канала и помещения значения в следующую строку, но теперь проблема заключается в следующем: «Этап... задание AwaitPostDeployApproval зависит от неизвестного задания '[]'» . Я могу себе представить, почему это происходит, [${{join(',',parameters.deployJobs)}}] вероятно, не понимает названия работы.

SimonAx 25.06.2024 14:48

Отличные новости, это работает!

SimonAx 25.06.2024 14:53
Функция join возвращает одну строку, а не массив. Кроме того, сложные объекты преобразуются в пустую строку.
Rui Jarimba 25.06.2024 14:53

Да, верно, он не объединяет и не фильтрует только имена должностей. Я проверил красивое и аккуратное предложение @RuiJarimba. Синтаксис YAML расширен, как и ожидалось. Пожалуйста, дайте нам знать, если это работает и для вас. Оцените ваши усилия и идеи, RUI.

Alvin Zhao - MSFT 25.06.2024 14:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упоминал @Alvin Zhao - MSFT, свойство dependsOn должно быть массивом [], а не строкой, если ваша работа имеет несколько зависимостей.

функцию join нельзя использовать в этом случае, потому что:

  • Возвращает одну строку, а не массив
  • Сложные объекты, такие как задание, преобразуются в пустую строку.

Итак, вместо:

dependsOn: ${{join(',',parameters.deployJobs)}}

Попробуйте использовать отфильтрованный массив :

dependsOn: ${{ parameters.deployJobs.*.job }}

Объяснение:

  • parameters.deployJobs.*.job сообщает системе, что она должна работать с parameters.deployJobs как с отфильтрованным массивом, а затем выбрать свойство job.

Полный рабочий пример

trigger: none

parameters:
  - name: deployJobs
    type: jobList
    default:
      - job: A
        displayName: Job A
        steps:
          - script: echo "Hello from Job A"
      - job: B
        displayName: Job B
        steps:
          - script: echo "Hello from Job B"
      - job: C
        displayName: Job C
        steps:
          - script: echo "Hello from Job C"

jobs:
  - ${{ parameters.deployJobs }}

  - job: D
    displayName: Job D
    dependsOn: ${{ parameters.deployJobs.*.job }}
    steps:
      - script: echo "Hello from Job D"

Другие вопросы по теме