Compartilhar via


Condições da tubulação

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

Este artigo descreve as condições sob as quais um estágio, trabalho ou etapa do Azure Pipelines é executado e como especificar condições diferentes. Para obter mais contexto sobre estágios, trabalhos e etapas, consulte Principais conceitos para Pipelines do Azure.

  • Por padrão, um trabalho ou estágio é executado se não depender de nenhum outro trabalho ou estágio, ou se todas as suas dependências forem concluídas e bem-sucedidas. Esse requisito se aplica não apenas às dependências diretas, mas às suas dependências indiretas, calculadas recursivamente.

  • Por padrão, uma etapa é executada se nada em seu trabalho falhar ainda e a etapa imediatamente anterior a ela for concluída.

Você pode substituir ou personalizar esse comportamento forçando a execução de um estágio, trabalho ou etapa mesmo que uma dependência anterior falhe, ou especificando uma condição personalizada.

Observação

Este artigo discute os recursos de pipeline YAML. Para pipelines clássicos, você pode especificar algumas condições sob as quais as tarefas ou trabalhos são executados nas Opções de controle de cada tarefa e nas opções adicionais para um trabalho em um pipeline de versão.

Condições sob as quais um estágio, trabalho ou etapa é executado

Na definição de pipeline YAML, você pode especificar as seguintes condições sob as quais um estágio, trabalho ou etapa é executado:

  • Somente quando todas as dependências diretas e indiretas anteriores com o mesmo pool de agentes forem bem-sucedidas. Se você tiver pools de agentes diferentes, esses estágios ou trabalhos serão executados simultaneamente. Essa condição será o padrão se nenhuma condição estiver definida no YAML.

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

  • Mesmo se uma dependência anterior falhar e mesmo se a execução for cancelada. Use always() no YAML para essa condição.

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

  • Condições personalizadas.

Por padrão, estágios, trabalhos e etapas são executados se todas as dependências diretas e indiretas forem bem-sucedidas. Esse status é o mesmo que especificar condition: succeeded(). Para obter mais informações, consulte Função de status bem-sucedida.

Ao especificar uma condition propriedade para um estágio, trabalho ou etapa, você substitui o padrão condition: succeeded(). Especificar suas próprias condições pode fazer com que seu estágio, trabalho ou etapa seja executado mesmo se a compilação for cancelada. Certifique-se de que as condições que você escreve levam em conta o estado do estágio pai ou do trabalho.

O exemplo YAML a seguir mostra as always() condições e failed() . A etapa no primeiro trabalho é executada mesmo se as dependências falharem ou a compilação for cancelada. O segundo trabalho é executado somente se o primeiro trabalho falhar.

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

Você também pode definir e usar variáveis em condições. O exemplo a seguir define e usa uma isMain variável para designar main como o 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)

Importante

As condições são avaliadas para determinar se deve iniciar um estágio, trabalho ou etapa. Portanto, nada computado em tempo de execução dentro dessa unidade de trabalho está disponível. Por exemplo, se você tiver um trabalho que defina uma variável usando uma expressão de tempo de execução com $[ ] sintaxe, não poderá usar essa variável em uma condição personalizada nesse trabalho.

Condições personalizadas

Se as condições internas não atenderem às suas necessidades, você poderá especificar condições personalizadas. Você escreve condições como expressões em definições de pipeline YAML.

O agente avalia a expressão começando com a função mais interna e prosseguindo para fora. O resultado final é um valor booleano que determina se a tarefa, o trabalho ou o estágio devem ou não ser executados. Para obter um guia completo da sintaxe, consulte Expressões.

Se qualquer uma de suas condições possibilitar que a tarefa seja executada mesmo depois que a compilação for cancelada, especifique um valor razoável para o tempo limite de cancelamento para que essas tarefas tenham tempo suficiente para serem concluídas depois que o usuário cancelar uma execução.

Resultados da condição quando uma compilação é cancelada

