Поделиться через


Условия трубопровода

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022 | Azure DevOps Server 2020

В этой статье описываются различные условия, позволяющие выполнять этап, задание или шаг Azure Pipelines, а также как задать эти условия в определении конвейера YAML.

Примечание.

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

Условия выполнения этапа, задания или шага

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

По умолчанию шаг выполняется, если ничего в его задании еще не провалилось и шаг, непосредственно предшествующий, завершен. Дополнительные сведения о этапах, заданиях и шагах см. в разделе "Основные понятия" для Azure Pipelines.

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

Примечание.

Условия применяются ко всем предыдущим прямым и косвенным зависимостям с одинаковым пулом агентов. Этапы или задания в разных пулах агентов выполняются одновременно.

Условия, основанные на предыдущем состоянии зависимости, включают:

  • Выполнено: запустите только в том случае, если все предыдущие зависимости выполнены успешно. Это поведение по умолчанию, если условие не задано в YAML. Чтобы применить это условие, укажите condition: succeeded().
  • Выполнено успешно или завершилось сбоем: запуск, даже если предыдущая зависимость завершается ошибкой, если выполнение не отменено. Чтобы применить это условие, укажите condition: succeededOrFailed().
  • Всегда: запуск, даже если предыдущая зависимость завершается ошибкой, даже если выполнение отменено. Чтобы применить это условие, укажите condition: always().
  • Сбой. Запуск выполняется только в том случае, если предыдущая зависимость завершается ошибкой. Чтобы применить это условие, укажите condition: failed().

Внимание

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

Пример условия

В следующем примере YAML показаны always() условия и failed() условия. Первая задача скрипта в задании 1 имеет always условие, поэтому выполняется даже в случае сбоя зависимостей или отмены сборки. Во второй задаче скрипта exit job1 вызывает сбой задания job1.

Этапы конвейера выполняются последовательно по умолчанию, но задания могут выполняться параллельно. Свойство можно использовать dependsOn для явного определения зависимостей между этапами или заданиями.

Чтобы задать условия для задания, зависящее от результата другого задания, используйте dependsOn для определения зависимости. В следующем примере зависит от и выполняется job2 из-за job1job1 сбоя.

jobs:
- job: job1
  steps:
  - script: echo Hello!
    condition: always() # this step runs even if the build is canceled
  - script: |
      echo "This task will fail."
      exit job1 
- job: job2
  dependsOn: job1
  condition: failed() # this job runs only if job1 fails

Примечание.

Вы также можете использовать пользовательский интерфейс Azure Pipelines для выполнения зависимых этапов вручную при сбое родительского этапа. Дополнительные сведения см. в разделе "Запуск дочерних этапов" при сбое родительского этапа.

Настраиваемые условия

Если встроенные условия не соответствуют вашим потребностям, можно указать настраиваемые условия в виде выражений в определениях конвейера YAML.

Агент оценивает выражение, начиная с самой внутренней функции и переходя к внешним. Конечный результат — логическое значение, определяющее, следует ли запускать этап, задание или шаг. Полное руководство по синтаксису см. в разделе "Выражения".

Внимание

Условия оцениваются, чтобы определить, следует ли начинать этап, задание или шаг. Таким образом, ничто не вычисляется во время выполнения этапа, задания или шага доступно для использования в рамках этого же этапа, задания или шага. Например, если вы устанавливаете переменную в задании с помощью выражения среды выполнения с $[ ] синтаксисом, эту переменную нельзя использовать в условиях в этом задании.

Переменные в условиях

Переменные конвейера можно задать и использовать в условиях. Следующий конвейер задает isMain переменную и использует ее в условии, которое запускает этап B только в том случае, если исходная ветвь сборки имеет значение main.

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)

Можно задать условие для запуска, если переменная имеет значение NULL или пустая строка. Все переменные обрабатываются как строки в Azure Pipelines, поэтому пустая строка эквивалентна null следующему конвейеру:

variables:
- name: testEmpty
  value: ''

jobs:
  - job: A
    steps:
    - script: echo testEmpty is blank
    condition: eq(variables.testEmpty, '')

Выходные переменные задания, используемые в других условиях задания

Вы можете создать переменную в задании, которое другие задания могут указывать в условиях. Переменные, доступные для зависимых заданий, должны быть помечены как выходные переменные с несколькими заданиями с помощью isOutput=trueследующего кода:

jobs:
- job: A
  steps:
  - bash: |
      echo "This is job A."
      echo "##vso[task.setvariable variable=doThing;isOutput=true]Yes" #set variable doThing to Yes
    name: DetermineResult
- job: B
  dependsOn: A
  condition: eq(dependencies.A.outputs['DetermineResult.doThing'], 'Yes') #map doThing and check the value
  steps:
  - script: echo "Job A 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 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'))

