Определение условий

Azure DevOps Services | Azure DevOps Server 2022 г. - Azure DevOps Server 2019 г. | TFS 2018

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

Примечание

В Microsoft Team Foundation Server (TFS) 2018 и предыдущих версий конвейеры сборки и выпуска называются определениями, выполнения называются сборками, подключения к службам называются конечными точками служб, этапы называются средами, а задания называются этапами.

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

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

  • Даже если произошел сбой предыдущей зависимости, если запуск не отменен. Используйте succeededOrFailed() в YAML для этого условия.

  • Даже если произошел сбой предыдущей зависимости и даже если запуск отменен. Используйте always() в YAML для этого условия.

  • Только после сбоя предыдущей зависимости. Используйте failed() в YAML для этого условия.

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

По умолчанию шаги, задания и этапы выполняются, если все предыдущие шаги или задания выполнены успешно. Это так, как если бы вы указали "condition: succeeded()" (см . раздел Функции состояния задания).

jobs:
- job: Foo

  steps:
  - script: echo Hello!
    condition: always() # this step will always run, even if the pipeline is canceled

- job: Bar
  dependsOn: Foo
  condition: failed() # this job will only run if Foo fails

Переменные также можно использовать в условиях.

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 не поддерживается в TFS.

Примечание

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

Включение настраиваемого условия

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

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

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

Поведение конвейера при отмене сборки

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

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

Рассмотрим несколько примеров.

В этом конвейере по умолчанию stage2 зависит от stage1 и stage2 имеет condition набор. stage2 Выполняется, только если исходная ветвь имеет значение main.

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

Если вы ставите сборку в очередь в main ветвь и отменяете ее во время stage1 выполнения, stage2 будет по-прежнему trueвыполняться, так как eq(variables['Build.SourceBranch'], 'refs/heads/main') имеет значение .

В этом конвейере stage1 зависит от stage2. Задание B имеет condition набор для него.

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

Если вы ставите сборку в очередь в main ветвь и отменяете ее во время stage1 выполнения, stage2не будет выполняться, даже если она содержит задание A , условие которого оценивается как true. Причина заключается в том, что stage2 имеет значение по умолчанию condition: succeeded(), которое имеет false значение при stage1 отмене. Таким образом, stage2 пропускается, и ни одно из его заданий не выполняется.

Предположим, у вас есть следующий конвейер YAML. Обратите внимание, что по умолчанию stage2 зависит от stage1 и , script: echo 2 для которого condition задано значение .

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')

Если вы ставите сборку main в очередь в ветвь и отменяете ее во время stage1 выполнения, stage2не будет выполняться, даже если она содержит шаг в задании B , условие которого оценивается как true. Причина в том, что stage2 пропускается в ответ на отмену stage1 .

Чтобы предотвратить выполнение этапов, заданий или шагов с conditions при отмене сборки, убедитесь, что при записи учитывается состояние родительского conditionsэлемента . Дополнительные сведения см. в разделе Функции состояния задания.

Примеры

Запуск для главной ветви, даже если она отменена, даже в случае сбоя

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')

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

Всегда выполняется, если переменная имеет значение 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.

в condition конвейере объединяет две функции: succeeded() и eq('${{ parameters.doThing }}', true). Функция succeeded() проверяет, успешно ли выполнен предыдущий шаг. Функция succeeded() возвращает значение true, так как предыдущего шага не было.

Функция eq('${{ parameters.doThing }}', true) проверяет, равен trueли параметр doThing . Так как значение по умолчанию для doThing равно true, условие возвращает значение 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
parameters:
- name: doThing
  default: true # value passed to the condition
  type: boolean

jobs:
  - job: B
    steps:
    - script: echo I did a thing
    condition: ${{ if eq(parameters.doThing, true) }}
# azure-pipeline.yml
parameters:
- name: doThing
  default: true 
  type: boolean

trigger:
- none

extends:
  template: parameters.yml

Выходные данные этого конвейера обусловлены I did a thing тем, что параметр doThing имеет значение true.

Использование выходной переменной из задания в условии в последующем задании

Вы можете сделать переменную доступной для будущих заданий и указать ее в условии. Переменные, доступные для будущих заданий, должны быть помечены как выходные переменные с несколькими заданиями с помощью 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."

Использование переменной конвейера, созданной на шаге, в условии на последующем шаге

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

Существует несколько важных моментов, которые следует отметить в отношении приведенного выше подхода и области.

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

Ниже приведен пример создания переменной конвейера на шаге и использования переменной в условии и скрипте последующего шага.

steps:

# This step creates a new pipeline variable: doThing. This variable will be available to subsquent steps.
- bash: |
    echo "##vso[task.setvariable variable=doThing]Yes"
  displayName: Step 1

# This step is able to use doThing, so it uses it in its condition
- script: |
    # You can 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') позволяет выполнять задание, так как задание 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

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

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

Узнайте больше о поведении конвейера при отмене сборки.