Especificar condiciones

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

Puede especificar las condiciones bajo las cuales se ejecuta cada etapa, trabajo o paso. De manera predeterminada, se ejecuta un trabajo o una fase si no depende de ningún otro trabajo o fase, o si todos los trabajos o fases de los que depende se hayan completado y realizado correctamente. Esto incluye no solo dependencias directas, sino también sus dependencias, calculadas de forma recursiva. De manera predeterminada, se ejecuta un paso si aún no se ha producido ningún error en su trabajo y el paso inmediatamente anterior a él ha finalizado. Puede personalizar este comportamiento forzando una fase, un trabajo o un paso para ejecutarse aunque se produzca un error en una dependencia anterior o especificando una condición personalizada.

Puede especificar condiciones en las que se ejecutará un paso, un trabajo o una fase.

  • Solo cuando todas las dependencias directas e indirectas anteriores que tienen el mismo grupo de agentes se hayan realizado correctamente. Si tiene grupos de agentes diferentes, esas fases o trabajos se ejecutarán simultáneamente. Este es el valor predeterminado si no hay ninguna condición establecida en YAML.

  • Incluso si se ha producido un error en una dependencia anterior, a menos que se haya cancelado la ejecución. Use succeededOrFailed() en YAML para esta condición.

  • Incluso si se ha producido un error en una dependencia anterior, incluso si se ha cancelado la ejecución. Use always() en YAML para esta condición.

  • Solo cuando se ha producido un error en una dependencia anterior. Use failed() en YAML para esta condición.

  • Condiciones personalizadas

De manera predeterminada, los pasos, los trabajos y las fases se ejecutan si todas las dependencias directas e indirectas se han completado correctamente. Es como si especificara "condition: succeeded()" (consulte Funciones con estado correcto).

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

También puede usar variables en las condiciones.

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)

Las condiciones se evalúan para decidir si se debe iniciar una fase, un trabajo o un paso. Esto significa que nada calculado en tiempo de ejecución dentro de esa unidad de trabajo estará disponible. Por ejemplo, si tiene un trabajo que establece una variable con una expresión en tiempo de ejecución mediante la sintaxis $[ ], no podrá usar esa variable en la condición personalizada.

No se admite YAML en TFS.

Nota:

Al especificar su propia propiedad condition para una fase, trabajo o paso, debe sobrescribir su valor predeterminado condition: succeeded(). Esto puede dar lugar a la ejecución de la fase, el trabajo o el paso, incluso si se cancela la compilación. No olvide tener en cuenta el estado de la fase o trabajo primario al escribir sus propias condiciones.

Habilitación de una condición personalizada

Si las condiciones integradas no satisfacen sus necesidades, puede especificar condiciones personalizadas.

Las condiciones se escriben como expresiones en canalizaciones de YAML. El agente evalúa la expresión comenzando con la función más interna y trabaja para salir. El resultado final es un valor booleano que determina si la tarea, trabajo o etapa debe ejecutarse o no. Consulte el artículo expresiones para ver una guía completa sobre la sintaxis.

¿Alguna de las condiciones permite que la tarea se ejecute incluso después de que un usuario cancele la compilación? Si es así, especifique un valor razonable para cancelar el tiempo de espera para que estos tipos de tareas tengan tiempo suficiente para completarse después de que el usuario cancele una ejecución.

Comportamiento de canalización cuando se cancela la compilación

Cuando se cancela una compilación, no significa que todas sus fases, trabajos o pasos dejen de ejecutarse. La decisión depende de la fase, el trabajo o el paso conditions que especificó y en qué punto de ejecución de la canalización canceló la compilación.

Si la condición no tiene en cuenta el estado del elemento primario de la fase, el trabajo o el paso, si la condición se evalúa como true, se ejecutará la fase, el trabajo o el paso, aunque se cancele su elemento primario. Si se omite su elemento primario, no se ejecutará la fase, el trabajo o el paso.

Veamos algunos ejemplos.

En esta canalización, de forma predeterminada, stage2 depende de stage1 y stage2 tiene una condition establecida. stage2 solo se ejecuta cuando la rama de origen es 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

Si pone en cola una compilación en la rama main y la cancela mientras se ejecuta stage1, stage2 seguirá ejecutándose, ya que eq(variables['Build.SourceBranch'], 'refs/heads/main') se evalúa como true.

En esta canalización, stage2 depende de stage1. El trabajo B tiene una condition establecida para él.

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

Si pone en cola una compilación en la rama main y la cancela mientras se ejecuta stage1, stage2no se ejecutará, aunque contenga un trabajo B cuya condición se evalúe como true. El motivo es que stage2 tiene el valor predeterminado condition: succeeded(), que se evalúa como false cuando se cancela stage1. Por lo tanto, se omite stage2 y no se ejecuta ninguna de sus trabajos.

