Partager via


Conditions du pipeline

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

Cet article décrit les conditions dans lesquelles une étape, un travail ou une étape Azure Pipelines s’exécute et comment spécifier différentes conditions. Pour plus de contexte sur les étapes, les travaux et les étapes, consultez Concepts clés pour Azure Pipelines.

  • Par défaut, un travail ou une étape s’exécute s’il ne dépend d’aucun autre travail ou étape, ou si toutes ses dépendances sont terminées et réussies. Cette exigence s’applique non seulement aux dépendances directes, mais à leurs dépendances indirectes, calculées de manière récursive.

  • Par défaut, une étape s’exécute si rien dans son travail n’a pas encore échoué et que l’étape qui précède immédiatement sa fin.

Vous pouvez remplacer ou personnaliser ce comportement en forçant une étape, un travail ou une étape à exécuter même si une dépendance précédente échoue ou en spécifiant une condition personnalisée.

Remarque

Cet article décrit les fonctionnalités du pipeline YAML. Pour les pipelines classiques, vous pouvez spécifier certaines conditions dans lesquelles les tâches ou travaux s’exécutent dans les options de contrôle de chaque tâche et dans les options supplémentaires d’un travail dans un pipeline de mise en production.

Conditions dans lesquelles une étape, un travail ou une étape s’exécute

Dans la définition de pipeline YAML, vous pouvez spécifier les conditions suivantes dans lesquelles une étape, un travail ou une étape s’exécute :

  • Uniquement lorsque toutes les dépendances directes et indirectes précédentes avec le même pool d’agents réussissent. Si vous avez des pools d’agents différents, ces phases ou travaux s’exécutent simultanément. Cette condition est la valeur par défaut si aucune condition n’est définie dans yaML.

  • Même si une dépendance précédente échoue, sauf si l’exécution est annulée. Utilisez succeededOrFailed() dans le fichier YAML pour cette condition.

  • Même si une dépendance précédente échoue, et même si l’exécution est annulée. Utilisez always() dans le fichier YAML pour cette condition.

  • Uniquement lorsqu’une dépendance précédente échoue. Utilisez failed() dans le fichier YAML pour cette condition.

  • Conditions personnalisées.

Par défaut, les étapes, les travaux et les étapes s’exécutent si toutes les dépendances directes et indirectes réussissent. Cet état est le même que la spécification condition: succeeded(). Pour plus d’informations, consultez la fonction d’état réussie.

Lorsque vous spécifiez une propriété pour une étape, un condition travail ou une étape, vous remplacez la valeur par défaut condition: succeeded(). La spécification de vos propres conditions peut entraîner l’exécution de votre étape, de votre travail ou de votre étape, même si la build est annulée. Assurez-vous que les conditions que vous écrivez tiennent compte de l’état de la phase parente ou du travail.

L’exemple YAML suivant montre les conditions et failed() les always() conditions. L’étape du premier travail s’exécute même si les dépendances échouent ou si la build est annulée. Le deuxième travail s’exécute uniquement si le premier travail échoue.

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

Vous pouvez également définir et utiliser des variables dans des conditions. L’exemple suivant définit et utilise une isMain variable pour désigner main le 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)

Important

Les conditions sont évaluées pour déterminer s’il faut démarrer une étape, un travail ou une étape. Par conséquent, rien calculé au moment de l’exécution à l’intérieur de cette unité de travail n’est disponible. Par exemple, si vous avez un travail qui définit une variable à l’aide d’une expression runtime avec $[ ] une syntaxe, vous ne pouvez pas utiliser cette variable dans une condition personnalisée dans ce travail.

Conditions personnalisées

Si les conditions intégrées ne répondent pas à vos besoins, vous pouvez spécifier des conditions personnalisées. Vous écrivez des conditions en tant qu’expressions dans les définitions de pipeline YAML.

L’agent évalue l’expression commençant par la fonction la plus interne et se poursuit vers l’extérieur. Le résultat final est une valeur booléenne qui détermine si la tâche, le travail ou l’étape doit s’exécuter. Pour obtenir un guide complet de la syntaxe, consultez Expressions.

Si l’une de vos conditions permet à la tâche d’s’exécuter même après l’annulation de la build, spécifiez une valeur raisonnable pour le délai d’expiration de l’annulation afin que ces tâches aient suffisamment de temps après l’annulation d’une exécution par l’utilisateur.

Résultats de condition lorsqu’une build est annulée

