Pipelinevillkor

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

Den här artikeln beskriver de villkor under vilka en Azure Pipelines-fas, ett jobb eller ett steg körs och hur du anger olika villkor. Mer kontext om steg, jobb och steg finns i Viktiga begrepp för Azure Pipelines.

  • Som standard körs ett jobb eller en fas om det inte är beroende av något annat jobb eller stadium, eller om alla dess beroenden har slutförts och slutförts. Det här kravet gäller inte bara direkta beroenden, utan även deras indirekta beroenden, som beräknas rekursivt.

  • Som standard körs ett steg om inget i jobbet misslyckades ännu och steget omedelbart före det slutfördes.

Du kan åsidosätta eller anpassa det här beteendet genom att tvinga ett steg, jobb eller steg att köras även om ett tidigare beroende misslyckas eller genom att ange ett anpassat villkor.

Kommentar

I den här artikeln beskrivs YAML-pipelinefunktioner. För klassiska pipelines kan du ange vissa villkor under vilka aktiviteter eller jobb körs i kontrollalternativen för varje aktivitet och i Ytterligare alternativ för ett jobb i en versionspipeline.

Villkor under vilka ett steg, ett jobb eller ett steg körs

I pipelinedefinitionen YAML kan du ange följande villkor under vilka ett steg, ett jobb eller ett steg körs:

  • Endast när alla tidigare direkta och indirekta beroenden med samma agentpool lyckas. Om du har olika agentpooler körs dessa faser eller jobb samtidigt. Det här villkoret är standard om inget villkor har angetts i YAML.

  • Även om ett tidigare beroende misslyckas, såvida inte körningen avbryts. Använd succeededOrFailed() i YAML för det här villkoret.

  • Även om ett tidigare beroende misslyckas och även om körningen avbryts. Använd always() i YAML för det här villkoret.

  • Endast när ett tidigare beroende misslyckas. Använd failed() i YAML för det här villkoret.

  • Anpassade villkor.

Som standard körs steg, jobb och steg om alla direkta och indirekta beroenden lyckas. Den här statusen är samma som att condition: succeeded()ange . Mer information finns i statusfunktionen lyckades.

När du anger en condition egenskap för en fas, ett jobb eller ett steg skriver du över standardvärdet condition: succeeded(). Om du anger dina egna villkor kan det leda till att steget, jobbet eller steget körs även om bygget avbryts. Kontrollera att de villkor som du skriver tar hänsyn till tillståndet för det överordnade steget eller jobbet.

I följande YAML-exempel visas villkoren always() och failed() . Steget i det första jobbet körs även om beroenden misslyckas eller om bygget avbryts. Det andra jobbet körs bara om det första jobbet misslyckas.

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

Du kan också ange och använda variabler i villkor. I följande exempel anges och används en isMain variabel för att ange main som 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)

Viktigt!

Villkor utvärderas för att avgöra om ett steg, ett jobb eller ett steg ska startas. Därför är inget som beräknas vid körning i den arbetsenheten tillgängligt. Om du till exempel har ett jobb som anger en variabel med ett körningsuttryck med $[ ] syntax kan du inte använda variabeln i ett anpassat villkor i jobbet.

Anpassade villkor

Om de inbyggda villkoren inte uppfyller dina behov kan du ange anpassade villkor. Du skriver villkor som uttryck i YAML-pipelinedefinitioner.

Agenten utvärderar uttrycket som börjar med den innersta funktionen och fortsätter utåt. Slutresultatet är ett booleskt värde som avgör om uppgiften, jobbet eller fasen ska köras eller inte. En fullständig guide till syntaxen finns i Uttryck.

Om något av dina villkor gör det möjligt för aktiviteten att köras även efter att bygget har avbrutits anger du ett rimligt värde för tidsgränsen för att avbryta tidsgränsen så att dessa aktiviteter har tillräckligt med tid att slutföra efter att användaren har avbrutit en körning.

Villkorsresultat när en version avbryts