Supongamos que tiene la siguiente canalización de YAML. Tenga en cuenta que, de forma predeterminada, stage2 depende de stage1 y que script: echo 2 tiene una condition establecida para él.

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

Si pone en cola una compilación en la rama main y la cancela mientras se ejecuta stage1, stage2no se ejecutará, aunque contenga un paso en el trabajo B cuya condición se evalúe como true. El motivo es que se omite stage2 en respuesta a la cancelación de stage1.

Para evitar que las fases, los trabajos o los pasos que tienen conditions se ejecuten cuando se cancele una compilación, no olvide tener en cuenta el estado de su elemento primario al escribir conditions. Para obtener más información, consulte Funciones de estado del trabajo.

Ejemplos

Ejecución para la rama principal, aunque se cancele, incluso si se produce un error

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

Ejecución para la rama principal si se realiza correctamente.

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

Ejecución si la rama no es principal y si se realiza correctamente

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

Ejecución para ramas de temas de usuario si se realiza correctamente

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

Ejecución para compilaciones de integración continua (CI) si se realiza correctamente

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

Ejecución si la compilación se ejecuta mediante una directiva de rama para una solicitud de incorporación de cambios, si se produce un error

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

Ejecución si la compilación está programada, aunque se produzca un error, incluso si se cancela

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

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

Ejecución siempre si una variable está establecida en true, aunque se cancele, incluso si se produce un error

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

Ejecución si una variable es null (cadena vacía)

Dado que todas las variables se tratan como cadenas en Azure Pipelines, una cadena vacía es equivalente a null en esta canalización.

variables:
- name: testEmpty
  value: ''

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

Uso de un parámetro de plantilla como parte de una condición

Al declarar un parámetro en la misma canalización que tiene una condición, la expansión de parámetros se produce antes de que se tengan en cuenta las condiciones. En este caso, puede insertar parámetros dentro de condiciones. El script de este archivo YAML se ejecutará porque parameters.doThing es true.

La condition de la canalización combina dos funciones: succeeded() y eq('${{ parameters.doThing }}', true). La función succeeded() comprueba si el paso anterior se realizó correctamente. La función succeeded() devuelve true porque no había ningún paso anterior.

La función eq('${{ parameters.doThing }}', true) comprueba si el parámetro doThing es igual a true. Dado que el valor predeterminado de doThing es true, la condición devolverá true de manera predeterminada, a menos que se establezca un valor diferente en la canalización.

Para obtener más ejemplos de parámetros de plantilla, consulte Tipos y uso de plantillas.

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

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

Al pasar un parámetro a una plantilla, debe establecer el valor del parámetro en la plantilla o usar templateContext para pasar propiedades a las plantillas.

# 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

La salida de esta canalización es I did a thing porque el parámetro doThing es true.

Uso de la variable de salida de un trabajo en una condición en un trabajo posterior

Puede hacer que una variable esté disponible para trabajos futuros y especificarla en una condición. Las variables disponibles para trabajos futuros deben marcarse como variables de salida de varios trabajos mediante 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."

Uso de la variable de canalización creada a partir de un paso en una condición en un paso posterior

Puede hacer que una variable esté disponible para pasos futuros y especificarla en una condición. De forma predeterminada, las variables creadas a partir de un paso están disponibles para pasos futuros y no es necesario marcarlas como variables de salida de varios trabajos mediante isOutput=true.

Hay que tener en cuenta algunos aspectos importantes en relación con el enfoque y el ámbito anteriores:

  • Las variables creadas en un paso de un trabajo se limitarán a los pasos del mismo trabajo.
  • Las variables creadas en un paso solo estarán disponibles en pasos posteriores como variables de entorno.
  • Las variables creadas en un paso no se pueden usar en el paso que las define.

A continuación se muestra un ejemplo de creación de una variable de canalización en un paso y el uso de la variable en la condición y el script de un paso posterior.

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

Preguntas más frecuentes

¿Cómo puedo desencadenar un trabajo si un trabajo anterior se realizó correctamente con incidencias?

Puede usar el resultado del trabajo anterior. Por ejemplo, en este archivo YAML, la condición eq(dependencies.A.result,'SucceededWithIssues') permite que se ejecute el trabajo, ya que el trabajo A se realizó correctamente con 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

Cancelé mi compilación, pero todavía se está ejecutando. ¿Qué sucede?

Experimentará este problema si la condición configurada en la fase no incluye ninguna función de comprobación de estado del trabajo. Para resolver el problema, agregue una función de comprobación de estado del trabajo a la condición. Si cancela un trabajo mientras está en la cola, pero no en ejecución, se cancelará todo el trabajo, incluidas las demás fases.

Obtenga más información sobre el comportamiento de una canalización cuando se cancela una compilación.