Условие конвейера Azure Devops Yaml не выполняется, когда переменная поступает из библиотеки

В моем конвейере YAML Azure DevOps развертывание веб-сайта было закодировано в шаблоне многократного использования. Этот шаблон выполнит шаг в зависимости от значения входного параметра:

# Template 'deployTemplate.yml'
parameters:
- name: preDeployApprovalRequired
  type: string

jobs: 
- job: PrintVariables
  steps:
  - ${{if eq(parameters.preDeployApprovalRequired, 'true')}}:
      - powershell: | 
          Write-Host "Pre deploy required: '${{parameters.preDeployApprovalRequired}}'"
    - ${{else}}:
      - powershell: | 
          Write-Host "Pre deploy NOT required: '${{parameters.preDeployApprovalRequired}}'"

и этот шаблон называется следующим образом

# Pipeline
# Beginning of pipeline is omitted, works as intended
- stage: Development
  variables:
  - group: Development  #Reference to Library
  
  jobs:
  - template: deployTemplate.yml
    parameters:
      preDeployApprovalRequired: $(PreDeployApprovalRequired)

Здесь $(PreDeployApprovalRequired) поступает из библиотеки под названием «Разработка». Я проверил, что значение равно true, и, как следует из приведенного выше кода, значение будет напечатано в задаче Powershell. При запуске конвейера я вижу на выходе: Pre deploy NOT required: 'true'. Почему?? Чтобы сделать ситуацию еще более загадочной, если я изменю последнюю строку в конвейере на preDeployApprovalRequired: 'true' или preDeployApprovalRequired: true (без кавычек вокруг слова true), т. е. значение жестко запрограммировано в конвейере и не поступает из библиотеки, выходные данные это Pre deploy required: 'true', как и ожидалось.

Есть идеи о том, как я могу условно выполнить задачу на основе значения в библиотеке?

-------------- Обновлять --------------

Исходный вопрос показал только надуманный пример: на самом деле я хочу добиться условного вызова задачи ManualValidation@0. Мотивация использования этой задачи и то, почему я действительно хочу, чтобы переменная была взята из библиотеки, описаны в связанном с этим вопросе. На основании предложений, которые были сделаны на данный момент, я изменил код на следующий:

# Template 'deployTemplate.yml'
parameters:
- name: preDeployApprovers
  type: string

jobs: 
- job: WaitForValidation
  pool: server
  variables: 
    approvers: ${{parameters.preDeployApprovers}}
  steps:
  - task: ManualValidation@0
    condition: ne(variables['approvers'],'')
    inputs: 
      notifyUsers: | 
       $(approvers)
       onTimeout: reject

Хорошая новость в том, что условие работает, хотя я не совсем понимаю, почему добавление отдельной переменной approvers работает; Я ожидаю, что он тоже расширится parameters.preDeployApprovers, что неизвестно во время компиляции. Плохая новость заключается в том, что пользователи не уведомляются. Когда я заменяю синтаксис макроса $(approvers) своим жестко заданным адресом электронной почты, я получаю электронное письмо. Есть идеи?

Переменная из группы переменных в библиотеке может обрабатываться только во время выполнения. Они не имеют значения в выражениях шаблонов (${{if}}), которые обрабатываются во время компиляции. Вы можете рассмотреть возможность использования шаблона переменной (.yml) с выражениями шаблона или использования свойства condition задачи с выражениями времени выполнения.

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

Ответы 2

Как упоминал @Alvin Zhao - MSFT, переменная из группы переменных в библиотеке может обрабатываться только во время выполнения с использованием синтаксиса макроса $(foo) или выражения времени выполнения $[variables.foo].

Проблема в том, что выражения шаблона ${{ ... }} обрабатываются во время компиляции, до начала выполнения. Вот почему ваше ${{ if ... }} состояние всегда оценивается как false.

Вы можете исправить это, используя вместо этого условие.

Вместо:

- ${{if eq(parameters.preDeployApprovalRequired, 'true')}}:
  - powershell: | 
      Write-Host "Pre deploy required: '${{parameters.preDeployApprovalRequired}}'"

Пытаться