Att avbryta ett bygge innebär inte att alla dess faser, jobb eller steg slutar köras. Vilka steg, jobb eller steg som slutar köras beror på de villkor som du angav och vid vilken tidpunkt av pipelinens körning du avbröt bygget. Om en fas, ett jobb eller ett stegs överordnade objekt hoppas över, körs inte aktiviteten, oavsett villkor.

Ett steg, ett jobb eller ett steg körs när dess villkor utvärderas till true. Om ditt villkor inte tar hänsyn till tillståndet för aktivitetens överordnade kan aktiviteten köras även om dess överordnade objekt avbryts. Kontrollera om steg, jobb eller steg med villkor körs när en version avbryts genom att inkludera en funktion för jobbstatuskontroll i dina villkor.

I följande exempel visas resultatet av olika villkor som angetts för steg, jobb eller steg när bygget avbryts.

Stegexempel 1

I följande pipeline skulle som standard stage2 vara beroende av stage1 stage1, men stage2 har en condition uppsättning som ska köras när källgrenen är main, oavsett status.

Om du köar ett bygge på grenen main och avbryter den medan stage1 den körs stage2 , körs fortfarande, eftersom eq(variables['Build.SourceBranch'], 'refs/heads/main') utvärderas till 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

Stegexempel 2

I följande pipeline stage2 är beroende av stage1 som standard. Jobbet B i stage2 har en condition uppsättning. Om du köar ett bygge på grenen main och avbryter den medan stage1 den körs stage2 , körs den inte, även om den innehåller ett jobb vars villkor utvärderas till true.

Orsaken är att stage2 har standardvärdet condition: succeeded(), som utvärderas till false när stage1 avbryts. stage2 Därför hoppas över och inget av dess jobb körs.

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

Stegexempel 3

I följande pipeline beror som standard stage2stage1, och steget inuti jobbet B har en condition uppsättning.

Om du köar ett bygge på grenen main och avbryter den medan stage1 den körs stage2 , körs den inte, även om den innehåller ett steg i jobbet B vars villkor utvärderas till true. Orsaken är att stage2 hoppas över som svar på att stage1 avbrytas.

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

Jobbexempel 1

I följande YAML-pipeline är jobbet B beroende av jobb A som standard, men jobbet B har en condition uppsättning som ska köras när källgrenen är main. Om du köar ett bygge på grenen main och avbryter det medan jobbet A körs, körs jobbet B fortfarande eftersom eq(variables['Build.SourceBranch'], 'refs/heads/main') utvärderas till 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

Om du bara vill att jobbet B ska köras när jobbet A lyckas och byggkällan är grenen main bör du condition vara and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')).

Jobbexempel 2

I följande pipeline är jobbet B beroende av jobbet A som standard. Om du köar ett bygge på grenen main och avbryter det medan jobbet A körs, körs inte jobbet B , även om steget har ett condition som utvärderas till true.

Orsaken är att jobbet B har standardvärdet condition: succeeded(), som utvärderas till false när jobbet A avbryts. Därför hoppas jobbet B över och inget av stegen körs.

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

Stegexempel

Du kan också ha villkor för steg.

I följande pipeline har steg 2.3 en condition uppsättning som ska köras när källgrenen är main. Om du köar en version av grenen main och avbryter den medan steg 2.1 eller 2.2 körs, körs steg 2.3 fortfarande eftersom eq(variables['Build.SourceBranch'], 'refs/heads/main') utvärderas till 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')

Villkorsinställningar

I följande tabell visas exempelinställningar condition för att skapa olika resultat.

Kommentar

Release.Artifacts.{artifact-alias}.SourceBranch motsvarar Build.SourceBranch.

