Especificar condições

Serviços de DevOps do Azure | Azure DevOps Server 2022 - Azure DevOps Server 2019

Pode especificar as condições de execução de cada fase, trabalho ou passo. Por padrão, um trabalho ou estágio é executado se não depender de nenhum outro trabalho ou estágio, ou se todos os trabalhos ou estágios dos quais depende tiverem sido concluídos e bem-sucedidos. Isso inclui não apenas dependências diretas, mas também suas dependências, calculadas recursivamente. Por predefinição, um passo será executado se nada no trabalho tiver falhado e se o passo imediatamente anterior tiver terminado. Pode personalizar este comportamento ao forçar a execução de uma fase, um trabalho ou um passo, mesmo que a dependência anterior falhe, ou ao especificar uma condição personalizada.

Pode especificar as condições nas quais um passo, um trabalho ou uma fase serão executados.

  • Somente quando todas as dependências diretas e indiretas anteriores com o mesmo pool de agentes tiverem sido bem-sucedidas. Se tiver conjuntos de agentes diferentes, estas fases ou trabalhos serão executados em simultâneo. Este é o padrão se não houver uma 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 esta condição.

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

  • Apenas quando uma dependência anterior falhou. Use failed() no YAML para esta condição.

  • Condições personalizadas

Por padrão, etapas, trabalhos e estágios são executados se todas as dependências diretas e indiretas tiverem sido bem-sucedidas. É como se você especificasse "condição: succeeded()" (consulte a função de status 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

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 se iniciam uma etapa, trabalho ou etapa. Isso significa que nada computado em tempo de execução 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 tempo de execução usando $[ ] sintaxe, não poderá usar essa variável em sua condição personalizada.

YAML não é suportado no TFS.

Nota

Quando você especifica sua própria condition propriedade para um estágio / trabalho / etapa, você substitui seu padrão condition: succeeded(). Isso pode levar à execução do seu estágio/trabalho/etapa, mesmo que a compilação seja cancelada. Certifique-se de levar em conta o estado do estágio pai / trabalho ao escrever suas próprias condições.

Ativar uma condição personalizada

Se as condições internas não atenderem às suas necessidades, você poderá especificar condições personalizadas.

As condições são escritas como expressões nos pipelines YAML. O agente avalia a expressão a partir da função mais interna e progride a partir daí. O resultado final é um valor booleano que determina se a tarefa, o trabalho ou a fase devem ou não ser executados. Consulte o artigo de expressões para obter um guia completo da sintaxe.

Alguma das condições permite que a tarefa seja executada, mesmo depois de a compilação ser cancelada por um utilizador? Em caso afirmativo, especifique um valor razoável para cancelar o tempo limite para que esses tipos de tarefas tenham tempo suficiente para serem concluídas depois que o usuário cancelar uma execução.

Comportamento do pipeline quando a compilação é cancelada

Quando uma compilação é cancelada, isso não significa que todos os seus estágios, trabalhos ou etapas parem de ser executados. A decisão depende do estágio, trabalho ou etapa conditions que você especificou e em que ponto da execução do pipeline você cancelou a compilação.

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

Vejamos alguns exemplos.

Neste pipeline, por padrão, stage2 depende stage1 e stage2 tem um condition conjunto. stage2 só é executado quando a ramificação 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 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.

Neste pipeline, stage2 depende de stage1. Job B tem um condition conjunto para isso.

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 uma compilação na main ramificação e cancelá-la enquanto stage1 estiver em execução, stage2ela não será executada, mesmo que ela contenha um trabalho B 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.

Digamos que você tenha o seguinte pipeline YAML. Observe que, por padrão, stage2 depende e stage1 que script: echo 2 tem um condition conjunto para isso.

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 uma compilação na main ramificação e cancelá-la enquanto stage1 estiver em execução, stage2não será executado, mesmo que ela contenha uma etapa no trabalho B cuja condição é avaliada como true. O motivo é porque stage2 é ignorado em resposta ao stage1 cancelamento.

Para evitar que estágios, trabalhos ou etapas com conditions sejam executados quando uma compilação for cancelada, considere o estado dos pais ao escrever o conditions. Para obter mais informações, consulte Funções de status do trabalho.

Exemplos

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

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

Executar para a ramificação principal, se for bem-sucedido

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

Executar se a ramificação não for principal, se for bem-sucedida

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

Executar para ramificações de tópico do usuário, se for bem-sucedido

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

Executar para compilações de integração contínua (CI) se for bem-sucedida

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

Executar se a compilação for executada por uma política de ramificação para uma solicitação pull, se falhar

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

Executar se a compilação estiver agendada, mesmo se falhar, mesmo se cancelada

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 cancelada, mesmo se falhar

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 esse pipeline.

variables:
- name: testEmpty
  value: ''

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

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

Quando declara um parâmetro no mesmo pipeline no qual tem uma condição, a expansão do parâmetro ocorre antes de as condições serem consideradas. Neste caso, pode incorporar parâmetros dentro das condições. O script neste arquivo YAML será executado porque parameters.doThing é true.

O condition no pipeline 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 parâmetro doThing é igual a true. Como o valor padrão para doThing é true, a condição retornará true por padrão, a menos que um valor diferente seja definido no pipeline.

Para obter mais exemplos de parâmetros de modelo, consulte Tipos de modelo & uso.

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.

Utilizar a variável de saída de um trabalho numa condição num 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."

Utilizar a variável de pipeline criada a partir de um passo numa condição num passo subsequente

Você pode disponibilizar uma variável para etapas futuras e especificá-la em uma condição. Por padrão, as variáveis criadas a partir de 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 observar em relação à abordagem e 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 usando a variável na condição e no 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'))

FAQ

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

Você enfrentará esse problema se a condição configurada no 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 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 uma compilação é cancelada.