Delen via


Pijplijnvoorwaarden

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

In dit artikel worden de voorwaarden beschreven waaronder een Azure Pipelines-fase, -taak of -stap wordt uitgevoerd en hoe u verschillende voorwaarden opgeeft. Zie de belangrijkste concepten voor Azure Pipelines voor meer context over fasen, taken en stappen.

  • Standaard wordt een taak of fase uitgevoerd als er geen afhankelijkheid is van een andere taak of fase, of als alle afhankelijkheden succesvol voltooid zijn. Deze vereiste geldt niet alleen voor directe afhankelijkheden, maar voor hun indirecte afhankelijkheden, die recursief worden berekend.

  • Het is standaard dat een stap wordt uitgevoerd als er nog niets in de taak is mislukt en de voorafgaande stap is voltooid.

U kunt dit gedrag overschrijven of aanpassen door een fase, taak of stap af te dwingen, zelfs als een eerdere afhankelijkheid mislukt of door een aangepaste voorwaarde op te geven.

Notitie

In dit artikel worden de mogelijkheden van YAML-pijplijnen besproken. Voor klassieke pijplijnen kunt u bepaalde voorwaarden opgeven waaronder taken of taken worden uitgevoerd in de beheeropties van elke taak en in de aanvullende opties voor een taak in een release-pijplijn.

Voorwaarden waaronder een fase, taak of stap wordt uitgevoerd

In de YAML van de pijplijndefinitie kunt u de volgende voorwaarden opgeven waaronder een fase, taak of stap wordt uitgevoerd:

  • Alleen wanneer alle vorige directe en indirecte afhankelijkheden met dezelfde agentgroep slagen. Als u verschillende agentpools hebt, worden deze fasen of taken gelijktijdig uitgevoerd. Deze voorwaarde is de standaardvoorwaarde als er geen voorwaarde is ingesteld in de YAML.

  • Zelfs als een eerdere afhankelijkheid mislukt, tenzij de uitvoering wordt geannuleerd. Gebruik succeededOrFailed() in de YAML voor deze voorwaarde.

  • Zelfs als een eerdere afhankelijkheid mislukt en zelfs als de uitvoering wordt geannuleerd. Gebruik always() in de YAML voor deze voorwaarde.

  • Alleen wanneer een eerdere afhankelijkheid mislukt. Gebruik failed() in de YAML voor deze voorwaarde.

  • Aangepaste voorwaarden.

Fasen, taken en stappen worden standaard uitgevoerd als alle directe en indirecte afhankelijkheden slagen. Deze status is hetzelfde als het opgeven condition: succeeded(). Voor meer informatie kunt u de functie Geslaagde status bekijken.

Wanneer u een condition eigenschap opgeeft voor een fase, taak of stap, overschrijft u de standaardwaarde condition: succeeded(). Als u uw eigen voorwaarden opgeeft, kan dit ertoe leiden dat uw fase, taak of stap wordt uitgevoerd, zelfs als de build is geannuleerd. Zorg ervoor dat de voorwaarden die u schrijft rekening houden met de status van de bovenliggende fase of taak.

In het volgende YAML-voorbeeld ziet u de always() en failed() voorwaarden. De stap in de eerste taak wordt uitgevoerd, zelfs als afhankelijkheden mislukken of als de build wordt geannuleerd. In de tweede scripttaak laat exit 1 de Foo taak mislukken. De tweede taak wordt alleen uitgevoerd als de eerste taak mislukt.

jobs:
- job: Foo
  steps:
  - script: echo Hello!
    condition: always() # this step runs, even if the build is canceled
  - script: |
      echo "This task will fail."
      exit 1 
- job: Bar
  dependsOn: Foo
  condition: failed() # this job runs only if Foo fails

U kunt ook variabelen instellen en gebruiken in voorwaarden. In het volgende voorbeeld wordt een isMain variabele ingesteld en gebruikt om aan te wijzen main als de 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)

Belangrijk