Önskat resultat Exempel på villkorsinställning
Kör om källgrenen är huvudgrenen, även om det överordnade eller föregående steget, jobbet eller steget misslyckades eller avbröts. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Kör om källgrenen är huvudgrenen och det överordnade eller föregående steget, jobbet eller steget lyckades. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Kör om källgrenen inte är huvudgrenen och det överordnade eller föregående steget, jobbet eller steget lyckades. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Kör för användarämnesgrenar om det överordnade eller föregående steget, jobbet eller steget lyckades. and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
Kör för kontinuerlig integrering (CI) om det överordnade eller föregående steget, jobbet eller steget lyckades. and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
Kör om bygget utlöstes av en grenprincip för en pull-begäran och det överordnade eller föregående steget, jobbet eller steget misslyckades. and(failed(), eq(variables['Build.Reason'], 'PullRequest'))
Kör för en schemalagd version, även om det överordnade eller föregående steget, jobbet eller steget misslyckades eller avbröts. eq(variables['Build.Reason'], 'Schedule')
Kör om en variabel är inställd på true, även om det överordnade eller föregående steget, jobbet eller steget misslyckades eller avbröts. eq(variables['System.debug'], true)

Kommentar

Du kan ange att ett villkor ska köras om en variabel är null (tom sträng). Eftersom alla variabler behandlas som strängar i Azure Pipelines motsvarar null en tom sträng i följande pipeline:

variables:
- name: testEmpty
  value: ''

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

Parametrar i villkor

Parameterexpansion sker innan villkor övervägs. När du deklarerar en parameter i samma pipeline som ett villkor kan du därför bädda in parametern i villkoret. Skriptet i följande YAML körs eftersom parameters.doThing är sant.

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

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

I condition föregående pipeline kombineras två funktioner: succeeded() och ${{ eq(parameters.doThing, true) }}. Funktionen succeeded() kontrollerar om föregående steg lyckades. Funktionen succeeded() returnerar true eftersom det inte fanns något föregående steg.

Funktionen ${{ eq(parameters.doThing, true) }} kontrollerar om parametern doThing är lika med true. Eftersom standardvärdet för doThing är truereturneras true villkoret som standard om inte pipelinen anger ett annat värde.

Mallparametrar i villkor

När du skickar en parameter till en mall måste du antingen ange parameterns värde i mallen eller använda templateContext för att skicka parametern till mallen.

Följande parameters.yml-fil deklarerar till exempel parametern doThing och standardvärdet:

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

Pipelinekoden refererar till mallen parameters.yml . Utdata från pipelinen beror I did a thing på att parametern doThing är sann.

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

trigger:
- none

extends:
  template: parameters.yml

Fler exempel på mallparameter finns i mallanvändningsreferensen.

Jobbutdatavariabler som används i efterföljande jobbvillkor

Du kan göra en variabel tillgänglig för framtida jobb och ange den i ett villkor. Variabler som är tillgängliga för framtida jobb måste markeras som utdatavariabler för flera jobb med hjälp isOutput=trueav , som i följande kod:

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

Variabler som skapats i ett steg som används i efterföljande stegvillkor

Du kan skapa en variabel som är tillgänglig för framtida steg att ange i ett villkor. Variabler som skapas från steg är tillgängliga för framtida steg som standard och behöver inte markeras som utdatavariabler för flera jobb.

Det finns några viktiga saker att tänka på omfångsvariabler som skapas från steg.

  • Variabler som skapas i ett steg i ett jobb begränsas till stegen i samma jobb.
  • Variabler som skapas i ett steg är endast tillgängliga i efterföljande steg som miljövariabler.
  • Variabler som skapas i ett steg kan inte användas i steget som definierar dem.

I följande exempel visas hur du skapar en pipelinevariabel i ett steg och använder variabeln i ett efterföljande stegs villkor och skript.

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

Vanliga frågor

Hur utlöser jag ett jobb om ett tidigare jobb avslutats med problem?

Du kan använda resultatet av det tidigare jobbet i ett villkor. I följande YAML tillåter villkoret eq(dependencies.A.result,'SucceededWithIssues') till exempel att jobbet B körs eftersom jobbet A lyckades med problem.

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

Jag avbröt min version, men den körs fortfarande. Varför?

Du kan uppleva det här problemet om ett villkor som konfigurerats i en fas inte innehåller någon funktion för jobbstatuskontroll. Lös problemet genom att lägga till en funktion för jobbstatuskontroll i villkoret.

Om du avbryter ett jobb medan det är i köfasen men inte körs avbryts hela jobbet, inklusive alla andra steg. Mer information finns i Villkorsresultat när en version avbryts tidigare i den här artikeln.