В моем конвейере 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) своим жестко заданным адресом электронной почты, я получаю электронное письмо. Есть идеи?





Как упоминал @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')
Как упоминалось в обновлении к исходному вопросу, добавив новую переменную и используя условие, я могу выполнить поставленную задачу условно. Чего я не понимаю, так это того, как работает добавление новой переменной для перехвата параметра шаблона. Не могли бы вы уточнить или указать мне на документацию?
В этой части я просто хотел сказать вам, что оценка значения параметра шаблона, например condition: ${{ eq(parameters['preDeployApprovalRequired'], 'true') }}, не будет работать должным образом. Если вам нужно передать значение параметра в шаблон и оценить его значение, вам нужно будет определить новую переменную с помощью newVar: ${{parameters.preDeployApprovalRequired}} и оценить с помощью condition: eq(variables['newVar'], 'true'); или просто вычислите переменную в группе переменных, например condition: eq(variables['PreDeployApprovalRequired'], 'true').
Переменная из группы переменных в библиотеке может обрабатываться только во время выполнения. Они не имеют значения в выражениях шаблонов (
${{if}}), которые обрабатываются во время компиляции. Вы можете рассмотреть возможность использования шаблона переменной (.yml) с выражениями шаблона или использования свойстваconditionзадачи с выражениями времени выполнения.