Expressions

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

Important

Select a version from Azure DevOps Content Version selector.

Sélectionnez la version de cet article qui correspond à votre plateforme et à votre version. Le sélecteur de version se trouve au-dessus de la table des matières. Recherchez votre plateforme et votre version Azure DevOps.

Les expressions peuvent être utilisées dans de nombreux endroits où vous devez spécifier une chaîne, une valeur booléenne ou un nombre lors de la création d’un pipeline. Lorsqu'une expression retourne un tableau, les règles d'indexation normales s'appliquent et l'index commence par 0.

L’utilisation la plus courante des expressions est dans des conditions pour déterminer si un travail ou une étape doit s’exécuter.

# Expressions are used to define conditions for a step, job, or stage
steps:
- task: ...
  condition: <expression>

Une autre utilisation courante des expressions est la définition de variables. Les expressions peuvent être évaluées au moment de la compilation ou au moment de l’exécution. Les expressions au moment de la compilation peuvent être utilisées n’importe où ; les expressions au moment de l’exécution peuvent être utilisées dans des variables et des conditions. Les expressions au moment de l’exécution sont destinées à calculer le contenu des variables et de l’état (exemple : condition).

# Two examples of expressions used to define variables
# The first one, a, is evaluated when the YAML file is compiled into a plan.
# The second one, b, is evaluated at runtime.
# Note the syntax ${{}} for compile time and $[] for runtime expressions.
variables:
  a: ${{ <expression> }}
  b: $[ <expression> ]

La différence entre les syntaxes d’expression au moment de l’exécution et de la compilation est principalement le contexte disponible. Dans une expression au moment de la compilation (${{ <expression> }}), vous avez accès à parameters et variables, défini statiquement. Dans une expression au moment de l’exécution ($[ <expression> ]), vous avez accès à variables, mais pas aux paramètres.

Dans cet exemple, une expression au moment de l’exécution définit la valeur de $(isMain). Une variable statique dans une expression au moment de la compilation définit la valeur de $(compileVar).

variables:
  staticVar: 'my value' # static variable
  compileVar: ${{ variables.staticVar }} # compile time expression
  isMain: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')] # runtime expression

steps:
  - script: |
      echo ${{variables.staticVar}} # outputs my value
      echo $(compileVar) # outputs my value
      echo $(isMain) # outputs True

Une expression peut être un littéral, une référence à une variable, une référence à une dépendance, une fonction ou une combinaison imbriquée valide de ces éléments.

Littéraux

Dans le cadre d’une expression, vous pouvez utiliser des booléens, null, des nombres, des chaînes ou des littéraux de version.

# Examples
variables:
  someBoolean: ${{ true }} # case insensitive, so True or TRUE also works
  someNumber: ${{ -1.2 }}
  someString: ${{ 'a b c' }}
  someVersion: ${{ 1.2.3 }}

Booléen

True et False sont des expressions littérales booléennes.

Null

Null est une expression littérale spéciale renvoyée par une absence de dictionnaire, par exemple (variables['noSuch']). Null peut être la sortie d’une expression, mais ne peut pas être appelé directement dans une expression.

Number

Commence par « - », « . » ou « 0 » à « 9 ».

String

Doit être entre guillemets uniques. Par exemple : 'this is a string'.

Pour exprimer un guillemet unique littéral, échappez-le avec un guillemet unique. Par exemple : 'It''s OK if they''re using contractions.'.

Vous pouvez utiliser un caractère de canal (|) pour les chaînes multilignes.

myKey: |
  one
  two
  three

Version

Numéro de version comprenant jusqu’à quatre segments. Doit commencer par un nombre et contenir deux ou trois caractères de point (.). Par exemple : 1.2.3.4.

Variables

Dans le cadre d’une expression, vous pouvez accéder à des variables à l’aide d’une des deux syntaxes suivantes :

  • Syntaxe d’index : variables['MyVar']
  • Syntaxe de déréférencement de propriété : variables.MyVar

Pour utiliser la syntaxe de déréférencement de propriété, le nom de la propriété doit :

  • Commencez par a-Z ou _
  • Faites suivre de a-Z0-9 ou _

Selon le contexte d’exécution, différentes variables sont disponibles.

  • Si vous créez des pipelines à l’aide de YAML, des variables de pipeline sont disponibles.
  • Si vous créez des pipelines de build à l’aide de l’éditeur classique, les variables de build sont disponibles.
  • Si vous créez des pipelines de mise en production à l’aide de l’éditeur classique, les variables de mise en production sont disponibles.

Les variables sont toujours des chaînes. Si vous souhaitez utiliser des valeurs typées, vous devez utiliser des paramètres à la place.

Notes

Il existe une limitation pour l’utilisation de variables avec des expressions pour les pipelines Classic et YAML lors de la configuration de ces variables via l’interface utilisateur de l’onglet Variables. Les variables définies en tant qu’expressions ne doivent pas dépendre d’une autre variable avec expression en valeur, car il n’est pas garanti que les deux expressions soient évaluées correctement. Par exemple, nous avons une variable a dont la valeur $[ <expression> ] est utilisée comme partie pour la valeur de la variable b. Étant donné que l’ordre de traitement des variables n’est pas garanti, la variable b peut avoir une valeur incorrecte de variable a après l’évaluation.

