Условия конвейера
Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019
В этой статье описываются условия, в которых выполняется этап, задание или шаг Azure Pipelines, а также способы указания различных условий. Дополнительные сведения о этапах, заданиях и шагах см. в разделе "Основные понятия" для Azure Pipelines.
По умолчанию задание или этап выполняется, если оно не зависит от другого задания или этапа, или если все его зависимости завершены и выполнены успешно. Это требование применяется не только к прямым зависимостям, но и к их косвенным зависимостям, вычисляемых рекурсивно.
По умолчанию шаг выполняется, если ничего в его задании еще не выполнено, и шаг, предшествующий его завершению.
Это поведение можно переопределить или настроить путем принудительного выполнения этапа, задания или шага, даже если предыдущая зависимость завершается сбоем или путем указания настраиваемого условия.
Примечание.
В этой статье рассматриваются возможности конвейера YAML. Для классических конвейеров можно указать некоторые условия, в которых выполняются задачи или задания в параметрах управления каждой задачи, а также в дополнительных параметрах задания в конвейере выпуска.
Условия выполнения этапа, задания или шага
В определении конвейера YAML можно указать следующие условия, в которых выполняется этап, задание или шаг:
Только если все предыдущие прямые и косвенные зависимости с одинаковым пулом агентов успешно выполнены. Если у вас есть разные пулы агентов, эти этапы или задания выполняются одновременно. Это условие по умолчанию, если условие не задано в YAML.
Даже если предыдущая зависимость завершается ошибкой, если выполнение не отменено. Используйте
succeededOrFailed()
в YAML для этого условия.Даже если предыдущая зависимость завершается ошибкой, и даже если выполнение отменено. Используйте
always()
в YAML для этого условия.Только если предыдущая зависимость завершается ошибкой. Используйте
failed()
в YAML для этого условия.
- Пользовательские условия.
По умолчанию этапы, задания и шаги выполняются, если все прямые и косвенные зависимости выполняются успешно. Это состояние совпадает с указанием condition: succeeded()
. Дополнительные сведения см. в статье об успешном выполнении функции состояния.
При указании condition
свойства для этапа, задания или шага вы перезаписываете значение по умолчанию condition: succeeded()
. Указание собственных условий может привести к выполнению этапа, задания или шага, даже если сборка отменена. Убедитесь, что условия, которые вы записываете, учитывают состояние родительской стадии или задания.
В следующем примере YAML показаны always()
условия и failed()
условия. Шаг в первом задании выполняется, даже если сбой зависимостей или сборка отменена. Второе задание выполняется только в том случае, если первое задание завершается ошибкой.
jobs:
- job: Foo
steps:
- script: echo Hello!
condition: always() # this step runs, even if the build is canceled
- job: Bar
dependsOn: Foo
condition: failed() # this job runs only if Foo fails
Можно также задать и использовать переменные в условиях. В следующем примере задаются и используются isMain
переменные для обозначения main
в качестве Build.SourceBranch
.
variables:
isMain: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')]
stages:
- stage: A
jobs:
- job: A1
steps:
- script: echo Hello Stage A!
- stage: B
condition: and(succeeded(), eq(variables.isMain, true))
jobs:
- job: B1
steps:
- script: echo Hello Stage B!
- script: echo $(isMain)
Внимание
Условия оцениваются, чтобы определить, следует ли начинать этап, задание или шаг. Поэтому ничего вычисляемого во время выполнения в этой единице работы доступно. Например, если у вас есть задание, которое задает переменную с помощью выражения среды выполнения с $[ ]
синтаксисом, эту переменную нельзя использовать в пользовательском условии в этом задании.
Настраиваемые условия
Если встроенные условия не соответствуют вашим потребностям, можно указать пользовательские условия. Условия записываются в виде выражений в определениях конвейера YAML.
Агент оценивает выражение, начиная с самой внутренней функции, и продолжается наружу. Окончательный результат — логическое значение, определяющее, должна ли задача, задание или этап выполняться. Полное руководство по синтаксису см. в разделе "Выражения".
Если любое из ваших условий позволяет выполнять задачу даже после отмены сборки, укажите разумное значение времени ожидания отмены, чтобы эти задачи имели достаточно времени для завершения после отмены выполнения пользователем.
Результаты условий при отмене сборки
Отмена сборки не означает, что все его этапы, задания или шаги перестают выполняться. Какие этапы, задания или шаги перестают выполняться, зависят от указанных условий и в какой точке выполнения конвейера вы отменили сборку. Если выполняется этап, задание или родитель шага, задача не выполняется независимо от его условий.
Этап, задание или шаг выполняются всякий раз, когда его условия оцениваются true
. Если условие не учитывает состояние родительского элемента задачи, задача может выполняться даже в том случае, если его родительский объект отменен. Чтобы управлять этапами, заданиями или шагами с условиями выполнения при отмене сборки, обязательно включите функцию проверки состояния задания в ваших условиях.
В следующих примерах показаны результаты различных условий, заданных на этапах, заданиях или шагах при отмене сборки.
Пример этапа 1
В следующем конвейере по умолчанию stage2
будет зависеть, stage1
но stage2
имеет condition
набор для выполнения всякий раз, когда исходная ветвь имеет main
значение независимо от stage1
состояния.
Если вы застроите сборку в main
ветви и отмените ее во время stage1
выполнения, по-прежнему выполняется, stage2
так как eq(variables['Build.SourceBranch'], 'refs/heads/main')
оценивается true
.
stages:
- stage: stage1
jobs:
- job: A
steps:
- script: echo 1; sleep 30
- stage: stage2
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
jobs:
- job: B
steps:
- script: echo 2
Пример этапа 2
В следующем конвейере stage2
зависит от stage1
по умолчанию. Задание B
в stage2
наборе condition
. Если вы застроите сборку в main
ветви и отмените ее во время stage1
выполнения, не выполняется, stage2
даже если она содержит задание, условие которого оценивается true
.
Причина заключается в том, что stage2
имеет значение по умолчанию condition: succeeded()
, которое оценивается false
при stage1
отмене. Таким образом, stage2
пропускается и ни одно из его заданий не выполняется.
stages:
- stage: stage1
jobs:
- job: A
steps:
- script: echo 1; sleep 30
- stage: stage2
jobs:
- job: B
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
steps:
- script: echo 2
Пример этапа 3
В следующем конвейере по умолчанию stage2
зависит от stage1
шага задания B
condition
.
Если вы застроите сборку в main
ветви и отмените ее во время stage1
выполнения, не выполняется, stage2
даже если он содержит шаг в задании B
, условие которого оценивается true
. Причина заключается в том, что stage2
пропускается в ответ на stage1
отмену.
stages:
- stage: stage1
jobs:
- job: A
steps:
- script: echo 1; sleep 30
- stage: stage2
jobs:
- job: B
steps:
- script: echo 2
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
Пример задания 1
В следующем конвейере YAML задание зависит от задания B
A
по умолчанию, но задание B
имеет condition
набор для выполнения при каждом запуске исходной ветви main
. Если вы застроите сборку в main
ветви и отмените ее во время выполнения задания A
, задание B
по-прежнему выполняется, так как eq(variables['Build.SourceBranch'], 'refs/heads/main')
оценивается true
.
jobs:
- job: A
steps:
- script: sleep 30
- job: B
dependsOn: A
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
steps:
- script: echo step 2.1
Если вы хотите, чтобы задание выполнялось только в случае успешного выполнения задания B
A
, а источник сборки — main
ветвь, condition
должен быть and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
.
Пример задания 2
В следующем конвейере задание B
зависит от задания A
по умолчанию. Если вы застроите сборку в main
ветви и отмените ее во время выполнения задания A
, задание B
не выполняется, даже если его шаг condition
имеет true
значение.
Причина заключается в том, что задание B
имеет значение по умолчанию condition: succeeded()
, которое оценивается false
при отмене задания A
. Таким образом, задание B
пропускается, и ни один из его шагов не выполняется.
jobs:
- job: A
steps:
- script: sleep 30
- job: B
dependsOn: A
steps:
- script: echo step 2.1
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main', succeeded())
Пример шага
Вы также можете иметь условия на шагах.
В следующем конвейере шаг 2.3 имеет condition
набор для запуска при каждом запуске исходной ветви main
. Если вы застроите сборку в main
ветви и отмените ее во время выполнения шагов 2.1 или 2.2, шаг 2.3 по-прежнему выполняется, так как eq(variables['Build.SourceBranch'], 'refs/heads/main')
оценивается true
.
steps:
- script: echo step 2.1
- script: echo step 2.2; sleep 30
- script: echo step 2.3
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
Параметры условия
В следующей таблице показаны примеры condition
параметров для получения различных результатов.
Примечание.
Release.Artifacts.{artifact-alias}.SourceBranch
эквивалентна Build.SourceBranch
.
Требуемый результат | Пример параметра условия |
---|---|
Запустите, если исходная ветвь является основной, даже если родительский или предыдущий этап, задание или шаг завершился сбоем или был отменен. | eq(variables['Build.SourceBranch'], 'refs/heads/main') |
Запустите, если исходная ветвь является основной и родительским или предыдущим этапом, заданием или шагом выполнена успешно. | and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) |
Запустите, если исходная ветвь не является основной, и родительский или предыдущий этап, задание или шаг успешно выполнен. | and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main')) |
Запустите ветви раздела пользователя, если родительский или предыдущий этап, задание или шаг выполнены успешно. | and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/')) |
Выполните сборки непрерывной интеграции (CI), если родительский или предыдущий этап, задание или шаг успешно выполнены. | and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) |
Запустите, если сборка была активирована политикой ветви для запроса на вытягивание, а родительский или предыдущий этап, задание или шаг завершился сбоем. | and(failed(), eq(variables['Build.Reason'], 'PullRequest')) |
Запуск для запланированной сборки, даже если родительский или предыдущий этап, задание или шаг завершился сбоем или отменен. | eq(variables['Build.Reason'], 'Schedule') |
Запустите, если переменная имеет значение true, даже если родительский или предыдущий этап, задание или шаг завершился сбоем или был отменен. | eq(variables['System.debug'], true) |
Примечание.
Можно задать условие для запуска, если переменная имеет значение NULL (пустая строка). Так как все переменные рассматриваются как строки в Azure Pipelines, пустая строка эквивалентна null
следующему конвейеру:
variables:
- name: testEmpty
value: ''
jobs:
- job: A
steps:
- script: echo testEmpty is blank
condition: eq(variables.testEmpty, '')
Параметры в условиях
Расширение параметров происходит до рассмотрения условий. Поэтому при объявлении параметра в том же конвейере, что и условие, можно внедрить параметр в условие. Скрипт в следующем yamL выполняется, так как parameters.doThing
имеет значение true.
parameters:
- name: doThing
default: true
type: boolean
steps:
- script: echo I did a thing
condition: and(succeeded(), ${{ eq(parameters.doThing, true) }})
В condition
предыдущем конвейере объединяются две функции: succeeded()
и ${{ eq(parameters.doThing, true) }}
. Функция succeeded()
проверяет, выполнен ли предыдущий шаг успешно. Функция возвращается succeeded()
true
из-за отсутствия предыдущего шага.
Функция ${{ eq(parameters.doThing, true) }}
проверяет, равен true
ли doThing
параметр. Так как значение doThing
по умолчанию равно true
, условие возвращается true
по умолчанию, если конвейер не задает другое значение.
Параметры шаблона в условиях
При передаче параметра в шаблон необходимо задать значение параметра в шаблоне или использовать templateContext для передачи параметра шаблону.
Например, следующий файл parameters.yml объявляет doThing
параметр и значение по умолчанию:
# parameters.yml
parameters:
- name: doThing
default: true # value passed to the condition
type: boolean
jobs:
- job: B
steps:
- script: echo I did a thing
condition: ${{ eq(parameters.doThing, true) }}
Код конвейера ссылается на шаблон parameters.yml . Выходные данные конвейера обусловлены I did a thing
тем, что параметр doThing
имеет значение true.
# azure-pipeline.yml
parameters:
- name: doThing
default: true
type: boolean
trigger:
- none
extends:
template: parameters.yml
Дополнительные примеры параметров шаблона см. в справочнике по использованию шаблона.
Выходные переменные задания, используемые в последующих условиях задания
Вы можете сделать переменную доступной для будущих заданий и указать ее в условии. Переменные, доступные для будущих заданий, должны быть помечены как выходные переменные с несколькими заданиями с помощью isOutput=true
следующего кода:
jobs:
- job: Foo
steps:
- bash: |
echo "This is job Foo."
echo "##vso[task.setvariable variable=doThing;isOutput=true]Yes" #set variable doThing to Yes
name: DetermineResult
- job: Bar
dependsOn: Foo
condition: eq(dependencies.Foo.outputs['DetermineResult.doThing'], 'Yes') #map doThing and check the value
steps:
- script: echo "Job Foo ran and doThing is Yes."
Переменные, созданные на шаге, используемом в последующих условиях шага
Вы можете создать переменную, доступную для будущих шагов, чтобы указать в условии. Переменные, созданные на основе шагов, доступны для будущих шагов по умолчанию и не должны быть помечены как переменные выходных данных с несколькими заданиями.
Есть некоторые важные моменты, которые следует отметить о переменных области , созданных на основе шагов.
- Переменные, созданные на шаге задания, относятся к шагам в том же задании.
- Переменные, созданные на шаге, доступны только в качестве переменных среды.
- Переменные, созданные на шаге, нельзя использовать на шаге, который определяет их.
В следующем примере показано создание переменной конвейера на шаге и использование переменной в условии и скрипте последующего шага.
steps:
# This step creates a new pipeline variable: doThing. This variable is available to subsequent steps.
- bash: |
echo "##vso[task.setvariable variable=doThing]Yes"
displayName: Step 1
# This step is able to use doThing, so it uses doThing in its condition
- script: |
# Access the variable from Step 1 as an environment variable.
echo "Value of doThing (as DOTHING env var): $DOTHING."
displayName: Step 2
condition: and(succeeded(), eq(variables['doThing'], 'Yes')) # or and(succeeded(), eq(variables.doThing, 'Yes'))
Вопросы и ответы
Как я могу активировать задание, если предыдущее задание было выполнено с проблемами?
Результат предыдущего задания можно использовать в условии. Например, в следующем YAML условие eq(dependencies.A.result,'SucceededWithIssues')
позволяет выполнять задание, так как задание B
A
выполнено успешно с проблемами.
jobs:
- job: A
displayName: Job A
continueOnError: true # next job starts even if this one fails
steps:
- script: echo Job A ran
- script: exit 1
- job: B
dependsOn: A
condition: eq(dependencies.A.result,'SucceededWithIssues') # targets the result of the previous job
displayName: Job B
steps:
- script: echo Job B ran
Я отменил свою сборку, но она все еще работает. Почему?
Эта проблема возникает, если условие, настроенное на этапе, не включает функцию проверки состояния задания. Чтобы устранить проблему, добавьте функцию проверки состояния задания в условие.
Если вы отменяете задание, пока оно находится на этапе очереди, но не выполняется, все задание отменяется, включая все остальные этапы. Дополнительные сведения см. в разделе о результатах условий, когда сборка отменена ранее в этой статье.