Параметры условия для различных результатов

В следующей таблице показаны condition параметры для создания различных нужных результатов.

Требуемый результат Пример настройки условия
Запустите, если исходная ветвь имеет значение main, даже если родительский или предыдущий этап, задание или шаг завершился сбоем или был отменен. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Запустите, если исходная ветвь является main родительской или предыдущей стадией, заданием или шагом успешно выполнена. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Запустите, если исходная ветвь не mainявляется, а родительский или предыдущий этап, задание или шаг выполнены успешно. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Запустите ветви, user если родительский или предыдущий этап, задание или шаг успешно выполнен. 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')
Запустите, если System.debug для переменной задано значение true, даже если родительский или предыдущий этап, задание или шаг завершился сбоем или был отменен. eq(variables['System.debug'], true)

Примечание.

Release.Artifacts.{artifact-alias}.SourceBranch эквивалентна Build.SourceBranch.

Результаты обработки условий при отмене сборки

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

Этап, задание или шаг выполняются всякий раз, когда их условия равны 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

Если вы застроите сборку в main ветви и отмените ее во время stage1 выполнения, и его задания не выполняются вообще, stage2 даже если этап содержит задание, условие которого оценивается true.

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 от успешного завершения. Шаг внутри задания Bstage2 имеет condition набор для выполнения всякий раз, когда исходная ветвь .main

Если вы застроите сборку в main ветви и отмените ее во время stage1 выполнения, и задание не выполняется вообще, stage2 даже если задание BB содержит шаг, условие которого оценивается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 по-прежнему выполняется, так как оценка равна condition: eq(variables['Build.SourceBranch'], 'refs/heads/main').

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

Если задание должно выполняться только в случае успешного выполнения задания BA и источника mainсборки, необходимо задать значение conditionand(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')).

Пример задания 2

В следующем конвейере YAML задание B зависит от успешного выполнения задания A . Задание B имеет condition набор для запуска при успешном выполнении задания A и ветвь mainисточника сборки.

Если вы застроите сборку в main ветви и отмените ее во время выполнения задания A , задание B не выполняется, даже если он имеет тот condition , который оценивается true. Условие задания B оценивается из-за false того, что задание A не выполнено. Таким образом, задание B и его шаги пропускаются.

jobs:
- job: A
  steps:
  - script: sleep 30
- job: B
  dependsOn: A 
  steps:
    - script: echo step 2.1
  condition: and(eq(variables['Build.SourceBranch'], 'refs/heads/main'), succeeded())

Пример результата условия шага

Вы также можете задать условия на шагах. В следующем конвейере шаг 2.3 настроен для выполнения каждый раз, когда исходная ветка является condition.

Если вы запустите сборку в ветке 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 следующем примере объединяются две функции: succeeded() и ${{ eq(parameters.doThing, true) }}. Функция succeeded() проверяет, выполнен ли предыдущий шаг успешно. Эта функция также возвращается true , если предыдущего шага нет.

Функция ${{ eq(parameters.doThing, true) }} проверяет, равен ли параметр doThingtrue. Шаг сценария в следующем примере выполняется parameters.doThing из-за отсутствия предыдущего шага и true по умолчанию.

parameters:
- name: doThing
  default: true
  type: boolean

steps:
- script: echo I did a thing
  condition: and(succeeded(), ${{ eq(parameters.doThing, true) }})

Параметры шаблона в условиях

При передаче параметра в шаблон конвейера можно задать значение параметра в файле шаблона или использовать templateContext для передачи параметра в шаблон.

Следующий файл шаблона parameters.yml объявляет doThing параметр со значением true по умолчанию и использует параметр в условии задания.

# parameters.yml
parameters:
- name: doThing
  default: true
  type: boolean

jobs:
  - job: B
    steps:
    - script: echo I did a thing
    condition: ${{ eq(parameters.doThing, true) }}

Следующее azure-pipelines.yml определение конвейера ссылается на задание в файле шаблона parameters.yml . Выходные данные конвейера обусловлены I did a thing тем, что параметр doThing имеет значение true по умолчанию.

# azure-pipelines.yml

extends:
  template: parameters.yml

Дополнительные примеры параметров шаблона см. в справочнике по использованию шаблона.

Вопросы и ответы

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

Вы можете использовать результат предыдущего задания в условии. В следующем YAML условие eq(dependencies.A.result,'SucceededWithIssues') задает задание B для запуска после успешного выполнения задания A с проблемами.

jobs:
- job: A
  steps:
  - script: echo Job A ran
- job: B
  dependsOn: A
  condition: eq(dependencies.A.result,'SucceededWithIssues') # targets the result of the previous job 
  steps:
  - script: echo Job A had issues

Почему сборка по-прежнему выполняется после отмены?

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