Les constructions décrites sont uniquement autorisées lors de la configuration des variables via le mot clé variables dans le pipeline YAML. Il est nécessaire de placer les variables dans l’ordre dans lequel elles doivent être traitées pour obtenir les valeurs correctes après le traitement.

Fonctions

Les fonctions intégrées suivantes peuvent être utilisées dans les expressions.

et

  • Évalue à True si tous les paramètres sont True
  • Paramètres min. : 2. Paramètres max. : N
  • Caste les paramètres en booléen pour l’évaluation
  • Court-circuite après le premier False
  • Exemple : and(eq(variables.letters, 'ABC'), eq(variables.numbers, 123))

coalesce

  • Évalue les paramètres dans l'ordre (de gauche à droite) et retourne la première valeur qui n'est pas égale à null ou à une chaîne vide.
  • Aucune valeur n'est retournée si les valeurs de paramètre sont toutes null ou vides.
  • Paramètres min. : 2. Paramètres max. : N
  • Exemple : coalesce(variables.couldBeNull, variables.couldAlsoBeNull, 'literal so it always works')

contains

  • Évalue à True si la chaîne du paramètre de gauche contient le paramètre de droite
  • Paramètres min. : 2. Paramètres max. : 2
  • Caste les paramètres en chaîne pour l’évaluation
  • Effectue une comparaison ordinale ignorant la casse
  • Exemple : contains('ABCDE', 'BCD') (retourne True)

containsValue

  • Évalue à True si le paramètre de gauche est un tableau et si un de ses éléments est égal au paramètre de droite. Évalue également à True si le paramètre de gauche est un objet et si la valeur d’une propriété est égale au paramètre de droite.
  • Paramètres min. : 2. Paramètres max. : 2
  • Si le paramètre de gauche est un tableau, convertissez chaque élément pour qu’il corresponde au type du paramètre de droite. Si le paramètre de gauche est un objet, convertissez la valeur de chaque propriété pour qu’elle corresponde au type du paramètre de droite. La comparaison d’égalité pour chaque élément spécifique évalue à False si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Court-circuite après la première correspondance

Notes

Il n’existe aucune syntaxe littérale dans un pipeline YAML pour spécifier un tableau. Cette fonction est d’une utilisation limitée dans les pipelines généraux. Elle est destinée à être utilisée dans le contexte du décorateur de pipeline avec des tableaux fournis par le système, comme la liste des étapes.

Vous pouvez utiliser l’expression containsValue pour rechercher une valeur correspondante dans un objet. Voici un exemple qui illustre la recherche dans la liste des branches sources d’une correspondance pour Build.SourceBranch.

parameters:
- name: branchOptions
  displayName: Source branch options
  type: object
  default:
    - refs/heads/main
    - refs/heads/test

jobs:
  - job: A1 
    steps:
    - ${{ each value in parameters.branchOptions }}:
      - script: echo ${{ value }}

  - job: B1 
    condition: ${{ containsValue(parameters.branchOptions, variables['Build.SourceBranch']) }}
    steps:
      - script: echo "Matching branch found"

convertToJson

  • Prend un objet complexe et le génère au format JSON.
  • Paramètres min. : 1. Paramètres max. : 1.
parameters:
  - name: listOfValues
    type: object
    default:
      this_is:
        a_complex: object
        with:
          - one
          - two

steps:
- script: |
    echo "${MY_JSON}"
  env:
    MY_JSON: ${{ convertToJson(parameters.listOfValues) }}

Sortie du script :

{
  "this_is": {
    "a_complex": "object",
    "with": [
      "one",
      "two"
    ]
  }
}

counter

  • Cette fonction ne peut être utilisée que dans une expression qui définit une variable. Il ne peut pas être utilisé dans le cadre d’une condition pour une étape, un travail ou une phase.
  • Évalue un nombre incrémenté à chaque exécution d’un pipeline.
  • Paramètres : 2. Voir prefix et seed.
  • Le préfixe est une expression de chaîne. Une valeur distincte de compteur est suivie pour chaque valeur unique de préfixe. Le prefix doit utiliser des caractères UTF-16.
  • La valeur initiale est la valeur de départ du compteur

Vous pouvez créer un compteur qui est automatiquement incrémenté de 1 lors de chaque exécution de votre pipeline. Lorsque vous définissez un compteur, vous fournissez un prefix et un seed. Voici un exemple qui illustre cela.

variables:
  major: 1
  # define minor as a counter with the prefix as variable major, and seed as 100.
  minor: $[counter(variables['major'], 100)]

steps:
- bash: echo $(minor)

La valeur de minor dans l’exemple ci-dessus dans la première exécution du pipeline sera 100. Dans la deuxième exécution, elle sera 101, à condition que la valeur de major soit toujours 1.

