Compartir vía


Condiciones de canalización

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

En este artículo se describen las condiciones en las que se ejecuta una fase, un trabajo o un paso de Azure Pipelines y cómo especificar condiciones diferentes. Para más contexto sobre las fases, los trabajos y los pasos, consulte Conceptos clave de Azure Pipelines.

  • De forma predeterminada, un trabajo o una fase se ejecuta si no depende de ningún otro trabajo o fase, o si todas sus dependencias se completaron y se realizaron correctamente. Este requisito se aplica no solo a las dependencias directas, sino a sus dependencias indirectas, calculadas de forma recursiva.

  • De forma predeterminada, se ejecuta un paso si aún no se ha producido ningún error en su trabajo y el paso inmediatamente anterior a su finalización.

Puede invalidar o personalizar este comportamiento al forzar una fase, un trabajo o un paso para ejecutarse incluso si se produce un error en una dependencia anterior o si se especifica una condición personalizada.

Nota:

En este artículo se describen las funcionalidades de canalización de YAML. En el caso de las canalizaciones clásicas, puede especificar algunas condiciones en las que se ejecutan tareas o trabajos en las opciones de control de cada tarea y en las opciones adicionales de un trabajo en una canalización de versión.

Condiciones en las que se ejecuta una fase, un trabajo o un paso

En la definición de canalización YAML, puede especificar las siguientes condiciones en las que se ejecuta una fase, un trabajo o un paso:

  • Solo cuando todas las dependencias directas e indirectas anteriores con el mismo grupo de agentes se realizan correctamente. Si tiene grupos de agentes diferentes, esas fases o trabajos se ejecutan simultáneamente. Esta condición es la predeterminada si no hay ninguna condición establecida en YAML.

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

  • Incluso si se produce un error en una dependencia anterior e incluso si se cancela la ejecución. Use always() en YAML para esta condición.

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

  • Condiciones personalizadas.

De forma predeterminada, las fases, los trabajos y los pasos se ejecutan si todas las dependencias directas e indirectas se ejecutan correctamente. Este estado es el mismo que especificar condition: succeeded(). Para obtener más información, consulte función de estado correcta.

Al especificar una condition propiedad para una fase, un trabajo o un paso, sobrescribe el valor predeterminado condition: succeeded(). Especificar sus propias condiciones puede hacer que la fase, el trabajo o el paso se ejecuten incluso si se cancela la compilación. Asegúrese de que las condiciones que escriba tenga en cuenta el estado de la fase primaria o el trabajo.

En el siguiente ejemplo de YAML se muestran las always() condiciones y failed() . El paso del primer trabajo se ejecuta aunque se produzca un error en las dependencias o se cancele la compilación. El segundo trabajo solo se ejecuta si se produce un error en el primer trabajo.

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

También puede establecer y usar variables en condiciones. En el ejemplo siguiente se establece y se usa una isMain variable 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

Las condiciones se evalúan para determinar si se debe iniciar una fase, un trabajo o un paso. Por lo tanto, no hay nada calculado en tiempo de ejecución dentro de esa unidad de trabajo disponible. Por ejemplo, si tiene un trabajo que establece una variable mediante una expresión en tiempo de ejecución con $[ ] sintaxis, no puede usar esa variable en una condición personalizada de ese trabajo.

Condiciones personalizadas

Si las condiciones integradas no satisfacen sus necesidades, puede especificar condiciones personalizadas. Las condiciones se escriben como expresiones en las definiciones de canalización de YAML.

El agente evalúa la expresión empezando por la función más interna y avanzando hacia fuera. El resultado final es un valor booleano que determina si se debe ejecutar la tarea, el trabajo o la fase. Para obtener una guía completa sobre la sintaxis, vea Expresiones.

Si alguna de las condiciones permite que la tarea se ejecute incluso después de cancelar la compilación, especifique un valor razonable para el tiempo de espera de cancelación para que estas tareas tengan tiempo suficiente para completarse después de que el usuario cancele una ejecución.