Cancelar uma compilação não significa que todos os seus estágios, trabalhos ou etapas param de ser executados. Quais estágios, trabalhos ou etapas param de ser executados dependem das condições especificadas e em que ponto da execução do pipeline você cancelou a compilação. Se um pai, trabalho ou etapa for ignorado, a tarefa não será executada, independentemente de suas condições.

Um estágio, trabalho ou etapa é executado sempre que suas condições são avaliadas para true. Se sua condição não levar em conta o estado do pai da tarefa, a tarefa poderá ser executada mesmo se seu pai for cancelado. Para controlar se estágios, trabalhos ou etapas com condições são executados quando uma compilação é cancelada, inclua uma função de verificação de status do trabalho em suas condições.

Os exemplos a seguir mostram os resultados de várias condições definidas em estágios, trabalhos ou etapas quando a compilação é cancelada.

Exemplo de estágio 1

No pipeline a seguir, por padrão stage2 , dependeria do stage1, mas stage2 tem um condition conjunto para ser executado sempre que a ramificação de origem for main, independentemente do stage1 status.

Se você enfileirar main uma compilação na ramificação e cancelá-la enquanto stage1 estiver em execução, stage2 ainda será executada, pois eq(variables['Build.SourceBranch'], 'refs/heads/main') avalia como 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

Exemplo de estágio 2

No pipeline a seguir, stage2 depende por stage1 padrão. Job B in stage2 tem um condition conjunto. Se você enfileirar uma compilação na ramificação e cancelá-la durante a main execução, stage2 ela não será executada, mesmo que ela contenha um trabalho cuja condição seja avaliada como true.stage1

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.

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

Exemplo de estágio 3

No pipeline a seguir, por padrão stage2 , depende de stage1, e a etapa interna do trabalho B tem um condition definido.

Se você enfileirar uma compilação na ramificação e cancelá-la durante a main execução, stage2 ela não será executada, mesmo que ela contenha uma etapa no trabalho B cuja condição seja avaliada como true.stage1 O motivo é que stage2 é ignorado em resposta ao cancelamento de 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')

Exemplo de trabalho 1

No pipeline YAML a seguir, o trabalho B depende do trabalho A por padrão, mas o trabalho B tem um condition conjunto para ser executado sempre que a ramificação de origem for main. Se você enfileirar uma compilação na ramificação e cancelá-la enquanto o main trabalho estiver em execução, o trabalho B ainda será executado, pois eq(variables['Build.SourceBranch'], 'refs/heads/main') será avaliado como trueA .

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

Se você quiser que o trabalho B seja executado somente quando o trabalho A for bem-sucedido e a origem da compilação for a main ramificação, seu condition deverá ser and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')).

Exemplo de trabalho 2

No pipeline a seguir, o trabalho B depende do trabalho A por padrão. Se você enfileirar uma compilação na ramificação e cancelá-la enquanto o main trabalho A estiver em execução, o trabalho B não será executado, mesmo que sua etapa tenha um condition que seja avaliado como true.

O motivo é que o trabalho B tem o padrão condition: succeeded(), que é avaliado como false quando o trabalho A é cancelado. Portanto, o trabalho B é ignorado e nenhuma de suas etapas é executada.

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

Exemplo de etapa

Você também pode ter condições nas etapas.

No pipeline a seguir, a etapa 2.3 tem um condition conjunto para ser executado sempre que a ramificação de origem for main. Se você enfileirar uma compilação na ramificação e cancelá-la enquanto as main etapas 2.1 ou 2.2 estiverem em execução, a etapa 2.3 ainda será executada, pois eq(variables['Build.SourceBranch'], 'refs/heads/main') avalia como 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')

Configurações de condição

A tabela a seguir mostra configurações de exemplo condition para produzir vários resultados.

Observação

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