Voorwaarden worden geëvalueerd om te bepalen of een fase, taak of stap moet worden gestart. Daarom is niets wat tijdens de uitvoeringstijd binnen die werkeenheid wordt berekend beschikbaar. Als u bijvoorbeeld een taak hebt waarmee een variabele wordt ingesteld met behulp van een runtime-expressie met $[ ] syntaxis, kunt u die variabele niet gebruiken in een aangepaste voorwaarde in die taak.

Aangepaste voorwaarden

Als de ingebouwde voorwaarden niet aan uw behoeften voldoen, kunt u aangepaste voorwaarden opgeven. U schrijft voorwaarden als expressies in YAML-pijplijndefinities.

De agent evalueert de expressie die begint met de binnenste functie en gaat naar buiten. Het uiteindelijke resultaat is een Booleaanse waarde die bepaalt of de taak, het werk of de fase moet worden uitgevoerd. Zie Expressies voor een volledige handleiding voor de syntaxis.

Als een van uw voorwaarden ervoor zorgt dat de taak kan worden uitgevoerd, zelfs nadat de build is geannuleerd, geeft u een redelijke waarde op voor de annulerings-time-out, waardoor deze taken voldoende tijd hebben om te voltooien nadat de gebruiker een uitvoering heeft geannuleerd.

Voorwaardelijke uitkomsten wanneer een build wordt geannuleerd

Als u een build annuleert, betekent dit niet dat alle fasen, taken of stappen niet meer worden uitgevoerd. Welke fasen, taken of stappen niet meer worden uitgevoerd, is afhankelijk van de opgegeven voorwaarden en op welk moment van de uitvoering van de pijplijn u de build hebt geannuleerd. Als een bovenliggende fase, taak of stap wordt overgeslagen, dan wordt de taak niet uitgevoerd, ongeacht de voorwaarden.

Een fase, taak of stap wordt uitgevoerd wanneer aan de voorwaarden wordt voldaan. Als uw voorwaarde niet rekening houdt met de status van de bovenliggende taak, kan de taak worden uitgevoerd, zelfs als het bovenliggende item wordt geannuleerd. Als u wilt bepalen of fasen, taken of stappen met voorwaarden worden uitgevoerd wanneer een build wordt geannuleerd, moet u een functie voor taakstatuscontrole opnemen in uw voorwaarden.

In de volgende voorbeelden ziet u de resultaten van verschillende voorwaarden die zijn ingesteld voor fasen, taken of stappen wanneer de build wordt geannuleerd.

Fasevoorbeeld 1

In de volgende pijplijn is stage2 standaard afhankelijk van stage1, maar stage2 heeft een condition ingesteld om te draaien wanneer de bronbranch main is, ongeacht de status van stage1.

Als u een build in de wachtrij plaatst op de main branch en deze annuleert terwijl stage1 aan het draaien is, draait stage2 nog steeds, omdat eq(variables['Build.SourceBranch'], 'refs/heads/main') gelijk is aan 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

Fasevoorbeeld 2

In de volgende pijplijn is stage2 standaard afhankelijk van stage1. Job B in stage2 heeft een condition set. Als u een build in de main-tak in de wachtrij plaatst en deze annuleert terwijl stage1 wordt uitgevoerd, wordt stage2 niet uitgevoerd, zelfs niet als het een taak bevat waarvan de voorwaarde resulteert in true.

De reden hiervoor is dat stage2 de standaardwaarde condition: succeeded() is, die false evalueert wanneer stage1 wordt geannuleerd. Daarom wordt stage2 overgeslagen en wordt geen enkele taak uitgevoerd.

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

Fasevoorbeeld 3

In de volgende pijplijn is standaard stage2 afhankelijk van stage1, en de stap in de taak B heeft een condition-instelling.

Als u een build op de main vertakking in de wachtrij zet en deze annuleert terwijl stage1 wordt uitgevoerd, wordt stage2 niet uitgevoerd, zelfs niet als het een stap bevat in de taak B waarvan de voorwaarde waar is bij true. De reden hiervoor is dat stage2 wordt overgeslagen als reactie op stage1 geannuleerd wordt.

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