Si vous modifiez le fichier YAML et mettez à jour la valeur de la variable major sur 2, lors de la prochaine exécution du pipeline, la valeur de minor sera 100. Les exécutions suivantes incrémentent le compteur à 101, 102, 103, ...

Plus tard, si vous modifiez le fichier YAML et que vous définissez à nouveau la valeur de major sur 1, la valeur du compteur reprend là où ce dernier s’est arrêté pour ce préfixe. Dans cet exemple, il reprend à 102.

Voici un autre exemple de définition d’une variable pour agir comme un compteur qui commence à 100, est incrémenté de 1 pour chaque exécution et est réinitialisé à 100 tous les jours.

Notes

pipeline.startTime n’est pas disponible en dehors des expressions. pipeline.startTime met en forme system.pipelineStartTime en objet de date et d’heure afin qu’il soit disponible pour utiliser des expressions. Le fuseau horaire par défaut pour pipeline.startTime est UTC. Vous pouvez modifier le fuseau horaire pour votre organisation.

jobs:
- job:
  variables:
    a: $[counter(format('{0:yyyyMMdd}', pipeline.startTime), 100)]
  steps:
  - bash: echo $(a)

Voici un exemple d’utilisation d’un compteur qui conserve une valeur distincte pour les exécutions de demandes de tirage et d’intégration continue.

variables:
  patch: $[counter(variables['build.reason'], 0)]

Les compteurs sont limités à un pipeline. En d’autres termes, sa valeur est incrémentée pour chaque exécution de ce pipeline. Il n’existe pas de compteurs pour l’étendue du projet.

endsWith

  • Évalue à True si la chaîne du paramètre de gauche se termine par le paramètre de droite
  • Paramètres min. : 2. Paramètres max. : 2
  • Caste les paramètres en chaîne pour l’évaluation
  • Effectue une comparaison ordinale ignorant la casse
  • Exemple : endsWith('ABCDE', 'DE') (retourne True)

eq

  • Évalue à True si les paramètres sont égaux
  • Paramètres min. : 2. Paramètres max. : 2
  • Convertit le paramètre droit pour correspondre au type de paramètre de gauche. Retourne False si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Exemple : eq(variables.letters, 'ABC')

format

  • Évalue les paramètres de fin et les insère dans la chaîne de paramètres de début
  • Paramètres min. : 1. Paramètres max. : N
  • Exemple : format('Hello {0} {1}', 'John', 'Doe')
  • Utilise des spécificateurs de format de date et d’heure personnalisés .NET pour la mise en forme de date (yyyy, yy, MM, M, dd, d, HH, H, m, mm, ss, s, f, ff, ffff, K)
  • Exemple : format('{0:yyyyMMdd}', pipeline.startTime). Dans ce cas, pipeline.startTime est une variable d’objet date/heure spéciale.
  • Échappez en doublant les accolades. Par exemple : format('literal left brace {{ and literal right brace }}')

ge

  • Évalue à True si le paramètre de gauche est supérieur ou égal au paramètre de droite
  • Paramètres min. : 2. Paramètres max. : 2
  • Convertit le paramètre droit pour correspondre au type de paramètre de gauche. Erreurs si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Exemple : ge(5, 5) (retourne True)

gt

  • Évalue à True si le paramètre de gauche est supérieur au paramètre de droite
  • Paramètres min. : 2. Paramètres max. : 2
  • Convertit le paramètre droit pour correspondre au type de paramètre de gauche. Erreurs si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Exemple : gt(5, 2) (retourne True)

in

  • Évalue à True si le paramètre de gauche est égal à n’importe quel paramètre de droite
  • Paramètres min. : 1. Paramètres max. : N
  • Convertit les paramètres de droite pour qu’ils correspondent au type de paramètre de gauche. La comparaison d’égalité évalue False si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Court-circuite après la première correspondance
  • Exemple : in('B', 'A', 'B', 'C') (retourne True)

join

  • Concatène tous les éléments du tableau de paramètres de droite, séparés par la chaîne de paramètre de gauche.
  • Paramètres min. : 2. Paramètres max. : 2
  • Chaque élément du tableau est converti en chaîne. Les objets complexes sont convertis en chaîne vide.
  • Si le paramètre de droite n’est pas un tableau, le résultat est le paramètre de droite converti en chaîne.

Dans cet exemple, un point-virgule est ajouté entre chaque élément du tableau. Le type de paramètre est un objet.

parameters:
- name: myArray
  type: object
  default:
    - FOO
    - BAR
    - ZOO

variables:
   A: ${{ join(';',parameters.myArray) }}

steps:
  - script: echo $A # outputs FOO;BAR;ZOO

le

  • Évalue à True si le paramètre de gauche est inférieur ou égal au paramètre de droite
  • Paramètres min. : 2. Paramètres max. : 2
  • Convertit le paramètre droit pour correspondre au type de paramètre de gauche. Erreurs si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Exemple : le(2, 2) (retourne True)

length

  • Retourne la longueur d’une chaîne ou d’un tableau, qui provient du système ou qui provient d’un paramètre
  • Paramètres min. : 1. Paramètres max. : 1
  • Exemple : length('fabrikam') retourne 8