Resultado desejado Exemplo de configuração de condição
Execute se a ramificação de origem for principal, mesmo se o estágio, trabalho ou etapa pai ou anterior falhar ou tiver sido cancelado. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Execute se a ramificação de origem for principal e o estágio, trabalho ou etapa pai ou anterior tiver sido bem-sucedido. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Execute se a ramificação de origem não for principal e o estágio, trabalho ou etapa pai ou anterior tiver sido bem-sucedido. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Executar para ramificações de tópico de usuário, se o estágio pai ou anterior, trabalho ou etapa tiver sido bem-sucedido. and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
Executar para compilações de integração contínua (CI), se o estágio pai ou anterior, trabalho ou etapa tiver sido bem-sucedido. and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
Execute se a compilação foi acionada por uma diretiva de ramificação para uma solicitação pull e o estágio, trabalho ou etapa pai ou anterior falhou. and(failed(), eq(variables['Build.Reason'], 'PullRequest'))
Executar para uma compilação agendada, mesmo se o estágio, trabalho ou etapa pai ou anterior falhar ou tiver sido cancelado. eq(variables['Build.Reason'], 'Schedule')
Execute se uma variável estiver definida como true, mesmo se o estágio, trabalho ou etapa pai ou anterior falhar ou tiver sido cancelado. eq(variables['System.debug'], true)

Observação

Você pode definir uma condição a ser executada 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 no seguinte pipeline:

variables:
- name: testEmpty
  value: ''

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

Parâmetros em condições

A expansão dos parâmetros ocorre antes que as condições sejam consideradas. Portanto, quando você declara um parâmetro no mesmo pipeline como uma condição, você pode incorporar o parâmetro dentro da condição. O script no YAML a seguir é executado porque parameters.doThing é true.

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

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

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

A eq('${{ parameters.doThing }}', true) função verifica se o doThing parâmetro é igual a true. Como o valor padrão para doThing é true, a condição retorna true por padrão, a menos que o pipeline defina um valor diferente.

Parâmetros do modelo em condições

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

Por exemplo, o seguinte arquivo parameters.yml declara o parâmetro e o doThing valor padrão:

# 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) }}

O código de pipeline faz referência ao modelo parameters.yml. A saída do pipeline é I did a thing porque o parâmetro doThing é true.

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

trigger:
- none

extends:
  template: parameters.yml

Para obter mais exemplos de parâmetros de modelo, consulte a Referência de uso de modelo.

Variáveis de saída do trabalho usadas nas condições de trabalho subsequentes

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, como no código a seguir:

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."

Variáveis criadas em uma etapa usada em condições de etapa subsequente

Você pode criar uma variável que está disponível para etapas futuras para especificar em uma condição. As variáveis criadas a partir de etapas estão disponíveis para etapas futuras por padrão e não precisam ser marcadas como variáveis de saída de vários trabalhos.

Há algumas coisas importantes a serem observadas sobre as variáveis de escopo que são criadas a partir das etapas.

  • As variáveis criadas em uma etapa em um trabalho têm como escopo as etapas no mesmo trabalho.
  • As variáveis criadas em uma etapa estão disponíveis nas etapas subsequentes apenas como variáveis de ambiente.
  • As variáveis criadas em uma etapa não podem ser usadas na etapa que as define.

O exemplo a seguir mostra a criação de uma variável de pipeline em uma etapa e o uso da variável na condição e no script de uma etapa subsequente.

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

Perguntas frequentes

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

Você pode usar o resultado do trabalho anterior em uma condição. Por exemplo, no YAML a seguir, a condição eq(dependencies.A.result,'SucceededWithIssues') permite que o trabalho B seja executado porque o trabalho A foi bem-sucedido 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. Por quê?

Você pode enfrentar esse problema se uma condição configurada em um estágio 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 no estágio de fila, mas não estiver em execução, todo o trabalho será cancelado, incluindo todos os outros estágios. Para obter mais informações, consulte Resultados da condição quando uma compilação é cancelada anteriormente neste artigo.