L’annulation d’une build ne signifie pas que toutes ses étapes, travaux ou étapes arrêtent de s’exécuter. Les étapes, les travaux ou les étapes qui arrêtent de s’exécuter dépendent des conditions que vous avez spécifiées, et à quel point de l’exécution du pipeline vous avez annulé la génération. Si le parent d’une étape, d’un travail ou d’une étape est ignoré, la tâche ne s’exécute pas, quelles que soient ses conditions.

Une étape, un travail ou une étape s’exécute chaque fois que ses conditions sont évaluées trueà . Si votre condition ne prend pas en compte l’état du parent de la tâche, elle peut s’exécuter même si son parent est annulé. Pour contrôler si des étapes, des travaux ou des étapes avec des conditions s’exécutent lorsqu’une build est annulée, veillez à inclure une fonction de vérification de l’état du travail dans vos conditions.

Les exemples suivants montrent les résultats de différentes conditions définies sur des étapes, des travaux ou des étapes lorsque la build est annulée.

Exemple d’étape 1

Dans le pipeline suivant, par défaut stage2 , dépend stage1de , mais stage2 a un condition ensemble à exécuter chaque fois que la branche source est main, quel que soit l’état stage1 .

Si vous mettez en file d’attente une build sur la branche et annulez-la main pendant stage1 l’exécution, stage2 toujours s’exécute, car eq(variables['Build.SourceBranch'], 'refs/heads/main') elle est évaluée à 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

Exemple d’étape 2

Dans le pipeline suivant, stage2 dépend stage1 par défaut. Le travail B dans a stage2 un condition ensemble. Si vous mettez en file d’attente une build sur la branche et annulez-la main pendant stage1 l’exécution, stage2 ne s’exécute pas, même si elle contient un travail dont la condition est trueévaluée .

La raison est que stage2 a la valeur par défaut condition: succeeded(), qui prend la valeur false quand stage1 est annulé. Par conséquent, stage2 est ignoré et aucun de ses travaux ne s’exécute.

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

Exemple d’étape 3

Dans le pipeline suivant, par défaut stage2 dépend stage1de l’étape à l’intérieur du travailB.condition

Si vous mettez en file d’attente une build sur la branche et annulez-la main pendant stage1 l’exécution, stage2 ne s’exécute pas, même si elle contient une étape du travail B dont la condition est trueévaluée . La raison est que stage2 est ignoré en réponse à l’annulation 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')

Exemple de travail 1

Dans le pipeline YAML suivant, le travail B dépend du travail A par défaut, mais le travail B a un condition ensemble à exécuter chaque fois que la branche source est main. Si vous mettez en file d’attente une build sur la branche et annulez-la main pendant l’exécution du travail A , la tâche B s’exécute toujours, car eq(variables['Build.SourceBranch'], 'refs/heads/main') elle est évaluée à 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 vous souhaitez que le travail B s’exécute uniquement lorsque le travail A réussit et que la source de build est la main branche, vous condition devez être and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')).

Exemple de travail 2

Dans le pipeline suivant, le travail dépend du travail B A par défaut. Si vous mettez en file d’attente une build sur la branche et annulez-la main pendant l’exécution du travail A , le travail B ne s’exécute pas, même si son étape a une condition valeur qui est trueévaluée .

La raison est que le travail B a la valeur par défaut condition: succeeded(), qui prend la valeur false quand le travail A est annulé. Par conséquent, le travail B est ignoré et aucune de ses étapes ne s’exécute.

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

Exemple d’étape

Vous pouvez également avoir des conditions sur des étapes.

Dans le pipeline suivant, l’étape 2.3 a un condition ensemble à exécuter chaque fois que la branche source est main. Si vous mettez en file d’attente une build sur la main branche et que vous l’annulez pendant que les étapes 2.1 ou 2.2 sont en cours d’exécution, l’étape 2.3 s’exécute toujours, car elle trueprend la valeur 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')

Paramètres de condition

Le tableau suivant présente des exemples condition de paramètres pour produire différents résultats.

Remarque

Release.Artifacts.{artifact-alias}.SourceBranch est équivalent à Build.SourceBranch.