lower

  • Convertit une chaîne ou une valeur de variable en caractères minuscules
  • Paramètres min. : 1. Paramètres max. : 1
  • Retourne l’équivalent minuscule d’une chaîne
  • Exemple : lower('FOO') retourne foo.

lt

  • Évalue à True si le paramètre gauche est inférieur au paramètre de droite
  • Paramètres min. : 2. Paramètres max. : 2
  • Convertit le paramètre droit pour correspondre au type de paramètre de gauche. Erreurs si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Exemple : lt(2, 5) (retourne True)

ne

  • Évalue à True si les paramètres ne sont pas égaux
  • Paramètres min. : 2. Paramètres max. : 2
  • Convertit le paramètre droit pour correspondre au type de paramètre de gauche. Retourne True si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Exemple : ne(1, 2) (retourne True)

not

  • Évalue à True si le paramètre est False
  • Paramètres min. : 1. Paramètres max. : 1
  • Convertit la valeur en booléen pour l’évaluation
  • Exemple : not(eq(1, 2)) (retourne True)

notIn

  • Évalue à True si le paramètre de gauche n’est pas égal à un des paramètres de droite
  • Paramètres min. : 1. Paramètres max. : N
  • Convertit les paramètres de droite pour qu’ils correspondent au type de paramètre de gauche. La comparaison d’égalité évalue False si la conversion échoue.
  • Comparaison ignorant la casse pour les chaînes
  • Court-circuite après la première correspondance
  • Exemple : notIn('D', 'A', 'B', 'C') (retourne True)

or

  • Évalue à True si un paramètre est True
  • Paramètres min. : 2. Paramètres max. : N
  • Caste les paramètres en booléen pour l’évaluation
  • Court-circuite après le premier True
  • Exemple : or(eq(1, 1), eq(2, 3)) (retourne True, court-circuite)

