Условия конвейера

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

Я отменил свою сборку, но она все еще работает. Почему?

Эта проблема возникает, если условие, настроенное на этапе, не включает функцию проверки состояния задания. Чтобы устранить проблему, добавьте функцию проверки состояния задания в условие.

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