Taakvoorbeeld 1

In de volgende YAML-pijplijn is de taak B standaard afhankelijk van de taak A , maar de taak B heeft een condition set die moet worden uitgevoerd wanneer de bronbranch zich bevindt main. Als u een build op de main-vertakking in de wachtrij zet en deze annuleert terwijl taak A wordt uitgevoerd, blijft taak B nog steeds draaien, omdat eq(variables['Build.SourceBranch'], 'refs/heads/main') evalueert tot 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

Als u wilt dat de taak B alleen wordt uitgevoerd wanneer de taak A slaagt en de buildbron de main branch is, moet uw conditionand(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) zijn.

Taakvoorbeeld 2

In de volgende pijplijn is de taak B standaard afhankelijk van de taak A . Als u een build in de wachtrij zet op de main-tak en deze annuleert terwijl taak A wordt uitgevoerd, wordt taak B niet uitgevoerd, ook al heeft de stap een condition die resulteert in true.

De reden hiervoor is dat taak B leidt tot false wanneer taak A wordt geannuleerd. Daarom wordt de taak B overgeslagen en worden de stappen niet uitgevoerd.

jobs:
- job: A
  steps:
  - script: sleep 30
- job: B
  dependsOn: A 
  steps:
    - script: echo step 2.1
  condition: and(eq(variables['Build.SourceBranch'], 'refs/heads/main'), succeeded())

Stapvoorbeeld

U kunt ook voorwaarden voor stappen hebben.

In de volgende pijplijn heeft stap 2.3 een condition set om uit te voeren wanneer de bronvertakking main is. Als u een build in de wachtrij zet op de main vertakking en deze annuleert terwijl stap 2.1 of 2.2 wordt uitgevoerd, wordt stap 2.3 nog steeds uitgevoerd, omdat eq(variables['Build.SourceBranch'], 'refs/heads/main') wordt geëvalueerd als 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')

Voorwaarde-instellingen

In de volgende tabel ziet u voorbeeldinstellingen condition voor het produceren van verschillende resultaten.

Notitie

Release.Artifacts.{artifact-alias}.SourceBranch is equivalent aan Build.SourceBranch.

Gewenst resultaat Voorbeeld van het instellen van voorwaarden
Voer uit als de bronbranch main is, zelfs als de bovenliggende of vorige fase, taak of stap is mislukt of is geannuleerd. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Voer uit als de bronbranch main is en de bovenliggende of vorige fase, taak of stap is geslaagd. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Voer uit als de bronbranch niet 'main' is en de ouder- of voorgaande fase, taak of stap is geslaagd. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Uitvoeren voor gebruikersonderwerp-branches, als de bovenliggende of voorgaande fase, taak of stap geslaagd is. and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
Wordt uitgevoerd voor CI-builds (continue integratie), als de bovenliggende of vorige fase, taak of stap is geslaagd. and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
Voer uit als de build is geactiveerd door een vertakkingsbeleid voor een pull-aanvraag en de bovenliggende of vorige fase, taak of stap is mislukt. and(failed(), eq(variables['Build.Reason'], 'PullRequest'))
Uitvoeren van een geplande build, zelfs als de bovenliggende of vorige fase, taak of stap is mislukt of is geannuleerd. eq(variables['Build.Reason'], 'Schedule')
Voer uit als een variabele is ingesteld op true, zelfs als de bovenliggende of vorige fase, taak of stap is mislukt of is geannuleerd. eq(variables['System.debug'], true)

Notitie

U kunt een voorwaarde instellen die moet worden uitgevoerd als een variabele null is (lege tekenreeks). Omdat alle variabelen worden behandeld als tekenreeksen in Azure Pipelines, is een lege tekenreeks gelijk aan null in de volgende pijplijn:

variables:
- name: testEmpty
  value: ''

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

Parameters in voorwaarden