Résultat souhaité Exemple de paramètre de condition
Exécutez si la branche source est principale, même si l’étape parente ou précédente, le travail ou l’étape a échoué ou a été annulée. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Exécutez si la branche source est principale et que l’étape parente ou précédente, le travail ou l’étape a réussi. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Exécutez si la branche source n’est pas principale et que l’étape parent ou précédente, le travail ou l’étape a réussi. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Exécutez les branches de rubrique utilisateur, si l’étape parente ou précédente, le travail ou l’étape a réussi. and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
Exécutez les builds d’intégration continue (CI), si l’étape parente ou précédente, le travail ou l’étape a réussi. and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
Exécutez si la génération a été déclenchée par une stratégie de branche pour une demande de tirage (pull request) et que l’étape parente ou précédente, le travail ou l’étape a échoué. and(failed(), eq(variables['Build.Reason'], 'PullRequest'))
Exécutez une build planifiée, même si l’étape parente ou précédente, le travail ou l’étape a échoué ou a été annulée. eq(variables['Build.Reason'], 'Schedule')
Exécutez si une variable a la valeur true, même si l’étape parente ou précédente, le travail ou l’étape a échoué ou a été annulée. eq(variables['System.debug'], true)

Remarque

Vous pouvez définir une condition à exécuter si une variable a la valeur Null (chaîne vide). Étant donné que toutes les variables sont traitées comme des chaînes dans Azure Pipelines, une chaîne vide équivaut à null celle du pipeline suivant :

variables:
- name: testEmpty
  value: ''

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

Paramètres dans les conditions

L’expansion des paramètres se produit avant que les conditions ne soient prises en compte. Par conséquent, lorsque vous déclarez un paramètre dans le même pipeline qu’une condition, vous pouvez incorporer le paramètre à l’intérieur de la condition. Le script dans les exécutions YAML suivantes est parameters.doThing vrai.

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

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

Le condition pipeline précédent combine deux fonctions : succeeded() et eq('${{ parameters.doThing }}', true). La fonction succeeded() vérifie si l’étape précédente a réussi. La succeeded() fonction retourne true parce qu’il n’y a pas eu d’étape précédente.

La eq('${{ parameters.doThing }}', true) fonction vérifie si le doThing paramètre est égal à true. Étant donné que la valeur doThing par défaut est true, la condition retourne true par défaut, sauf si le pipeline définit une valeur différente.

Paramètres de modèle dans les conditions

Lorsque vous passez un paramètre à un modèle, vous devez définir la valeur du paramètre dans votre modèle ou utiliser templateContext pour transmettre le paramètre au modèle.

Par exemple, le fichier parameters.yml suivant déclare le paramètre et la doThing valeur par défaut :

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

Le code de pipeline fait référence au modèle parameters.yml . La sortie du pipeline est I did a thing due au fait que le paramètre doThing a la valeur true.

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

trigger:
- none

extends:
  template: parameters.yml

Pour plus d’exemples de paramètres de modèle, consultez la référence d’utilisation du modèle.

Variables de sortie de travail utilisées dans les conditions de travail suivantes

Vous pouvez rendre une variable disponible pour de futurs travaux et la spécifier dans une condition. Les variables disponibles pour les travaux futurs doivent être marquées comme variables de sortie multi-travaux à l’aide isOutput=truede , comme dans le code suivant :

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 créées dans une étape utilisée dans les conditions d’étape suivantes

Vous pouvez créer une variable disponible pour les prochaines étapes à spécifier dans une condition. Les variables créées à partir des étapes sont disponibles pour les futures étapes par défaut et n’ont pas besoin d’être marquées comme variables de sortie à plusieurs travaux.

Il existe quelques points importants à noter sur les variables d’étendue créées à partir des étapes.

  • Les variables créées à une étape d’un travail sont limitées aux étapes du même travail.
  • Les variables créées dans une étape sont disponibles dans les étapes suivantes uniquement en tant que variables d’environnement.
  • Les variables créées dans une étape ne peuvent pas être utilisées dans l’étape qui les définit.

L’exemple suivant montre la création d’une variable de pipeline dans une étape et l’utilisation de la variable dans la condition et le script d’une étape ultérieure.

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

Comment déclencher un travail si un travail précédent a réussi avec des problèmes ?

Vous pouvez utiliser le résultat du travail précédent dans une condition. Par exemple, dans le YAML suivant, la condition eq(dependencies.A.result,'SucceededWithIssues') autorise l’exécution du travail B , car le travail A a réussi avec des problèmes.

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

J’ai annulé ma build, mais elle est toujours en cours d’exécution. Pourquoi ?

Vous pouvez rencontrer ce problème si une condition configurée dans une phase n’inclut pas de fonction de vérification de l’état du travail. Pour résoudre le problème, ajoutez une fonction de vérification de l’état du travail à la condition.

Si vous annulez un travail pendant qu’il se trouve dans la phase de file d’attente, mais qu’il n’est pas en cours d’exécution, le travail entier est annulé, y compris toutes les autres étapes. Pour plus d’informations, consultez Les résultats de condition lorsqu’une build est annulée plus haut dans cet article.