Especificar condições

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Você pode especificar as condições sob as quais cada fase, trabalho ou etapa é executado. Por padrão, um trabalho ou fase será executado se não depender de nenhum outro trabalho ou fase, ou se todos os trabalhos ou fases dos quais depende forem concluídos sem erros. Isso inclui não apenas dependências diretas, mas também suas dependências, computadas recursivamente. Por padrão, uma etapa será executada se nenhum erro ocorreu no trabalho e a etapa imediatamente anterior concluiu. Você pode personalizar esse comportamento ao especificar uma condição personalizada ou ao forçar a execução de uma fase, trabalho ou etapa, mesmo que uma dependência anterior falhe.

Você pode especificar condições sob as quais uma etapa, trabalho ou estágio será executado.

  • Somente quando todas as dependências diretas e indiretas anteriores com o mesmo pool de agentes tiverem sido bem-sucedidas. Se houver pools de agentes diferentes, esses fases ou trabalhos serão executados simultaneamente. Esse é o padrão se não há nenhuma condição definida no YAML.

  • Mesmo que uma dependência anterior tenha falhado, a menos que a execução tenha sido cancelada. Use succeededOrFailed() no YAML para essa condição.

  • Mesmo que uma dependência anterior tenha falhado, mesmo que a execução tenha sido cancelada. Use always() no YAML para essa condição.

  • Somente quando uma dependência anterior tiver falhado. Use failed() no YAML para essa condição.

  • Condições personalizadas

Por padrão, etapas, trabalhos e estágios serão executados se todas as dependências diretas e indiretas tiverem sido bem-sucedidas. É como se você tivesse especificado "condition: succeeded()" (confira função de status com êxito).

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

Você também pode usar variáveis em condições.

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)

As condições são avaliadas para decidir se deseja iniciar uma fase, um trabalho ou uma etapa. Isso significa que nada calculado no runtime dentro dessa unidade de trabalho estará disponível. Por exemplo, se você tiver um trabalho que define uma variável usando uma expressão de runtime usando a sintaxe $[ ], não poderá usar essa variável em sua condição personalizada.

O YAML não é compatível com o TFS.

Observação

Ao especificar sua própria propriedade condition para uma fase/trabalho/etapa, você substitui seu padrão condition: succeeded(). Isso pode levar à fase/trabalho/execução da etapa, mesmo que o build seja cancelado. Certifique-se de levar em conta o estado da fase pai/trabalho ao escrever suas próprias condições.

Habilitar uma condição personalizada

Se as condições embutidas não atenderem às suas necessidades, é possível especificar condições personalizadas.

As condições são escritas como expressões em pipelines do YAML. O agente avalia a expressão começando com a função mais interna até chegar na mais externa. O resultado final é um valor booliano que determina se a tarefa, o trabalho ou a fase deve ser executado ou não. Consulte o artigo expressões para obter um guia completo da sintaxe.

Alguma de suas condições possibilita que a tarefa seja executada mesmo depois que a compilação é cancelada por um usuário? Nesse caso, especifique um valor razoável de tempo limite de cancelamento para que esses tipos de tarefas tenham tempo suficiente de concluir após o usuário cancelar uma execução.

Comportamento do pipeline quando o build é cancelado

Quando um build é cancelado, isso não significa que todas as fases, trabalhos ou etapas param de ser executados. A decisão depende da fase, do trabalho ou da etapa conditions especificada e em que ponto da execução do pipeline você cancelou o build.

Se sua condição não levar em conta o estado do pai da fase/trabalho/etapa, se a condição for avaliada como true, sua fase, trabalho ou etapa será executado, mesmo que seu pai seja cancelado. Se o pai for ignorado, a fase, o trabalho ou a etapa não serão executados.

Vejamos alguns exemplos.

Nesse pipeline, por padrão, stage2 depende de stage1 e stage2 tem um conjunto condition. stage2 só é executado quando o branch de origem é 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

Se você enfileirar um build no branch main e cancelá-lo enquanto stage1 estiver em execução, stage2 ainda será executado, pois eq(variables['Build.SourceBranch'], 'refs/heads/main') será avaliado como true.

Nesse pipeline, stage2 depende de stage1. O trabalho B tem um conjunto condition para ele.

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

Se você enfileirar um build no branch main e cancelá-lo enquanto stage1 estiver em execução, stage2não será executado, mesmo que ele contenha um trabalho B cuja condição seja avaliada como true. O motivo é que stage2 tem o padrão condition: succeeded(), que é avaliado como false quando stage1 é cancelado. Portanto, stage2 é ignorado e nenhum de seus trabalhos é executado.

Digamos que você tenha o pipeline YAML a seguir. Observe que, por padrão, stage2 depende de stage1 e que script: echo 2 tem um condition definido para ele.

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

Se você enfileirar um build no branch main e cancelá-lo enquanto stage1 estiver em execução, stage2não será executado, mesmo que ele contenha uma etapa no trabalho B cuja condição é avaliada como true. O motivo é que stage2 é ignorado em resposta ao cancelamento de stage1.