- powershell: | 
    Write-Host "Pre deploy required: '${{parameters.preDeployApprovalRequired}}'"
  condition: eq(parameters['preDeployApprovalRequired'], 'true')
Ответ принят как подходящий

Проблема в том, что значение переменной из группы переменных в библиотеке обрабатывается во время выполнения, и мы не должны использовать условные вставки для оценки таких переменных, которые используют синтаксис выражений шаблона, обрабатываемых во время компиляции, прежде чем начинается время выполнения. Посмотрите это, чтобы помочь нам Понять синтаксис переменных.

Для этого вы можете рассмотреть возможность определения набора переменных в шаблоне variables.yml вместо использования группы переменных; эта опция расширит одну задачу powershell во время компиляции;

конвейер.yml

stages:
- stage: Development
  variables:
  # - group: Development  # Reference to Library
  - template: variables.yml # Reference to template variables.yml
  
  jobs:
  - template: deployTemplate.yml
    parameters:
      preDeployApprovalRequired: ${{variables.PreDeployApprovalRequired}} # Pass the vaule of the varialbe PreDeployApprovalRequired from variables.yml in TEMPLATE EXPRESSION syntax

переменные.yml

# Template 'variables.yml'

variables:
  PreDeployApprovalRequired : true

Или, если вы предпочитаете использовать группы переменных, вам нужно будет добавить свойство condition задачи/задания/этапа с выражениями времени выполнения вместо использования условных вставок; и нам также необходимо определить новую переменную(и) в шаблоне, чтобы перехватывать значения параметров, которые будут переданы, поскольку параметры шаблона могут использоваться только в выражениях шаблона, а значение ${{parameters.preDeployApprovalRequired}} равно '' во время компиляции; с другой стороны, это расширит две задачи powershell во время компиляции, но пропустит ту, состояние которой оценивается как false во время выполнения;

DeployTemplate.yml

# Template 'deployTemplate.yml'
parameters:
- name: preDeployApprovalRequired
  type: string
  default: ''

jobs: 
- job: PrintVariables
  variables:
    newVar: ${{parameters.preDeployApprovalRequired}}
  steps:
  # - ${{if eq(parameters.preDeployApprovalRequired, 'true')}}:
    - powershell: | 
        Write-Host "Pre deploy required: $(newVar)"
      condition: eq(variables['newVar'], 'true')
  # - ${{else}}:
    - powershell: | 
        Write-Host "Pre deploy NOT required: $(newVar)"
      condition: eq(variables['newVar'], 'false')

Если применимо, вы можете напрямую оценить переменную $(PreDeployApprovalRequired) из группы переменных Deployment в выражениях времени выполнения внутри свойства condition без необходимости передавать и получать значение из параметра шаблона.

# Template 'deployTemplate.yml'
parameters:
- name: preDeployApprovalRequired
  type: string
  default: ''

jobs: 
- job: PrintVariables
  steps:
    - powershell: | 
        Write-Host "Pre deploy required: $(PreDeployApprovalRequired)"
      condition: eq(variables['PreDeployApprovalRequired'], 'true')
    - powershell: | 
        Write-Host "Pre deploy NOT required: $(PreDeployApprovalRequired)"
      condition: eq(variables['PreDeployApprovalRequired'], 'false')

Как упоминалось в обновлении к исходному вопросу, добавив новую переменную и используя условие, я могу выполнить поставленную задачу условно. Чего я не понимаю, так это того, как работает добавление новой переменной для перехвата параметра шаблона. Не могли бы вы уточнить или указать мне на документацию?

SimonAx 19.06.2024 09:48

В этой части я просто хотел сказать вам, что оценка значения параметра шаблона, например condition: ${{ eq(parameters['preDeployApprovalRequired'], 'true') }}, не будет работать должным образом. Если вам нужно передать значение параметра в шаблон и оценить его значение, вам нужно будет определить новую переменную с помощью newVar: ${{parameters.preDeployApprovalRequired}} и оценить с помощью condition: eq(variables['newVar'], 'true'); или просто вычислите переменную в группе переменных, например condition: eq(variables['PreDeployApprovalRequired'], 'true').

Alvin Zhao - MSFT 19.06.2024 10:49

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