Warunki potoku
Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019
W tym artykule opisano warunki, w których jest uruchamiany etap, zadanie lub krok usługi Azure Pipelines oraz sposób określania różnych warunków. Aby uzyskać więcej kontekstu na etapach, zadaniach i krokach, zobacz Kluczowe pojęcia dotyczące usługi Azure Pipelines.
Domyślnie zadanie lub etap jest uruchamiane, jeśli nie zależy od innego zadania lub etapu, lub jeśli wszystkie jego zależności zostały ukończone i zakończyły się pomyślnie. To wymaganie dotyczy nie tylko bezpośrednich zależności, ale także ich zależności pośrednich obliczanych rekursywnie.
Domyślnie krok jest uruchamiany, jeśli jeszcze nic nie powiodło się, a krok bezpośrednio poprzedzający jego ukończenie.
To zachowanie można zastąpić lub dostosować, wymuszając uruchomienie etapu, zadania lub kroku, nawet jeśli poprzednia zależność zakończy się niepowodzeniem lub przez określenie warunku niestandardowego.
Uwaga
W tym artykule omówiono możliwości potoku YAML. W przypadku potoków klasycznych można określić pewne warunki, w których zadania lub zadania są uruchamiane w obszarze Opcje sterowania każdego zadania, oraz w dodatkowych opcjach zadania w potoku wydania.
Warunki, w których jest uruchamiany etap, zadanie lub krok
W definicji potoku YAML można określić następujące warunki, w których jest uruchamiany etap, zadanie lub krok:
Tylko wtedy, gdy wszystkie poprzednie zależności bezpośrednie i pośrednie z tą samą pulą agentów kończą się powodzeniem. Jeśli masz różne pule agentów, te etapy lub zadania są uruchamiane współbieżnie. Ten warunek jest domyślny, jeśli w YAML nie ustawiono żadnego warunku.
Nawet jeśli poprzednia zależność nie powiedzie się, chyba że przebieg zostanie anulowany. Użyj
succeededOrFailed()
w pliku YAML dla tego warunku.Nawet jeśli poprzednia zależność nie powiedzie się, a nawet jeśli przebieg zostanie anulowany. Użyj
always()
w pliku YAML dla tego warunku.Tylko wtedy, gdy poprzednia zależność zakończy się niepowodzeniem. Użyj
failed()
w pliku YAML dla tego warunku.
- Warunki niestandardowe.
Domyślnie etapy, zadania i kroki są uruchamiane, jeśli wszystkie zależności bezpośrednie i pośrednie powiedzą się. Ten stan jest taki sam, jak w przypadku określania condition: succeeded()
wartości . Aby uzyskać więcej informacji, zobacz funkcja stanu powodzenia.
Po określeniu condition
właściwości etapu, zadania lub kroku zastąpisz wartość domyślną condition: succeeded()
. Określenie własnych warunków może spowodować uruchomienie etapu, zadania lub kroku, nawet jeśli kompilacja zostanie anulowana. Upewnij się, że zapisane warunki uwzględniają stan etapu nadrzędnego lub zadania.
Poniższy przykład YAML przedstawia always()
warunki i failed()
. Krok w pierwszym zadaniu jest uruchamiany, nawet jeśli zależności kończą się niepowodzeniem lub kompilacja zostanie anulowana. Drugie zadanie jest uruchamiane tylko wtedy, gdy pierwsze zadanie zakończy się niepowodzeniem.
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
Zmienne można również ustawiać i używać w warunkach. Poniższy przykład ustawia zmienną i używa zmiennej isMain
do wyznaczenia Build.SourceBranch
main
jako .
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)
Ważne
Warunki są oceniane w celu określenia, czy należy rozpocząć etap, zadanie lub krok. W związku z tym nic nie jest obliczane w czasie wykonywania w ramach tej jednostki pracy. Jeśli na przykład masz zadanie, które ustawia zmienną przy użyciu wyrażenia środowiska uruchomieniowego ze składnią $[ ]
, nie można użyć tej zmiennej w warunku niestandardowym w tym zadaniu.
Warunki niestandardowe
Jeśli wbudowane warunki nie spełniają Twoich potrzeb, możesz określić warunki niestandardowe. Warunki są zapisywane jako wyrażenia w definicjach potoku YAML.
Agent oblicza wyrażenie rozpoczynające się od najbardziej wewnętrznej funkcji i przechodząc na zewnątrz. Końcowy wynik jest wartością logiczną, która określa, czy zadanie, zadanie lub etap powinny być uruchamiane. Aby uzyskać pełny przewodnik po składni, zobacz Wyrażenia.
Jeśli którykolwiek z warunków umożliwia uruchomienie zadania nawet po anulowaniu kompilacji, określ rozsądną wartość limitu czasu anulowania, aby te zadania miały wystarczający czas do ukończenia po anulowaniu przebiegu przez użytkownika.
Wyniki warunku po anulowaniu kompilacji
Anulowanie kompilacji nie oznacza, że wszystkie jej etapy, zadania lub kroki przestaną działać. Etapy, zadania lub kroki przestają działać, zależą od określonych warunków i w jakim momencie wykonania potoku anulowano kompilację. Jeśli element nadrzędny etapu, zadania lub kroku zostanie pominięty, zadanie nie zostanie uruchomione, niezależnie od warunków.
Etap, zadanie lub krok jest uruchamiany za każdym razem, gdy jego warunki są obliczane na true
wartość . Jeśli warunek nie uwzględnia stanu nadrzędnego zadania, zadanie może zostać uruchomione nawet wtedy, gdy jego element nadrzędny zostanie anulowany. Aby kontrolować, czy etapy, zadania lub kroki z warunkami są uruchamiane po anulowaniu kompilacji, pamiętaj, aby uwzględnić funkcję sprawdzania stanu zadania w warunkach.
W poniższych przykładach przedstawiono wyniki różnych warunków ustawionych na etapach, zadaniach lub krokach po anulowaniu kompilacji.
Przykład etapu 1
W poniższym potoku domyślnie stage2
będzie zależeć od stage1
elementu , ale stage2
ma ustawioną condition
wartość do uruchomienia za każdym razem, gdy gałąź źródłowa ma main
wartość , niezależnie od stage1
stanu.
Jeśli kolejkujesz kompilację w main
gałęzi i anulujesz ją podczas stage1
działania, nadal jest uruchamiana, stage2
ponieważ eq(variables['Build.SourceBranch'], 'refs/heads/main')
daje wartość .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
Przykład etapu 2
W poniższym potoku stage2
domyślnie zależy stage1
od tego. Zadanie B
w programie stage2
ma condition
zestaw. Jeśli kolejkujesz kompilację w main
gałęzi i anulujesz ją podczas stage1
działania, nie zostanie uruchomiona, stage2
mimo że zawiera zadanie, którego warunek daje wartość true
.
Przyczyną jest to, że stage2
ma wartość domyślną condition: succeeded()
, która daje wartość w przypadku false
stage1
anulowania. stage2
W związku z tym nie jest pomijany, a żadne z jego zadań nie jest uruchamiane.
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
Przykład etapu 3
W poniższym potoku domyślnie stage2
zależy od stage1
elementu , a krok wewnątrz zadania B
ma condition
ustawiony zestaw.
Jeśli kolejkujesz kompilację na main
gałęzi i anulujesz ją podczas stage1
działania, nie zostanie uruchomiona, stage2
mimo że zawiera krok w zadaniu B
, którego warunek daje wartość true
. Przyczyną jest stage2
pominięcie w odpowiedzi na stage1
anulowanie.
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')
Przykład zadania 1
W poniższym potoku YAML zadanie B
zależy od zadania A
domyślnie, ale zadanie B
ma ustawioną condition
wartość do uruchomienia za każdym razem, gdy gałąź źródłowa ma wartość main
. Jeśli tworzysz kompilację w main
gałęzi i anulujesz ją podczas uruchamiania zadaniaA
, zadanie B
nadal jest uruchamiane, ponieważ eq(variables['Build.SourceBranch'], 'refs/heads/main')
daje wartość .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
Jeśli chcesz, aby zadanie B
było uruchamiane tylko wtedy, gdy zadanie A
zakończy się pomyślnie, a źródłem kompilacji jest main
gałąź , condition
powinna to być and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
.
Przykład zadania 2
W poniższym potoku zadanie B
jest domyślnie zależne od zadania A
. Jeśli kolejkujesz kompilację w main
gałęzi i anulujesz ją podczas uruchamiania zadaniaA
, zadanie B
nie zostanie uruchomionetrue
, mimo że jego krok ma condition
wartość .
Przyczyną jest to, że zadanie B
ma wartość domyślną condition: succeeded()
, która ocenia false
, kiedy zadanie A
jest anulowane. W związku z tym zadanie B
jest pomijane i żaden z jego kroków nie jest uruchamiany.
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())
Przykładowy krok
Możesz również mieć warunki dotyczące kroków.
W poniższym potoku krok 2.3 ma condition
zestaw do uruchomienia za każdym razem, gdy gałąź źródłowa to main
. Jeśli kolejkujesz kompilację w main
gałęzi i anulujesz ją podczas wykonywania kroków 2.1 lub 2.2, krok 2.3 nadal działa, ponieważ eq(variables['Build.SourceBranch'], 'refs/heads/main')
daje wartość .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')
Ustawienia warunku
W poniższej tabeli przedstawiono przykładowe condition
ustawienia umożliwiające uzyskanie różnych wyników.
Uwaga
Release.Artifacts.{artifact-alias}.SourceBranch
jest równoważne z Build.SourceBranch
.
Żądany wynik | Przykładowe ustawienie warunku |
---|---|
Uruchom polecenie , jeśli gałąź źródłowa jest główna, nawet jeśli element nadrzędny lub poprzedni etap, zadanie lub krok zakończył się niepowodzeniem lub został anulowany. | eq(variables['Build.SourceBranch'], 'refs/heads/main') |
Uruchom polecenie , jeśli gałąź źródłowa jest główna, a poprzedni etap, zadanie lub krok zakończył się pomyślnie. | and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) |
Uruchom polecenie , jeśli gałąź źródłowa nie jest główna, a poprzedni etap, zadanie lub krok zakończył się pomyślnie. | and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main')) |
Uruchom polecenie dla gałęzi tematu użytkownika, jeśli element nadrzędny lub poprzedni etap, zadanie lub krok zakończył się pomyślnie. | and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/')) |
Uruchom polecenie w celu utworzenia kompilacji ciągłej integracji, jeśli nadrzędny lub poprzedzający etap, zadanie lub krok zakończył się pomyślnie. | and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) |
Uruchom polecenie , jeśli kompilacja została wyzwolona przez zasady gałęzi dla żądania ściągnięcia, a element nadrzędny lub poprzedni etap, zadanie lub krok zakończył się niepowodzeniem. | and(failed(), eq(variables['Build.Reason'], 'PullRequest')) |
Uruchom dla zaplanowanej kompilacji, nawet jeśli element nadrzędny lub poprzedni etap, zadanie lub krok zakończył się niepowodzeniem lub został anulowany. | eq(variables['Build.Reason'], 'Schedule') |
Uruchom polecenie , jeśli zmienna jest ustawiona na wartość true, nawet jeśli element nadrzędny lub poprzedni etap, zadanie lub krok zakończył się niepowodzeniem lub został anulowany. | eq(variables['System.debug'], true) |
Uwaga
Można ustawić warunek do uruchomienia, jeśli zmienna ma wartość null (pusty ciąg). Ponieważ wszystkie zmienne są traktowane jako ciągi w usłudze Azure Pipelines, pusty ciąg jest odpowiednikiem null
następującego potoku:
variables:
- name: testEmpty
value: ''
jobs:
- job: A
steps:
- script: echo testEmpty is blank
condition: eq(variables.testEmpty, '')
Parametry w warunkach
Rozszerzanie parametrów odbywa się przed rozważemy warunki. W związku z tym po zadeklarowaniu parametru w tym samym potoku co warunek można osadzić parametr wewnątrz warunku. Skrypt w poniższym pliku YAML jest uruchamiany, ponieważ parameters.doThing
ma wartość true.
parameters:
- name: doThing
default: true
type: boolean
steps:
- script: echo I did a thing
condition: and(succeeded(), ${{ eq(parameters.doThing, true) }})
Element condition
w poprzednim potoku łączy dwie funkcje: succeeded()
i ${{ eq(parameters.doThing, true) }}
. Funkcja succeeded()
sprawdza, czy poprzedni krok zakończył się pomyślnie. Funkcja succeeded()
zwraca wartość true
, ponieważ nie było poprzedniego kroku.
Funkcja ${{ eq(parameters.doThing, true) }}
sprawdza, czy doThing
parametr jest równy true
. Ponieważ wartość domyślna parametru doThing
to true
, warunek jest zwracany true
domyślnie, chyba że potok ustawi inną wartość.
Parametry szablonu w warunkach
Po przekazaniu parametru do szablonu należy ustawić wartość parametru w szablonie lub użyć parametru TemplateContext, aby przekazać parametr do szablonu.
Na przykład następujący plik parameters.yml deklaruje parametr i wartość domyślną doThing
:
# 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) }}
Kod potoku odwołuje się do szablonu parameters.yml . Dane wyjściowe potoku są I did a thing
spowodowane tym, że parametr doThing
ma wartość true.
# azure-pipeline.yml
parameters:
- name: doThing
default: true
type: boolean
trigger:
- none
extends:
template: parameters.yml
Aby uzyskać więcej przykładów parametrów szablonu, zobacz dokumentację użycia szablonu.
Zmienne wyjściowe zadania używane w kolejnych warunkach zadania
Możesz udostępnić zmienną przyszłym zadaniu i określić ją w warunku. Zmienne dostępne dla przyszłych zadań muszą być oznaczone jako zmienne wyjściowe z wieloma zadaniami przy użyciu polecenia isOutput=true
, jak w poniższym kodzie:
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."
Zmienne utworzone w kroku używanym w kolejnych warunkach
Możesz utworzyć zmienną dostępną dla przyszłych kroków, która będzie określana w warunku. Zmienne utworzone na podstawie kroków są domyślnie dostępne dla przyszłych kroków i nie muszą być oznaczone jako zmienne wyjściowe z wieloma zadaniami.
Istnieje kilka ważnych kwestii, które należy wziąć pod uwagę podczas określania zakresu zmiennych utworzonych na podstawie kroków.
- Zmienne utworzone w kroku zadania są ograniczone do kroków w tym samym zadaniu.
- Zmienne utworzone w kroku są dostępne w kolejnych krokach tylko jako zmienne środowiskowe.
- Zmiennych utworzonych w kroku nie można używać w kroku, który je definiuje.
W poniższym przykładzie pokazano tworzenie zmiennej potoku w kroku i używanie zmiennej w warunku i skrypsie kolejnego kroku.
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'))
Często zadawane pytania
Jak mogę wyzwolić zadanie, jeśli poprzednie zadanie zakończyło się z błędami?
Możesz użyć wyniku poprzedniego zadania w warunku. Na przykład w poniższym języku YAML warunek eq(dependencies.A.result,'SucceededWithIssues')
umożliwia uruchomienie zadania B
, ponieważ zadanie A
zakończyło się pomyślnie.
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
Anulowano moją kompilację, ale nadal działa. Dlaczego?
Ten problem może wystąpić, jeśli warunek skonfigurowany na etapie nie zawiera funkcji sprawdzania stanu zadania. Aby rozwiązać ten problem, dodaj funkcję sprawdzania stanu zadania do warunku.
Jeśli anulujesz zadanie na etapie kolejki, ale nie zostanie uruchomione, całe zadanie zostanie anulowane, w tym wszystkie pozostałe etapy. Aby uzyskać więcej informacji, zobacz Wyniki warunku, gdy kompilacja zostanie anulowana wcześniej w tym artykule.