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 stage2
på stage1
, 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 true
returneras 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=true
av , 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.