remplacer

  • Retourne une nouvelle chaîne dans laquelle toutes les instances d’une chaîne dans l’instance actuelle sont remplacées par une autre chaîne.
  • Paramètres min. : 3. Paramètres max. : 3
  • replace(a, b, c) : retourne a, avec toutes les instances de b remplacées par c
  • Exemple : replace('https://www.tinfoilsecurity.com/saml/consume','https://www.tinfoilsecurity.com','http://server') (retourne http://server/saml/consume)

split

  • Divise une chaîne en sous-chaînes en fonction de caractères de délimitation spécifiés
  • Paramètres min. : 2. Paramètres max. : 2
  • Le premier paramètre est la chaîne à fractionner
  • Le deuxième paramètre se compose des caractères délimitants
  • Retourne un tableau de sous-chaînes. Le tableau inclut des chaînes vides lorsque les caractères délimitants apparaissent consécutivement ou à la fin de la chaîne
  • Exemple :
    variables:
    - name: environments
      value: prod1,prod2 
    steps:  
      - ${{ each env in split(variables.environments, ',')}}:
        - script: ./deploy.sh --environment ${{ env }}
    
  • Exemple d'utilisation de split() avec replace() :
    parameters:
    - name: resourceIds
      type: object
      default:
      - /subscriptions/mysubscription/resourceGroups/myResourceGroup/providers/Microsoft.Network/loadBalancers/kubernetes-internal
      - /subscriptions/mysubscription02/resourceGroups/myResourceGroup02/providers/Microsoft.Network/loadBalancers/kubernetes
    - name: environments
      type: object
      default: 
      - prod1
      - prod2
    
    trigger:
    - main
    
    steps:
    - ${{ each env in parameters.environments }}:
      - ${{ each resourceId in parameters.resourceIds }}:
          - script: echo ${{ replace(split(resourceId, '/')[8], '-', '_') }}_${{ env }}
    

startsWith

  • Évalue à True si la chaîne de paramètre de gauche commence par le paramètre de droite
  • Paramètres min. : 2. Paramètres max. : 2
  • Caste les paramètres en chaîne pour l’évaluation
  • Effectue une comparaison ordinale ignorant la casse
  • Exemple : startsWith('ABCDE', 'AB') (retourne True)

upper

  • Convertit une valeur de chaîne ou de variable en caractères majuscules
  • Paramètres min. : 1. Paramètres max. : 1
  • Retourne l’équivalent majuscule d’une chaîne
  • Exemple : upper('bah') retourne BAH.

xor

  • Évalue à True si exactement un paramètre est True
  • Paramètres min. : 2. Paramètres max. : 2
  • Caste les paramètres en booléen pour l’évaluation
  • Exemple : xor(True, False) (retourne True)

Fonctions de vérification de l’état du travail

Vous pouvez utiliser les fonctions de vérification d’état suivantes en tant qu’expressions dans des conditions, mais pas dans les définitions de variables.

toujours

  • Évalue toujours à True (même en cas d’annulation). Remarque : Une défaillance critique peut toujours empêcher l’exécution d’une tâche. Par exemple, si l’obtention des sources a échoué.

annulé

  • Évalue à True si le pipeline a été annulé.

échec

  • Pour une étape, équivalent à eq(variables['Agent.JobStatus'], 'Failed').
  • Pour un projet :
    • Sans arguments, évalue à True uniquement en cas d’échec d’un travail précédent dans le graphe des dépendances.
    • Avec des noms de travaux en tant qu’arguments, évalue uniquement à True en cas d’échec de l’un de ces travaux.

succeeded

  • Pour une étape, équivalent à in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')
  • Utilisez avec dependsOn lorsque vous travaillez avec des travaux et que vous souhaitez évaluer si un travail précédent a réussi. Les travaux sont conçus pour s’exécuter en parallèle tandis que les phases s’exécutent séquentiellement.
  • Pour un projet :
    • Sans arguments, évalue uniquement à True si tous les travaux précédents dans le graphe des dépendances ont réussi ou partiellement réussi.
    • Avec des noms de travaux en tant qu’arguments, évalue à True si tous ces travaux ont réussi ou partiellement réussi.
    • Évalue à False si le pipeline est annulé.

succeededOrFailed

  • Pour une étape, équivalent à in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed')

  • Pour un travail :

    • Sans arguments, évalue à True indépendamment du fait que les travaux dans le graphe des dépendances ont réussi ou échoué.
    • Avec des noms de travaux en tant qu’arguments, évalue à True si l’un de ces travaux a réussi ou échoué.
    • Vous pouvez utiliser not(canceled()) à la place quand des travaux précédents ont été ignorés dans le graphe des dépendances.

    Cela est semblable à always(), sauf qu’il évaluera à False quand le pipeline est annulé.

Insertion conditionnelle

Vous pouvez utiliser les clauses if, elseif et else pour affecter des valeurs de variable de manière conditionnelle ou définir des entrées pour des tâches. Vous pouvez également exécuter une étape de manière conditionnelle lorsqu’une condition est remplie.

Vous pouvez utiliser if pour affecter des valeurs de variable de manière conditionnelle ou définir des entrées pour des tâches. Vous pouvez également exécuter une étape de manière conditionnelle lorsqu’une condition est remplie.

Les clauses elseif et else sont disponibles à partir d'Azure DevOps 2022 et ne sont pas disponibles pour Azure DevOps Server 2020 et les versions antérieures d'Azure DevOps.

Les conditions fonctionnent uniquement lors de l’utilisation de la syntaxe de modèle. En savoir plus sur la syntaxe des variables.

Pour les modèles, vous pouvez utiliser l’insertion conditionnelle lors de l’ajout d’une séquence ou d’un mappage. En savoir plus sur l’insertion conditionnelle dans les modèles.

Affecter une variable de manière conditionnelle

variables:
  ${{ if eq(variables['Build.SourceBranchName'], 'main') }}: # only works if you have a main branch
    stageName: prod

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo ${{variables.stageName}}

Définir de manière conditionnelle une entrée de tâche

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: PublishPipelineArtifact@1
  inputs:
    targetPath: '$(Pipeline.Workspace)'
    ${{ if eq(variables['Build.SourceBranchName'], 'main') }}:
      artifact: 'prod'
    ${{ else }}:
      artifact: 'dev'
    publishLocation: 'pipeline'

Exécuter une étape de manière conditionnelle

S’il n’existe aucun jeu de variables ou si la valeur de foo ne correspond pas aux conditions if, l’instruction else s’exécute. Ici, la valeur de foo retourne true dans la condition elseif.

variables:
  - name: foo
    value: contoso # triggers elseif condition

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo "start"
- ${{ if eq(variables.foo, 'adaptum') }}:
  - script: echo "this is adaptum"
- ${{ elseif eq(variables.foo, 'contoso') }}: # true
  - script: echo "this is contoso" 
- ${{ else }}:
  - script: echo "the value is not adaptum or contoso"

Each (mot clé)

Vous pouvez utiliser le mot clé each pour effectuer une boucle dans les paramètres avec le type d’objet.

parameters:
- name: listOfStrings
  type: object
  default:
  - one
  - two

steps:
- ${{ each value in parameters.listOfStrings }}:
  - script: echo ${{ value }}

En outre, vous pouvez itérer au sein d’un objet à travers des éléments imbriqués.

parameters:
- name: listOfFruits
  type: object
  default:
  - fruitName: 'apple'
    colors: ['red','green']
  - fruitName: 'lemon'
    colors: ['yellow']
steps:
- ${{ each fruit in parameters.listOfFruits }} :
  - ${{ each fruitColor in fruit.colors}} :
    - script: echo ${{ fruit.fruitName}} ${{ fruitColor }}

Les dépendances

Les expressions peuvent utiliser le contexte des dépendances pour référencer des travaux ou des phases précédents. Vous pouvez utiliser les dépendances pour :

  • Référencer l’état du travail d’un travail précédent
  • Référencer l’état de phase d’une phase précédente
  • Référencer des variables de sortie dans le travail précédent dans la même phase
  • Référencer les variables de sortie à la phase précédente d’une phase
  • Référencer des variables de sortie dans un travail à une phase précédente de la phase suivante

Le contexte est appelé dependencies pour les travaux et les phases et fonctionne comme les variables. Si vous faites référence à une variable de production d'un projet dans une autre étape, le contexte est appelé stageDependencies.

Si vous rencontrez des problèmes avec des variables de sortie contenant des guillemets (' ou "), consultez ce guide de résolution des problèmes.

Vue d'ensemble de la syntaxe des dépendances

La syntaxe du référencement des variables de production avec dépendances varie en fonction des circonstances. Voici une vue d'ensemble des scénarios les plus courants. Notez qu'il peut arriver qu'une autre syntaxe fonctionne également.

Type

Description

dépendance étape à étape (différentes étapes)

Référencez une variable de production d'une étape précédente dans un projet dans une autre étape dans une condition dans stages.

  • Syntaxe : and(succeeded(), eq(stageDependencies.<stage-name>.outputs['<job-name>.<step-name>.<variable-name>'], 'true'))
  • Exemple : and(succeeded(), eq(stageDependencies.A.outputs['A1.printvar.shouldrun'], 'true'))

Référencez une variable de production dans un projet différent dans la même étape dans stages.

  • Syntaxe : and(succeeded(), eq(dependencies.<stage-name>.outputs['<step-name>.<variable-name>'], 'true'))
  • Exemple : and(succeeded(), eq(dependencies.A.outputs['printvar.shouldrun'], 'true'))

Dépendance projet à étape (différentes étapes)

Référencez une variable de production dans une étape différente dans un job.

  • Syntaxe : eq(stageDependencies.<stage-name>.<job-name>.outputs['<step-name>.<variable-name>'], 'true')
  • Exemple : eq(stageDependencies.A.A1.outputs['printvar.shouldrun'], 'true')

Dépendance étape à étape (projet de déploiement)

Référencez une variable de production dans un projet de déploiement dans une autre étape dans stages.

  • Syntaxe : eq(dependencies.<stage-name>.outputs['<deployment-job-name>.<deployment-job-name>.<step-name>.<variable-name>'], 'true')
  • Exemple : eq(dependencies.build.outputs['build_job.build_job.setRunTests.runTests'], 'true')

Dépendance étape à étape (projet de déploiement avec ressource)

Référencez une variable de production dans un projet de déploiement qui inclut une ressource dans une étape différente dans stages.

  • Syntaxe : eq(dependencies.<stage-name>.outputs['<deployment-job-name>.<Deploy_resource-name>.<step-name>.<variable-name>'], 'true')
  • Exemple : eq(dependencies.build.outputs['build_job.Deploy_winVM.setRunTests.runTests'], 'true')

Il existe également différentes syntaxes pour les variables de production dans les projets de déploiement en fonction de la stratégie de déploiement. Pour en savoir plus, consultez Projets de déploiement.

Dépendances phase à phase

Structurellement, l’objet dependencies est une carte des noms de travaux et de phases vers results et outputs. Exprimé au format JSON, il se présente comme suit :

"dependencies": {
  "<STAGE_NAME>" : {
    "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
    "outputs": {
        "jobName.stepName.variableName": "value"
    }
  },
  "...": {
    // another stage
  }
}

Remarque

Les exemples suivants utilisent une syntaxe de pipeline standard. Si vous utilisez des pipelines de déploiement, la syntaxe d’une variable et celle d’une variable conditionnelle diffèrent. Pour plus d’informations sur la syntaxe spécifique à utiliser, consultez Travaux de déploiement.

Utilisez cette forme de dependencies pour mapper dans des variables ou vérifier les conditions à un niveau intermédiaire.

Dans cet exemple, il existe deux étapes, A et B. L'étape A a la condition false et ne s'exécute jamais comme résultat. L'étape B s'exécute si le résultat de l'étape A est Succeeded, SucceededWithIssues ou Skipped. L'étape B s'exécute, car l'étape A a été ignorée.

stages:
- stage: A
  condition: false
  jobs:
  - job: A1
    steps:
    - script: echo Job A1
- stage: B
  condition: in(dependencies.A.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
  jobs:
  - job: B1
    steps:
    - script: echo Job B1

Les phases peuvent également utiliser des variables de sortie d’une autre phase. Dans cet exemple, il existe également deux étapes. L'étape A inclut un projet, A1, qui définit une variable de production shouldrun sur true. L'étape B s'exécute quand shouldrun est true. Comme shouldrun est true, l'étape B s'exécute.

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
     # or on Windows:
     # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
       name: printvar

- stage: B
  condition: and(succeeded(), eq(dependencies.A.outputs['A1.printvar.shouldrun'], 'true'))
  dependsOn: A
  jobs:
  - job: B1
    steps:
    - script: echo hello from Stage B

Remarque

Par défaut, chaque index d’un pipeline dépend de celui qui se trouve juste avant lui dans le fichier YAML. Si vous devez faire référence à une phase qui n’est pas immédiatement antérieure à la phase actuelle, vous pouvez remplacer cette phase automatique par défaut en ajoutant une section dependsOn à la phase.

Dépendances de travail à travail au sein d’une phase

Au niveau du travail au sein d’une seule phase, les données dependencies ne contiennent pas d’informations au niveau de la phase.

"dependencies": {
  "<JOB_NAME>": {
    "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
    "outputs": {
      "stepName.variableName": "value1"
    }
  },
  "...": {
    // another job
  }
}

Dans cet exemple, il existe trois projets (a, b et c). Le projet a toujours été ignoré en raison de condition: false. Le projet b s'exécute, car aucune condition n'est associée. Le projet c s'exécute, car toutes ses dépendances réussissent (projet b) ou sont ignorées (projet a).

jobs:
- job: a
  condition: false
  steps:
  - script: echo Job a
- job: b
  steps:
  - script: echo Job b
- job: c
  dependsOn:
  - a
  - b
  condition: |
    and
    (
      in(dependencies.a.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
      in(dependencies.b.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
    )
  steps:
  - script: echo Job c

Dans cet exemple, le travail B dépend d’une variable de sortie du travail A.

jobs:
- job: A
  steps:
  - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
  # or on Windows:
  # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
    name: printvar

- job: B
  condition: and(succeeded(), eq(dependencies.A.outputs['printvar.shouldrun'], 'true'))
  dependsOn: A
  steps:
  - script: echo hello from B

Dépendances de travail à travail entre différentes phases

Au niveau du travail, vous pouvez également référencer les sorties d’un travail d’une phase précédente. Cela nécessite l’utilisation du contexte stageDependencies.

"stageDependencies": {
  "<STAGE_NAME>" : {
    "<JOB_NAME>": {
      "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
      "outputs": {
          "stepName.variableName": "value"
      }
    },
    "...": {
      // another job
    }
  },
  "...": {
    // another stage
  }
}

Dans cet exemple, le travail B1 s’exécute si le travail A1 est ignoré. Le travail B2 vérifie la valeur de la variable de sortie du travail A1 pour déterminer s’il doit s’exécuter.

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
     # or on Windows:
     # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
       name: printvar

- stage: B
  dependsOn: A
  jobs:
  - job: B1
    condition: in(stageDependencies.A.A1.result, 'Skipped') # change condition to `Succeeded and stage will be skipped`
    steps:
    - script: echo hello from Job B1
  - job: B2
    condition: eq(stageDependencies.A.A1.outputs['printvar.shouldrun'], 'true')
    steps:
     - script: echo hello from Job B2

Si un travail dépend d’une variable définie par un travail de déploiement à une phase différente, la syntaxe est différente. Dans l’exemple suivant, le travail run_tests s’exécute si le travail de déploiement build_job a défini runTests sur true. Notez que la clé utilisée pour le dictionnaire outputs est build_job.setRunTests.runTests.

stages:
- stage: build
  jobs:
  - deployment: build_job
    environment:
      name: Production
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            name: setRunTests
            inputs:
              targetType: inline
              pwsh: true
              script: |
                $runTests = "true"
                echo "setting runTests: $runTests"
                echo "##vso[task.setvariable variable=runTests;isOutput=true]$runTests"

- stage: test
  dependsOn:
  - 'build'
  jobs:  
    - job: run_tests
      condition: eq(stageDependencies.build.build_job.outputs['build_job.setRunTests.runTests'], 'true')
      steps:
        ...

Variables de production de projet de déploiement

Si une phase dépend d’une variable définie par un travail de déploiement dans une autre phase, la syntaxe est différente. Dans l’exemple suivant, la phase test dépend de build_job pour le déploiement, qui définit shouldTest sur true. Notez que dans le condition de la phase test, build_job apparaît deux fois.

stages:
- stage: build
  jobs:
  - deployment: build_job
    environment:
      name: Production
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            name: setRunTests
            inputs:
              targetType: inline
              pwsh: true
              script: |
                $runTests = "true"
                echo "setting runTests: $runTests"
                echo "##vso[task.setvariable variable=runTests;isOutput=true]$runTests"

- stage: test
  dependsOn:
  - 'build'
  condition: eq(dependencies.build.outputs['build_job.build_job.setRunTests.runTests'], 'true')
  jobs:
    - job: A
      steps:
        - script: echo Hello from job A

Dans l’exemple ci-dessus, la condition fait référence à un environnement et non à une ressource d’environnement. Pour référencer une ressource d’environnement, vous devez ajouter le nom de la ressource d’environnement à la condition de dépendances. Dans l’exemple suivant, la condition fait référence à une ressource de machine virtuelle d’environnement nommée vmtest.

stages:
- stage: build
  jobs:
  - deployment: build_job
    environment:
      name: vmtest
      resourceName: winVM2
      resourceType: VirtualMachine
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            name: setRunTests
            inputs:
              targetType: inline
              pwsh: true
              script: |
                $runTests = "true"
                echo "setting runTests: $runTests"
                echo "##vso[task.setvariable variable=runTests;isOutput=true]$runTests"

- stage: test
  dependsOn:
  - 'build'
  condition: eq(dependencies.build.outputs['build_job.Deploy_winVM2.setRunTests.runTests'], 'true')
  jobs:
  - job: A
    steps:
     - script: echo Hello from job A

Tableaux filtrés

Lorsque vous utilisez une collection d’éléments, vous pouvez utiliser la syntaxe * pour appliquer un tableau filtré. Un tableau filtré retourne tous les objets/éléments, quel que soit leur nom.

Par exemple, considérez un tableau d’objets nommé foo. Nous voulons obtenir un tableau des valeurs de la propriété id dans chaque objet de notre tableau.

[
    { "id": 1, "a": "avalue1"},
    { "id": 2, "a": "avalue2"},
    { "id": 3, "a": "avalue3"}
]

Nous pourrions effectuer les opérations suivantes :

foo.*.id

Cela indique au système de travailler sur foo en tant que tableau filtré, puis de sélectionner la propriété id.

Cela retournerait :

[ 1, 2, 3 ]

Cast de type

Les valeurs d’une expression peuvent être converties d’un type à un autre à mesure que l’expression est évaluée. Lorsqu’une expression est évaluée, les paramètres sont fusionnés avec le type de données approprié, puis reconvertis en chaînes.

Par exemple, dans ce YAML, les valeurs True et False sont converties en 1, et 0 lorsque l’expression est évaluée. La fonction lt() retourne True lorsque le paramètre de gauche est inférieur au paramètre de droite.

variables:
  firstEval: $[lt(False, True)] # 0 vs. 1, True
  secondEval: $[lt(True, False)] # 1 vs. 0, False

steps:
- script: echo $(firstEval)
- script: echo $(secondEval)

Dans cet exemple, les valeurs variables.emptyString et la chaîne vide sont toutes deux évaluées comme des chaînes vides. La fonction coalesce() évalue les paramètres dans l’ordre et retourne la première valeur qui n’est pas égale à null ou empty-string.

variables:
  coalesceLiteral: $[coalesce(variables.emptyString, '', 'literal value')]

steps:
- script: echo $(coalesceLiteral) # outputs literal value

Les règles de conversion détaillées sont répertoriées ci-dessous.

De/À Boolean Null Number String Version
Booléen - - Oui Oui -
Null Oui - Oui Oui -
Nombre Oui - - Oui Partiel
Chaîne Oui Partiel Partiel - Partiel
Version Oui - - Oui -

Boolean

Numéro de destination :

  • False0
  • True1

En chaîne :

  • False'False'
  • True'True'

Null

  • En booléen : False
  • Numéro de destination : 0
  • En chaîne : '' (chaîne vide)

Number

  • En booléen : 0False, tout autre nombre → True
  • En version : doit être supérieur à zéro et contenir une décimale autre que zéro. Doit être inférieur à Int32.MaxValue (composant décimal également).
  • En chaîne : convertit le nombre en chaîne sans séparateur de milliers ni séparateur décimal.

String

  • En booléen : '' (chaîne vide) → False, toute autre chaîne → True
  • En valeur null : '' (chaîne vide) → Null, toute autre chaîne non convertible
  • En nombre : '' (la chaîne vide) → 0, sinon, exécute Int32.TryParse de C# avec InvariantCulture et les règles suivantes : AllowDecimalPoint | AllowLeadingSign | AllowLeadingWhite | AllowThousands | AllowTrailingWhite. Si TryParse échoue, il n’est pas convertible.
  • En version : exécute Version.TryParse de C#. Doit contenir au minimum les composants Major et Minor. Si TryParse échoue, il n’est pas convertible.

Version

  • En booléen : True
  • En chaîne : Major.Minor ou Major.Minor.Build ou Major.Minor.Build.Revision.

Questions fréquentes (FAQ)

Je veux faire quelque chose qui n’est pas pris en charge par les expressions. Quelles sont les options dont je dispose pour étendre la fonctionnalité des pipelines ?

Vous pouvez personnaliser votre pipeline avec un script qui inclut une expression. Par exemple, cet extrait de code prend la variable BUILD_BUILDNUMBER et la fractionne avec Bash. Ce script génère deux nouvelles variables, $MAJOR_RUN et $MINOR_RUN, pour les numéros d’exécution majeurs et mineurs. Les deux variables sont ensuite utilisées pour créer deux variables de pipeline, $major et $minor, avec task.setvariable. Ces variables sont disponibles pour les étapes en aval. Pour partager des variables entre pipelines, consultez Groupes de variables.

steps:
- bash: |
    MAJOR_RUN=$(echo $BUILD_BUILDNUMBER | cut -d '.' -f1)
    echo "This is the major run number: $MAJOR_RUN"
    echo "##vso[task.setvariable variable=major]$MAJOR_RUN"

    MINOR_RUN=$(echo $BUILD_BUILDNUMBER | cut -d '.' -f2)
    echo "This is the minor run number: $MINOR_RUN"
    echo "##vso[task.setvariable variable=minor]$MINOR_RUN"

- bash: echo "My pipeline variable for major run is $(major)"
- bash: echo "My pipeline variable for minor run is $(minor)"