Parameteruitbreiding vindt plaats voordat voorwaarden worden overwogen. Wanneer u daarom een parameter declareert in dezelfde pijplijn als een voorwaarde, kunt u de parameter insluiten in de voorwaarde. Het script in de volgende YAML wordt uitgevoerd omdat parameters.doThing dit waar is.

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

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

In condition de voorgaande pijplijn worden twee functies gecombineerd: succeeded() en ${{ eq(parameters.doThing, true) }}. De succeeded() functie controleert of de vorige stap is geslaagd. De succeeded() functie retourneert true omdat er geen vorige stap is.

De ${{ eq(parameters.doThing, true) }} functie controleert of de doThing parameter gelijk is aan true. Aangezien de standaardwaarde voor doThingtrue is, retourneert de voorwaarde true standaard, tenzij de pijplijn een andere waarde instelt.

Sjabloonparameters in voorwaarden

Wanneer u een parameter doorgeeft aan een sjabloon, moet u de waarde van de parameter instellen in uw sjabloon of templateContext gebruiken om de parameter door te geven aan de sjabloon.

Het volgende parameters.yml bestand declareert bijvoorbeeld de doThing parameter en de standaardwaarde:

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

De pijplijncode verwijst naar de parameters.yml-sjabloon . De uitvoer van de pijplijn is I did a thing omdat de parameter doThing waar is.

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

trigger:
- none

extends:
  template: parameters.yml

Zie de sjabloongebruiksreferentie voor meer voorbeelden van sjabloonparameters.

Taakuitvoervariabelen die worden gebruikt in volgende taakvoorwaarden

U kunt een variabele beschikbaar maken voor toekomstige taken en deze opgeven in een voorwaarde. Variabelen die beschikbaar zijn voor toekomstige taken moeten worden gemarkeerd als uitvoervariabelen met meerdere taken, isOutput=truezoals in de volgende code:

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

Variabelen die zijn gemaakt in een stap die wordt gebruikt in de volgende stapvoorwaarden

U kunt een variabele maken die beschikbaar is voor toekomstige stappen die moeten worden opgegeven in een voorwaarde. Variabelen die zijn gemaakt op basis van stappen zijn standaard beschikbaar voor toekomstige stappen en hoeven niet te worden gemarkeerd als uitvoervariabelen voor meerdere taken.

Er zijn enkele belangrijke dingen die u moet weten over variabelen in scope, die vanuit stappen zijn gecreëerd.

  • Variabelen die zijn gemaakt in een stap in een taak, zijn gericht op de stappen in dezelfde taak.
  • Variabelen die in een stap zijn gemaakt, zijn alleen beschikbaar in volgende stappen als omgevingsvariabelen.
  • Variabelen die in een stap zijn gemaakt, kunnen niet worden gebruikt in de stap die deze definieert.

In het volgende voorbeeld ziet u het maken van een pijplijnvariabele in een stap en het gebruik van de variabele in de voorwaarde en het script van een volgende stap.

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

Veelgestelde vragen

Hoe kan ik een taak activeren als een vorige taak succesvol was, maar met problemen?

U kunt het resultaat van de vorige taak in een voorwaarde gebruiken. In het volgende YAML kan bijvoorbeeld taak B worden uitgevoerd met de voorwaarde eq(dependencies.A.result,'SucceededWithIssues'), nadat taak A slaagt ondanks problemen.

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

Ik heb mijn build geannuleerd, maar het wordt nog steeds uitgevoerd. Waarom?

U kunt dit probleem ondervinden als een voorwaarde die is geconfigureerd in een fase geen functie voor taakstatuscontrole bevat. U kunt het probleem oplossen door een functie voor taakstatuscontrole toe te voegen aan de voorwaarde.

Als u een taak annuleert terwijl deze zich in de wachtrijfase bevindt, maar niet wordt uitgevoerd, wordt de hele taak geannuleerd, inclusief alle andere fasen. Zie eerder in dit artikel Resultaten van voorwaarden wanneer een build wordt geannuleerd voor meer informatie.