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 obtener más contexto sobre las fases, los trabajos y los pasos, consulte Conceptos clave de Azure Pipelines.
De manera predeterminada, se ejecuta un trabajo o una fase si no depende de ningún otro trabajo o fase, o si todas sus dependencias han finalizado correctamente. Este requisito se aplica no solo a las dependencias directas, sino a sus dependencias indirectas, 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 invalidar o 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.
Nota:
En este artículo se describen las funcionalidades de canalización YAML. Para las canalizaciones clásicas, puede especificar las condiciones en las que se va a ejecutar la tarea o el trabajo en las Opciones de control de cada tarea y, en las Opciones adicionales de un trabajo de 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 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. Esta es la condición predeterminada 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, las fases, los trabajos y los pasos se ejecutan si todas las dependencias directas e indirectas se han completado correctamente. Este estado equivale a especificar condition: succeeded()
. Para obtener más información, consulte Función de estado correcto.
Al especificar una propiedad condition
para una fase, trabajo o paso, debe sobrescribir 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. No olvide tener en cuenta el estado de la fase o trabajo primario al escribir sus propias condiciones.
En el siguiente ejemplo de YAML se muestran las condiciones always()
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 las condiciones. En el ejemplo siguiente se establece y se usa una variable isMain
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, 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 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 YAML.
El agente evalúa la expresión comenzando con la función más interna y continuando hacia fuera. El resultado final es un valor booleano que determina si se debe ejecutar o no la tarea, el trabajo o la fase. Para obtener una guía completa sobre la sintaxis, consulte 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
Cuando se cancela 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 que haya especificado y del momento de la ejecución de la canalización en que canceló la compilación. Si se omite un elemento principal de la fase, el trabajo o el 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 principal de la tarea, esta podría ejecutarse incluso si se cancela su elemento principal. 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ía de stage1
, pero stage2
tiene establecida una condition
que se ejecutará siempre que la rama de origen sea main
, independientemente del estado de stage1
.
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
.
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
de forma predeterminada. El trabajo B
de stage2
tiene establecida una condition
. Si pone en cola una compilación en la rama main
y la cancela mientras se ejecuta stage1
, stage2
no se ejecutará, 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 de stage1
, y el paso dentro del trabajo B
tiene establecida una condition
.
Si pone en cola una compilación en la rama main
y la cancela mientras se ejecuta stage1
, stage2
no 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
.
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 YAML, el trabajo B
depende del trabajo A
de forma predeterminada, pero el trabajo B
tiene establecida una condition
para ejecutarse siempre que la rama de origen sea main
. Si pone en cola una compilación en la rama main
y la cancela mientras se ejecuta el trabajo A
, el trabajo B
seguirá ejecutándose, ya que eq(variables['Build.SourceBranch'], 'refs/heads/main')
se evalúa 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
Si quiere que el trabajo B
solo se ejecute cuando el trabajo A
se realice correctamente y el origen de compilación sea la rama main
, su condition
debería 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 rama main
y la cancela mientras el trabajo A
se está ejecutando, B
el trabajo no se ejecutará, aunque su paso tenga una 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', succeeded())
Ejemplo de paso
También puede tener condiciones en los pasos.
En la canalización siguiente, el paso 2.3 tiene establecida una condition
para ejecutarse cada vez que la rama de origen sea main
. Si pone en cola una compilación en la rama main
y la cancela mientras se ejecutan los pasos 2.1 o 2.2, el paso 2.3 se sigue ejecutando, ya que eq(variables['Build.SourceBranch'], 'refs/heads/main')
se evalúa 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')
Configuración de la condición
En la tabla siguiente se muestra la configuración de ejemplo de condition
para generar varios resultados.
Nota:
Release.Artifacts.{artifact-alias}.SourceBranch
equivale a Build.SourceBranch
.
Resultado deseado | Configuración de condición de ejemplo |
---|---|
Ejecutar si la rama de origen es principal, incluso si la fase, el trabajo o el paso principal o anterior no se pudieron realizar o se cancelaron. | eq(variables['Build.SourceBranch'], 'refs/heads/main') |
Ejecutar si la rama de origen es principal y la fase, el trabajo o el paso principal o anterior se realizaron correctamente. | and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) |
Ejecutar si la rama de origen no es principal y la fase, el trabajo o el paso principal o anterior se realizaron correctamente. | and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main')) |
Ejecutar para ramas de temas de usuario, si la fase, el trabajo o el paso principal o anterior se realizaron correctamente. | and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/')) |
Ejecutar para compilaciones de integración continua (CI), si la fase, el trabajo o el paso principal o anterior se realizaron correctamente. | and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) |
Ejecutar 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, el trabajo o el paso principal o anterior. | and(failed(), eq(variables['Build.Reason'], 'PullRequest')) |
Ejecutar para una compilación programada, incluso si se produjo un error en la fase, el trabajo o el paso principal o anterior o se cancelaron. | eq(variables['Build.Reason'], 'Schedule') |
Ejecutar si una variable se establece en true, incluso si la fase, el trabajo o el paso principal o anterior no se realizaron correctamente 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 es equivalente a null
en la siguiente canalización:
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: and(succeeded(), ${{ eq(parameters.doThing, true) }})
La condition
de la canalización anterior 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 para 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 doThing
y el 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 es I did a thing
porque 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 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 utilizadas en condiciones de paso posteriores
Puede crear una variable que esté disponible para pasos futuros para especificarla en una condición. Las variables creadas a partir de pasos están disponibles para 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 limitarán a los pasos del mismo trabajo.
- Las variables creadas en un paso solo estarán disponibles en pasos posteriores solo 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 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 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 YAML, la condición eq(dependencies.A.result,'SucceededWithIssues')
permite que se ejecute el trabajo B
, 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. ¿Por qué?
Puede experimentar este problema si una condición configurada en una 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 fase de cola, pero no en ejecución, se cancelará todo el trabajo, incluidas las demás fases. Para obtener más información, consulte Salidas de condición cuando se cancela una compilación anteriormente en este artículo.