Pipelinebedingungen
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2019
In diesem Artikel werden die Bedingungen beschrieben, unter denen eine Azure Pipelines-Phase, ein Azure Pipelines-Auftrag oder ein Azure Pipelines-Schritt ausgeführt wird, und Sie erfahren, wie Sie unterschiedliche Bedingungen angeben. Mehr Kontext zu Phasen, Aufträgen und Schritten finden Sie unter Wichtige Konzepte für Azure Pipelines.
Standardmäßig werden Aufträge oder Phasen ausgeführt, wenn sie nicht von einem anderen Auftrag bzw. von einer anderen Phase abhängig sind oder wenn alle ihre Abhängigkeiten erfolgreich abgeschlossen wurden. Diese Anforderung gilt nicht nur für direkte Abhängigkeiten, sondern auch für ihre indirekten Abhängigkeiten, die rekursiv berechnet werden.
Schritte werden standardmäßig ausgeführt, wenn im zugehörigen Auftrag noch kein Fehler aufgetreten ist und der unmittelbar vorangehende Schritt abgeschlossen wurde.
Sie können dieses Verhalten außer Kraft setzen oder anpassen, indem Sie erzwingen, dass eine Phase, ein Auftrag oder ein Schritt auch bei einem Fehler einer vorherigen Abhängigkeit ausgeführt wird, oder indem Sie eine benutzerdefinierte Bedingung angeben.
Hinweis
In diesem Artikel werden YAML-Pipelinefunktionen erläutert. Bei klassischen Pipelines können Sie in den Steuerungsoptionen der jeweiligen Aufgabe einige Bedingungen angeben, unter denen die Aufgabe oder der Auftrag ausgeführt wird. Für einen Auftrag in einer Releasepipeline können Sie dafür Zusätzliche Optionen verwenden.
Bedingungen, unter denen eine Phase, ein Auftrag oder ein Schritt ausgeführt wird
Im YAML-Code der Pipelinedefinition können die folgenden Bedingungen angegeben werden, unter denen eine Phase, ein Auftrag oder ein Schritt ausgeführt wird:
Nur, wenn die Überprüfung aller vorherigen direkten und indirekten Abhängigkeiten mit demselben Agentenpool erfolgreich ist. Wenn Sie über verschiedene Agentenpools verfügen, werden diese Phasen oder Aufträge gleichzeitig ausgeführt. Diese Bedingung ist die Standardeinstellung, wenn in der YAML-Datei keine Bedingung festgelegt ist.
Auch wenn eine vorherige Abhängigkeit fehlschlägt ist, außer wenn die Ausführung abgebrochen wird. Verwenden Sie für diese Bedingung
succeededOrFailed()
in der YAML-Datei.Auch wenn eine vorherige Abhängigkeit fehlschlägt ist, auch wenn die Ausführung abgebrochen wird. Verwenden Sie für diese Bedingung
always()
in der YAML-Datei.Nur wenn eine vorherige Abhängigkeit fehlschlägt. Verwenden Sie für diese Bedingung
failed()
in der YAML-Datei.
- Benutzerdefinierte Bedingungen.
Standardmäßig werden Phasen, Aufträge und Schritte ausgeführt, wenn alle direkten und indirekten Abhängigkeiten erfolgreich sind. Dieser Status entspricht der Angabe von condition: succeeded()
. Weitere Informationen finden Sie unter der Statusfunktion succeeded.
Wenn Sie eine condition
-Eigenschaft für eine Phase, für einen Auftrag oder für einen Schritt angeben, wird dadurch die Standardeinstellung condition: succeeded()
überschrieben. Die Angabe eigenen Bedingungen kann dazu führen, dass Ihre Phase, Ihr Auftrag oder Ihr Schritt ausgeführt wird, auch wenn der Buildvorgang abgebrochen wird. Achten Sie darauf, dass die von Ihnen geschriebenen Bedingungen den Status der übergeordneten Phase bzw. des übergeordneten Auftrags berücksichtigen.
Das folgende YAML-Beispiel zeigt die Bedingungen always()
und failed()
. Der Schritt im ersten Auftrag wird auch ausgeführt, wenn Abhängigkeiten nicht erfolgreich waren oder der Buildvorgang abgebrochen wird. Der zweite Auftrag wird nur ausgeführt, wenn der erste Auftrag nicht erfolgreich war.
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
Sie können in Bedingungen auch Variablen festlegen und verwenden. Im folgenden Beispiel wird eine isMain
-Variable festgelegt und verwendet, um main
als Build.SourceBranch
festzulegen.
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)
Wichtig
Bedingungen werden ausgewertet, um zu bestimmen, ob eine Phase, ein Auftrag oder ein Schritt gestartet werden soll. Daher ist nichts von dem verfügbar, was zur Laufzeit innerhalb dieser Arbeitseinheit berechnet wird. Wenn Sie beispielsweise über einen Auftrag verfügen, der eine Variable unter Verwendung eines Laufzeitausdrucks mit $[ ]
-Syntax festlegt, können Sie diese Variable nicht in einer benutzerdefinierten Bedingung in diesem Auftrag verwenden.
Benutzerdefinierte Bedingungen
Sollten die integrierten Bedingungen Ihre Anforderungen nicht erfüllen, können Sie benutzerdefinierte Bedingungen definieren. Bedingungen werden als Ausdrücke in YAML-Pipelinedefinitionen geschrieben.
Der Agent wertet den Ausdruck aus. Dabei beginnt er mit der innersten Funktion. Das Endergebnis ist ein boolescher Wert, der bestimmt, ob die Aufgabe, der Auftrag oder die Phase ausgeführt werden soll. Eine vollständige Anleitung für die Syntax finden Sie unter Ausdrücke.
Wenn eine Ihrer Bedingungen die Ausführung der Aufgabe auch nach Abbruch des Buildvorgangs ermöglicht, geben Sie einen angemessenen Wert für das Abbruchtimeout an, damit nach dem benutzerseitigen Abbruch einer Ausführung genügend Zeit bleibt, um diese Aufgaben abzuschließen.
Bedingungsergebnisse, wenn ein Buildvorgang abgebrochen wird
Wenn ein Buildvorgang abgebrochen wird, bedeutet das nicht, dass die Ausführung aller zugehörigen Phasen, Aufträge oder Schritte beendet wird. Welche Phasen, Aufträge oder Schritte beendet werden, hängt von den angegebenen Bedingungen sowie davon ab, an welchem Punkt der Pipelineausführung der Buildvorgang abgebrochen wurde. Wenn das übergeordnete Element einer Phase, eines Auftrags oder eines Schritts übersprungen wird, wird die Aufgabe unabhängig von ihren Bedingungen nicht ausgeführt.
Eine Phase, ein Auftrag oder ein Schritt wird ausgeführt, wenn die Auswertung der zugehörigen Bedingungen true
ergibt. Wenn Ihre Bedingung den Status des übergeordneten Elements der Aufgabe nicht berücksichtigt, wird die Aufgabe unter Umständen auch dann ausgeführt, wenn das übergeordnete Element abgebrochen wird. Wenn Sie steuern möchten, ob Phasen, Aufträge oder Schritte mit Bedingungen ausgeführt werden, wenn ein Buildvorgang abgebrochen wird, müssen Sie eine Auftragsstatus-Überprüfungsfunktion in Ihre Bedingungen einschließen.
Die folgenden Beispiele zeigen die Ergebnisse verschiedener festgelegter Bedingungen für Phasen, Aufträge oder Schritte, wenn der Buildvorgang abgebrochen wird.
Phasenbeispiel 1
In der folgenden Pipeline hängt stage2
standardmäßig von stage1
ab. Für stage2
ist jedoch eine Bedingung (condition
) festgelegt, damit die Ausführung immer erfolgt, wenn der Quellbranch main
lautet – unabhängig vom Status von stage1
.
Wenn Sie einen Buildvorgang für den main
-Branch in die Warteschlange stellen und ihn während der Ausführung von stage1
abbrechen, wird stage2
trotzdem ausgeführt, da eq(variables['Build.SourceBranch'], 'refs/heads/main')
als true
ausgewertet wird.
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
Phasenbeispiel 2
In der folgenden Pipeline ist stage2
standardmäßig von stage1
abhängig. Für den Auftrag B
in stage2
ist eine Bedingung (condition
) festgelegt. Wenn Sie einen Buildvorgang für den main
-Branch in die Warteschlange stellen und ihn während der Ausführung von stage1
abbrechen, wird stage2
nicht ausgeführt, obwohl darin ein Auftrag enthalten ist, dessen Bedingung als true
ausgewertet wird.
Der Grund dafür ist, dass für stage2
der Standardwert condition: succeeded()
verwendet wird, der als beim Abbrechen von false
als stage1
ausgewertet wird. Daher wird stage2
übersprungen, und keiner der Aufträge wird ausgeführt.
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
Phasenbeispiel 3
In der folgenden Pipeline hängt stage2
standardmäßig von stage1
ab, und für den Schritt innerhalb des Auftrags B
ist eine Bedingung (condition
) festgelegt.
Wenn Sie einen Buildvorgang für den main
-Branch in die Warteschlange stellen und ihn während der Ausführung von stage1
abbrechen, wird stage2
nicht ausgeführt, obwohl ein Schritt im Auftrag B
enthalten ist, dessen Bedingung als true
ausgewertet wird. Der Grund liegt darin, dass stage2
als Reaktion auf den Abbruch von stage1
übersprungen wird.
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')
Auftragsbeispiel 1
In der folgenden YAML-Pipeline hängt der Auftrag B
standardmäßig vom Auftrag A
ab. Für den Auftrag B
ist jedoch eine Bedingung (condition
) festgelegt, damit er immer ausgeführt wird, wenn der Quellbranch main
lautet. Wenn Sie einen Buildvorgang für den main
-Branch in die Warteschlange stellen und ihn während der Ausführung des Auftrags A
abbrechen, wird der Auftrag B
trotzdem ausgeführt, da eq(variables['Build.SourceBranch'], 'refs/heads/main')
als true
ausgewertet wird.
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
Soll der Auftrag B
nur ausgeführt werden, wenn der Auftrag A
erfolgreich ist und es sich bei der Buildquelle um den main
-Branch handelt, muss Ihre Bedingung (condition
) wie folgt lauten: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
.
Auftragsbeispiel 2
In der folgenden Pipeline hängt der Auftrag B
standardmäßig vom Auftrag A
ab. Wenn Sie einen Buildvorgang für den main
-Branch in die Warteschlange stellen und ihn abbrechen, während der Auftrag A
ausgeführt wird, wird der Auftrag B
nicht ausgeführt, obwohl der zugehörige Schritt über eine Bedingung (condition
) verfügt, die als true
ausgewertet wird.
Der Grund dafür ist, dass für Auftrag B
der Standardwert condition: succeeded()
verwendet wird, der beim Abbrechen des Auftrags false
als A
ausgewertet wird. Daher wird der Auftrag B
übersprungen, und keiner der Schritte wird ausgeführt.
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())
Schrittbeispiel
Sie können auch Bedingungen für Schritte festlegen.
In der folgenden Pipeline ist für den Schritt 2.3 eine Bedingung (condition
) festgelegt, damit der Schritt ausgeführt wird, wenn der Quellbranch main
lautet. Wenn Sie einen Buildvorgang für den main
-Branch in die Warteschlange stellen und ihn abbrechen, während der Schritt 2.1 oder 2.2 ausgeführt wird, wird der Schritt 2.3 trotzdem ausgeführt, da eq(variables['Build.SourceBranch'], 'refs/heads/main')
als true
ausgewertet wird.
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')
Bedingungseinstellungen
Die folgende Tabelle enthält exemplarische Einstellungen für condition
, um verschiedene Ergebnisse zu erzielen.
Hinweis
Release.Artifacts.{artifact-alias}.SourceBranch
entspricht Build.SourceBranch
.
Gewünschtes Ergebnis | Exemplarische Bedingungseinstellung |
---|---|
Die Ausführung soll erfolgen, wenn der Quellbranch „main“ lautet, auch wenn die übergeordnete oder vorhergehende Phase, der übergeordnete oder vorhergehende Auftrag oder der übergeordnete oder vorhergehende Schritt nicht erfolgreich war oder abgebrochen wurde. | eq(variables['Build.SourceBranch'], 'refs/heads/main') |
Die Ausführung soll erfolgen, wenn der Quellbranch „main“ lautet und die übergeordnete oder vorhergehende Phase, der übergeordnete oder vorhergehende Auftrag oder der übergeordnete oder vorhergehende Schritt erfolgreich war. | and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) |
Die Ausführung soll erfolgen, wenn der Quellbranch nicht „main“ lautet und die übergeordnete oder vorhergehende Phase, der übergeordnete oder vorhergehende Auftrag oder der übergeordnete oder vorhergehende Schritt erfolgreich war. | and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main')) |
Die Ausführung soll für Benutzerthemabranches erfolgen, wenn die übergeordnete oder vorherige Phase, der übergeordnete oder vorherige Auftrag oder der übergeordnete oder vorherige Schritt erfolgreich war. | and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/')) |
Die Ausführung soll für CI-Builds (Continuous Integration) erfolgen, wenn die übergeordnete oder vorhergehende Phase, der übergeordnete oder vorhergehende Auftrag oder der übergeordnete oder vorhergehende Schritt erfolgreich war. | and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) |
Die Ausführung soll erfolgen, wenn der Buildvorgang durch eine Branchrichtlinie für einen Pull Request ausgelöst wurde und die übergeordnete oder vorhergehende Phase, der übergeordnete oder vorhergehende Auftrag oder der übergeordnete oder vorhergehende Schritt nicht erfolgreich war. | and(failed(), eq(variables['Build.Reason'], 'PullRequest')) |
Die Ausführung soll für einen geplanten Buildvorgang erfolgen, auch wenn die übergeordnete oder vorhergehende Phase, der übergeordnete oder vorhergehende Auftrag oder der übergeordnete oder vorhergehende Schritt nicht erfolgreich war oder abgebrochen wurde. | eq(variables['Build.Reason'], 'Schedule') |
Die Ausführung soll erfolgen, wenn eine Variable auf „true“ festgelegt ist, auch wenn die übergeordnete oder vorhergehende Phase, der übergeordnete oder vorhergehende Auftrag oder der übergeordnete oder vorhergehende Schritt nicht erfolgreich war oder abgebrochen wurde. | eq(variables['System.debug'], true) |
Hinweis
Sie können eine Bedingung festlegen, die dafür sorgt, dass die Ausführung erfolgt, wenn eine Variable NULL ist (leere Zeichenfolge). Da alle Variablen in Azure Pipelines als Zeichenfolgen behandelt werden, entspricht eine leere Zeichenfolge null
in der folgenden Pipeline:
variables:
- name: testEmpty
value: ''
jobs:
- job: A
steps:
- script: echo testEmpty is blank
condition: eq(variables.testEmpty, '')
Parameter in Bedingungen
Die Parametererweiterung erfolgt, bevor Bedingungen berücksichtigt werden. Wenn Sie also einen Parameter in der gleichen Pipeline deklarieren wie eine Bedingung, können Sie den Parameter in die Bedingung einbetten. Das Skript in der folgenden YAML-Datei wird ausgeführt, weil parameters.doThing
„true“ ist:
parameters:
- name: doThing
default: true
type: boolean
steps:
- script: echo I did a thing
condition: and(succeeded(), ${{ eq(parameters.doThing, true) }})
Die Bedingung (condition
) in der obigen Pipeline kombiniert zwei Funktionen: succeeded()
und ${{ eq(parameters.doThing, true) }}
. Die Funktion succeeded()
überprüft, ob der vorherige Schritt erfolgreich war. Die Funktion succeeded()
gibt true
zurück, weil es keinen vorherigen Schritt gab.
Die Funktion ${{ eq(parameters.doThing, true) }}
überprüft, ob der doThing
-Parameter gleich true
ist. Da doThing
den Standardwert true
hat, gibt die Bedingung standardmäßig true
zurück – es sei denn, die Pipeline legt einen anderen Wert fest.
Vorlagenparameter in Bedingungen
Wenn Sie einen Parameter an eine Vorlage übergeben, müssen Sie entweder den Wert des Parameters in Ihrer Vorlage festlegen oder templateContext verwenden, um den Parameter an die Vorlage zu übergeben.
Die folgende Datei parameters.yml deklariert beispielsweise den doThing
-Parameter und den Standardwert:
# 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) }}
Der Pipelinecode verweist auf die Vorlage parameters.yml. Die Ausgabe der Pipeline ist I did a thing
, weil der Parameter doThing
„true“ ist.
# azure-pipeline.yml
parameters:
- name: doThing
default: true
type: boolean
trigger:
- none
extends:
template: parameters.yml
Weitere Vorlagenparameterbeispiele finden Sie in der Referenz zur Vorlageverwendung.
In nachfolgenden Auftragsbedingungen verwendete Auftragsausgabevariablen
Sie können eine Variable für zukünftige Aufträge zur Verfügung stellen und sie in einer Bedingung angeben. Für zukünftige Aufträge verfügbare Variablen müssen mithilfe von isOutput=true
als Ausgabevariablen für mehrere Aufträge gekennzeichnet werden, wie im folgenden Code zu sehen:
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."
In einem Schritt erstellte Variablen, die in nachfolgenden Schrittbedingungen verwendet werden
Sie können eine Variable erstellen, die für zukünftige Schritte verfügbar sind, um sie in einer Bedingung anzugeben. Auf der Grundlage von Schritten erstellte Variablen sind standardmäßig für zukünftige Schritte verfügbar und müssen nicht als Ausgabevariablen für mehrere Aufträge gekennzeichnet werden.
Bei der Bereichsdefinition von Variablen, die auf der Grundlage von Schritten erstellt werden, müssen einige wichtige Punkte berücksichtigt werden.
- Der Bereich von Variablen, die in einem Schritt eines Auftrags erstellt werden, wird auf die Schritte im gleichen Auftrag festgelegt.
- In einem Schritt erstellte Variablen sind in nachfolgenden Schritten nur als Umgebungsvariablen verfügbar.
- In einem Schritt erstellte Variablen können nicht in dem Schritt verwendet werden, der sie definiert.
Das folgende Beispiel zeigt die Erstellung einer Pipelinevariablen in einem Schritt und die Verwendung der Variablen in der Bedingung und dem Skript eines nachfolgenden Schritts:
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'))
Häufig gestellte Fragen
Wie kann ich einen Auftrag auslösen, wenn ein vorheriger Auftrag mit Problemen erfolgreich war?
Sie können das Ergebnis des vorherigen Auftrags in einer Bedingung verwenden. Im folgenden YAML-Code ermöglicht beispielsweise die Bedingung eq(dependencies.A.result,'SucceededWithIssues')
die Ausführung des Auftrags B
, da der Auftrag A
mit Problemen abgeschlossen wurde:
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
Ich habe meinen Build abgebrochen, aber er wird weiterhin ausgeführt. Warum?
Dieses Problem kann auftreten, wenn eine in einer Phase konfigurierte Bedingung keine Auftragsstatus-Überprüfungsfunktion enthält. Um das Problem zu beheben, fügen Sie der Bedingung eine Auftragsstatus-Überprüfungsfunktion hinzu.
Wenn Sie einen Auftrag abbrechen, der sich in der Warteschlangenphase befindet und noch nicht ausgeführt wird, wird der gesamte Auftrag abgebrochen, einschließlich aller anderen Phasen. Weitere Informationen finden Sie weiter oben in diesem Artikel unter Bedingungsergebnisse, wenn ein Buildvorgang abgebrochen wird.