Condições do gasoduto

Serviços de DevOps do Azure | 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 Conceitos-chave 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. Este requisito aplica-se não só às dependências diretas, mas também às suas dependências indiretas, calculadas recursivamente.

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

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

Nota

Este artigo discute os recursos de pipeline YAML. Para pipelines clássicos, você pode especificar algumas condições sob as quais 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 em que 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. Esta condição é o padrão se nenhuma condição estiver definida no YAML.

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

  • Mesmo que uma dependência anterior falhe e mesmo que a execução seja cancelada. Use always() no YAML para esta condição.

  • Apenas quando uma dependência anterior falha. Use failed() no YAML para esta 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 ou trabalho pai.

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 .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 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 define 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 deve ou não ser executado. Para obter um guia completo sobre a sintaxe, consulte Expressões.

Se qualquer uma das suas condições permitir que a tarefa seja executada mesmo depois que a compilação for cancelada, especifique um valor razoável para cancelar o tempo limite 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 parem 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 o pai de um estágio, 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 avaliam a true. Se a sua condição não levar em conta o estado do pai da tarefa, a tarefa poderá ser executada mesmo que o pai seja cancelado. Para controlar se estágios, trabalhos ou etapas com condições são executados quando uma compilação é cancelada, certifique-se de incluir 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 de 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 uma compilação na main ramificação e cancelá-la enquanto stage1 estiver em execução, stage2 ainda será executado, porque 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 main ramificação e cancelá-la enquanto stage1 estiver em execução, stage2 ela não será executada, mesmo que ela contenha um trabalho cuja condição seja avaliada como true.

O motivo é porque stage2 tem o padrão condition: succeeded(), que avalia até 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 dentro do trabalho B tem um condition conjunto.

Se você enfileirar uma compilação na main ramificação e cancelá-la enquanto stage1 estiver em execução, stage2 ela não será executada, mesmo que ela contenha uma etapa no trabalho B cuja condição seja avaliada como true. O motivo é porque stage2 é ignorado em resposta ao stage1 cancelamento.

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 trabalho A estiver em execução, o main trabalho B ainda será executado, porque eq(variables['Build.SourceBranch'], 'refs/heads/main') avalia como 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

Se você quiser que o trabalho B seja executado somente quando o trabalho A for bem-sucedido e a fonte de compilação for a main ramificação, você condition deve 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 avalia como true.

O motivo é porque o trabalho B tem o padrão condition: succeeded(), que avalia quando o false 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', succeeded())
      

Exemplo de passo

Você também pode ter condições sobre os degraus.

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 etapas 2.1 ou 2.2 estiverem em execução, a main etapa 2.3 ainda será executada, porque 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.

Nota

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 que o estágio, trabalho ou etapa pai ou anterior tenha falhado ou 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 êxito. 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 êxito. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Executar para ramificações de tópico de usuário, se o estágio, trabalho ou etapa pai ou anterior 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, trabalho ou etapa pai ou anterior tiver sido bem-sucedido. and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
Execute se a compilação foi acionada por uma política 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 que o estágio, trabalho ou etapa pai ou anterior tenha falhado ou sido cancelado. eq(variables['Build.Reason'], 'Schedule')
Execute se uma variável estiver definida como true, mesmo que o estágio, trabalho ou etapa pai ou anterior tenha falhado ou sido cancelado. eq(variables['System.debug'], true)

Nota

Você pode definir uma condição para 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 ao null 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 do parâmetro acontece 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 é verdadeiro.

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

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

O condition pipeline anterior combina duas funções: succeeded() e ${{ eq(parameters.doThing, true) }}. A succeeded() função 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 de 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 de trabalho usadas em 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 subsequentes

Você pode criar uma variável que está disponível para etapas futuras a serem especificadas 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 observar sobre as variáveis de escopo que são criadas a partir de 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 somente 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'))

FAQ

Como poderei acionar um trabalho se um trabalho anterior tiver sido concluído 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

Eu cancelei minha compilação, mas ela ainda está em execução. Porquê?

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.