Para impedir que fases, trabalhos ou etapas com conditions sejam executados quando um build for cancelado, considere o estado do pai ao gravar o conditions. Para obter mais informações, confira Funções de status de trabalho.

Exemplos

Executar para a ramificação principal, mesmo se cancelado, mesmo se estiver falhando

eq(variables['Build.SourceBranch'], 'refs/heads/main')

Executar para a ramificação principal, se tiver êxito

and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))

Executar se a ramificação não for a principal, se tiver êxito

and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))

Executar para ramificações de tópico do usuário, se tiver êxito

and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))

Executar para ramificações de CI (integração contínua) se tiver êxito

and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))

Executar se o build for executado por uma política de ramificação para uma solicitação de pull, se estiver falhando

and(failed(), eq(variables['Build.Reason'], 'PullRequest'))

Execute se o build estiver agendado, mesmo se estiver falhando, mesmo que cancelado

eq(variables['Build.Reason'], 'Schedule')

Release.Artifacts.{artifact-alias}.SourceBranch é equivalente a Build.SourceBranch.

Sempre execute se uma variável estiver definida como true, mesmo se for cancelada, mesmo se estiver falhando

eq(variables['System.debug'], true)

Executar se uma variável for nula (cadeia de caracteres vazia)

Como todas as variáveis são tratadas como cadeias de caracteres no Azure Pipelines, uma cadeia de caracteres vazia é equivalente a null neste pipeline.

variables:
- name: testEmpty
  value: ''

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

Usar um parâmetro de modelo como parte de uma condição

Quando você declara um parâmetro no mesmo pipeline em que há uma condição, a expansão do parâmetro ocorre antes que as condições sejam consideradas. Nesse caso, é possível inserir os parâmetros dentro das condições. O script neste arquivo YAML será executado porque parameters.doThing é verdadeiro.

O condition no pipeline combina duas funções: succeeded() e eq('${{ parameters.doThing }}', true). A função succeeded() verifica se a etapa anterior foi bem-sucedida. A função succeeded() retorna true porque não havia nenhuma etapa anterior.

A função eq('${{ parameters.doThing }}', true) verifica se o parâmetro doThing é igual a true. Como o valor padrão de doThing é true, a condição retornará true por padrão, a menos que um valor diferente seja definido no pipeline.

Para mais exemplos de parâmetro de modelo, confira Tipos e uso de modelo.

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

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

Ao passar um parâmetro para um modelo, você precisa definir o valor do parâmetro em seu modelo ou usar templateContext para passar propriedades para modelos.

# 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) }}
# azure-pipeline.yml
parameters:
- name: doThing
  default: true 
  type: boolean

trigger:
- none

extends:
  template: parameters.yml

A saída desse pipeline é I did a thing porque o parâmetro doThing é true.

Usar a variável de saída de um trabalho em uma condição de um trabalho subsequente

Você pode disponibilizar uma variável para trabalhos futuros e especificá-la em uma condição. As variáveis disponíveis para trabalhos futuros devem ser marcadas como variáveis de saída de vários trabalhos usando 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."

Usar a variável de pipeline criada em uma etapa, em uma condição de uma etapa subsequente

Você pode disponibilizar uma variável para etapas futuras e especificá-la em uma condição. Por padrão, as variáveis criadas com base em uma etapa estão disponíveis para etapas futuras e não precisam ser marcadas como variáveis de saída de vários trabalhos usando isOutput=true.

Há algumas coisas importantes a serem observadas em relação à abordagem e ao escopo acima:

  • As variáveis criadas em uma etapa em um trabalho terão como escopo as etapas no mesmo trabalho.
  • As variáveis criadas em uma etapa só estarão disponíveis nas etapas subsequentes como variáveis de ambiente.
  • As variáveis criadas em uma etapa não podem ser usadas na etapa que as define.

Abaixo está um exemplo de criação de uma variável de pipeline em uma etapa e o uso da variável em uma condição e script de uma etapa subsequente.

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

Perguntas frequentes

Como posso disparar um trabalho se um trabalho anterior concluir com problemas?

Você pode usar o resultado do trabalho anterior. Por exemplo, neste arquivo YAML, a condição eq(dependencies.A.result,'SucceededWithIssues') permite que o trabalho seja executado porque o Trabalho A teve êxito com problemas.

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

Cancelei minha compilação, mas ela ainda está em execução. O que está acontecendo?

Você terá esse problema se a condição configurada na fase não incluir uma função de verificação de status do trabalho. Para resolver o problema, adicione uma função de verificação de status do trabalho à condição. Se você cancelar um trabalho enquanto ele estiver na fila, mas não estiver em execução, todo o trabalho será cancelado, incluindo todos os outros estágios.

Saiba mais sobre o comportamento de um pipeline quando um build é cancelado.