Resultados de condición cuando se cancela una compilación

Cancelar una compilación no significa que todas sus fases, trabajos o pasos dejen de ejecutarse. Las fases, trabajos o pasos que dejan de ejecutarse dependen de las condiciones especificadas y en qué punto de ejecución de la canalización canceló la compilación. Si se omite una fase, un trabajo o un elemento primario del paso, la tarea no se ejecuta, independientemente de sus condiciones.

Una fase, trabajo o paso se ejecuta cada vez que sus condiciones se evalúan como true. Si la condición no tiene en cuenta el estado del elemento primario de la tarea, la tarea podría ejecutarse incluso si se cancela su elemento primario. Para controlar si se ejecutan fases, trabajos o pasos con condiciones cuando se cancela una compilación, asegúrese de incluir una función de comprobación de estado del trabajo en las condiciones.

En los ejemplos siguientes se muestran los resultados de varias condiciones establecidas en fases, trabajos o pasos cuando se cancela la compilación.

Ejemplo de fase 1

En la canalización siguiente, de forma predeterminada stage2 dependerá stage1de , pero stage2 tiene un condition conjunto que se ejecutará siempre que la rama de origen sea main, independientemente del stage1 estado.

Si pone en cola una compilación en la main rama y la cancela mientras stage1 se ejecuta, sigue ejecutándose, stage2 ya que se evalúa truecomo eq(variables['Build.SourceBranch'], 'refs/heads/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

Ejemplo de fase 2

En la canalización siguiente, stage2 depende de stage1 forma predeterminada. El trabajo B de stage2 tiene un condition conjunto. Si pone en cola una compilación en la main rama y la cancela mientras stage1 se está ejecutando, no se ejecuta, stage2 aunque contenga un trabajo 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.

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

Ejemplo de fase 3

En la canalización siguiente, de forma predeterminada stage2 depende stage1de y el paso dentro del trabajo B tiene un condition conjunto.

Si pone en cola una compilación en la main rama y la cancela mientras stage1 se está ejecutando, no se ejecuta, stage2 aunque contenga un paso en el trabajo B cuya condición se evalúa como true. El motivo es que se omite stage2 en respuesta a la cancelación 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')

Ejemplo de trabajo 1

En la siguiente canalización de YAML, el trabajo B depende del trabajo A de forma predeterminada, pero el trabajo B tiene establecido condition para ejecutarse siempre que la rama de origen sea main. Si pone en cola una compilación en la main rama y la cancela mientras se ejecuta el trabajo A , el trabajo B sigue ejecutándose, ya que se evalúa como eq(variables['Build.SourceBranch'], 'refs/heads/main')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

Si desea que el trabajo solo se ejecute cuando el trabajo BA se realice correctamente y el origen de compilación sea la main rama , el condition debe ser and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')).

Ejemplo de trabajo 2

En la canalización siguiente, el trabajo B depende del trabajo A de forma predeterminada. Si pone en cola una compilación en la main rama y la cancela mientras se ejecuta el trabajo A , el trabajo B no se ejecuta, aunque su paso tenga un condition que se evalúe como true.

El motivo es que el trabajo B tiene el valor predeterminado condition: succeeded(), que se evalúa como false cuando se cancela el trabajo A. Por lo tanto, se omite el trabajo B y no se ejecuta ninguno de sus pasos.

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

Ejemplo de paso

También puede tener condiciones en los pasos.

En la canalización siguiente, el paso 2.3 tiene establecido que condition se ejecutará cada vez que la rama de origen sea main. Si pone en cola una compilación en la main rama y la cancela mientras se ejecutan los pasos 2.1 o 2.2, el paso 2.3 sigue ejecutándose, ya que se evalúa truecomo eq(variables['Build.SourceBranch'], 'refs/heads/main') .

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

Configuración de condición

En la tabla siguiente se muestra la configuración de ejemplo condition para generar varios resultados.

Nota:

Release.Artifacts.{artifact-alias}.SourceBranch equivale a Build.SourceBranch.

Resultado deseado Configuración de condición de ejemplo
Ejecute si la rama de origen es principal, incluso si la fase primaria o anterior, el trabajo o el paso no se pudieron realizar o se cancelaron. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Ejecute si la rama de origen es principal y la fase primaria o anterior, el trabajo o el paso se realizaron correctamente. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Ejecute si la rama de origen no es principal y la fase primaria o anterior, el trabajo o el paso se realizaron correctamente. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Ejecute para ramas de temas de usuario, si la fase primaria o anterior, el trabajo o el paso se realizaron correctamente. and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
Ejecute para compilaciones de integración continua (CI), si la fase primaria o anterior, el trabajo o el paso se realizaron correctamente. and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
Ejecute si una directiva de rama desencadenó la compilación para una solicitud de incorporación de cambios y se produjo un error en la fase primaria o anterior, el trabajo o el paso. and(failed(), eq(variables['Build.Reason'], 'PullRequest'))
Ejecute para una compilación programada, incluso si se produjo un error en la fase primaria o anterior, el trabajo o el paso o se canceló. eq(variables['Build.Reason'], 'Schedule')
Ejecute si una variable se establece en true, incluso si la fase primaria o anterior, el trabajo o el paso no se pudieron realizar o se cancelaron. eq(variables['System.debug'], true)

Nota:

Puede establecer una condición para que se ejecute si una variable es null (cadena vacía). Dado que todas las variables se tratan como cadenas en Azure Pipelines, una cadena vacía equivale a null en la canalización siguiente:

variables:
- name: testEmpty
  value: ''

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

Parámetros en condiciones

La expansión de parámetros se produce antes de que se consideren las condiciones. Por lo tanto, al declarar un parámetro en la misma canalización que una condición, puede insertar el parámetro dentro de la condición. El script del siguiente código YAML se ejecuta porque parameters.doThing es true.

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

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

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

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

Parámetros de plantilla en condiciones

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

Por ejemplo, el siguiente archivo parameters.yml declara el parámetro y el doThing valor predeterminado:

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

El código de canalización hace referencia a la plantilla de parameters.yml . La salida de la canalización se debe I did a thing a que el parámetro doThing es true.

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

trigger:
- none

extends:
  template: parameters.yml

Para obtener más ejemplos de parámetros de plantilla, consulte la referencia de uso de plantillas.

Variables de salida de trabajo usadas en condiciones de trabajo posteriores

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, como en el código siguiente:

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

Variables creadas en un paso usado en condiciones de paso posteriores

Puede crear una variable que esté disponible para futuros pasos para especificar en una condición. Las variables creadas a partir de los pasos están disponibles para los pasos futuros de forma predeterminada y no es necesario marcarlas como variables de salida de varios trabajos.

Hay algunos aspectos importantes que se deben tener en cuenta sobre las variables de ámbito que se crean a partir de los pasos.

  • Las variables creadas en un paso de un trabajo se limitan a los pasos del mismo trabajo.
  • Las variables creadas en un paso solo está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.

En el ejemplo siguiente se muestra cómo crear una variable de canalización en un paso y usar la variable en la condición y el script de un paso posterior.

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

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 en una condición. Por ejemplo, en el siguiente CÓDIGO YAML, la condición eq(dependencies.A.result,'SucceededWithIssues') permite que el trabajo B se ejecute porque 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. ¿Por qué?

Puede experimentar este problema si una condición configurada en una fase no incluye una 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 se encuentra en la fase de cola pero no se está ejecutando, se cancela todo el trabajo, incluidas todas las demás fases. Para obtener más información, consulte Resultados de condición cuando se cancela una compilación anteriormente en este artículo.