Warunki rurociągu
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 dotyczącego etapów, zadań i kroków, 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 z powodzeniem. 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 w jego zadaniu jeszcze nic nie nie powiodło i krok bezpośrednio go poprzedzający został ukończony.
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
Artykuł omawia 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 uruchamiania etapu, zadania lub kroku
W definicji procesu YAML można określić warunki, na podstawie których uruchamiany jest 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 uruchomienie zostanie anulowane. 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 powiodą się. Ten stan jest taki sam, jak w przypadku określania condition: succeeded()
. Aby uzyskać więcej informacji, zobacz funkcja stanu pomyślnego.
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 warunki, które piszesz, uwzględniają stan etapu rodzicielskiego lub zadania.
Poniższy przykład YAML pokazuje warunki always()
i failed()
. Krok w pierwszym zadaniu jest uruchamiany, nawet jeśli zależności kończą się niepowodzeniem lub kompilacja zostanie anulowana. W drugim zadaniu skryptu exit 1
wymusza niepowodzenie zadania Foo
. 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
- script: |
echo "This task will fail."
exit 1
- 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 i używa zmienną isMain
do wyznaczenia main
jako 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)
Ważne
Warunki są oceniane w celu określenia, czy należy rozpocząć etap, zadanie lub krok. W związku z tym nic, co jest obliczane w czasie wykonywania w ramach tej jednostki pracy, nie jest dostępne. 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 zapisuj jako wyrażenia w definicjach potoku YAML.
Agent oblicza wyrażenie, zaczynając od najbardziej wewnętrznej funkcji i kontynuując na zewnątrz. Końcowy wynik jest wartością logiczną, która określa, czy zadanie lub etap powinny być wykonywane. 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ść czasu anulowania, aby te zadania miały wystarczający czas na ukończenie po anulowaniu uruchomienia 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ć, są zależne od warunków, które określiłeś, oraz momentu, w którym anulowałeś kompilację podczas realizacji potoku. 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 uruchamia się za każdym razem, gdy jego warunki są oceniane na true
. Jeśli warunek nie uwzględnia stanu zadania nadrzędnego, zadanie może zostać uruchomione nawet wtedy, gdy jego zadanie nadrzędne zostanie anulowane. 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 przepływie operacji domyślnie stage2
będzie zależne od stage1
, ale stage2
ma ustawioną wartość condition
, aby uruchomić się za każdym razem, gdy gałąź źródłowa jest main
, niezależnie od stanu stage1
.
Jeśli kolejkujesz kompilację w main
gałęzi i anulujesz ją podczas działania stage1
, stage2
nadal jest uruchamiane, ponieważ eq(variables['Build.SourceBranch'], 'refs/heads/main')
ocenia się do 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 od stage1
. Zadanie B
w stage2
ma condition
ustawienie. Jeśli kolejkujesz kompilację w gałęzi main
i anulujesz ją, gdy stage1
jest w trakcie działania, stage2
nie zostanie uruchomione, nawet jeśli zawiera zadanie, którego warunek daje wartość true
.
Jest tak, ponieważ stage2
ma domyślną wartość condition: succeeded()
, co skutkuje false
przy anulowaniu stage1
.
stage2
, w związku z tym, 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
, a krok wewnątrz zadania B
ma ustawioną wartość condition
.
Jeśli kolejkujesz kompilację na gałęzi main
i anulujesz ją podczas działania stage1
, stage2
nie zostanie uruchomiona, nawet jeśli zawiera krok w zadaniu B
, którego warunek ocenia się na true
. Przyczyną jest pominięcie stage2
w odpowiedzi na anulowanie stage1
.
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 ustawisz w kolejce kompilację na gałęzi main
i anulujesz ją podczas uruchamiania zadania A
, zadanie B
nadal będzie uruchamiane, ponieważ eq(variables['Build.SourceBranch'], 'refs/heads/main')
ocenia się na 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 gałęzią źródłową kompilacji jest main
, twój condition
powinien być and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
.
Przykład zadania 2
W poniższym ciągu technologicznym zadanie B
domyślnie zależy od zadania A
. Jeśli kolejkujesz kompilację w gałęzi main
i anulujesz ją podczas uruchamiania zadania A
, zadanie B
nie zostanie uruchomione, mimo że jego krok ma wartość true
.
Przyczyną jest to, że zadanie B
uzyskuje wartość false
, gdy zadanie A
zostaje anulowane. W związku z tym zadanie B
jest pomijane i jego kroki nie są wykonywane.
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())
Przykładowy krok
Możesz również mieć warunki dotyczące kroków.
W poniższej ścieżce krok 2.3 jest ustawiony do uruchamiania 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, jeśli gałąź źródłowa to main, nawet jeśli etap 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, jeśli gałąź źródłowa nie jest główną, a poprzedzający etap, zadanie lub krok zakończył się sukcesem. | and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main')) |
Uruchom dla gałęzi 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 kompilacje 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, jeśli kompilacja została wyzwolona przez zasady gałęzi dla pull request, a nadrzędny lub poprzedni etap, zadanie lub krok zakończył się niepowodzeniem. | and(failed(), eq(variables['Build.Reason'], 'PullRequest')) |
Uruchom kompilację zaplanowaną, 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, jeśli zmienna jest ustawiona na wartość true, nawet jeśli etap 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 znaków w usłudze Azure Pipelines, pusty ciąg znaków jest równoważny null
w poniższym 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żeniem warunków. 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 danych łą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 dla doThing
to true
, zwracana wartość to domyślnie true
, chyba że rura strumieniowa 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 pipeline 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 wynikowe dla wielu zadań przy użyciu 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, które są używane w warunkach kolejnych kroków.
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 skrypcie 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ę sukcesem mimo problemów?
Możesz użyć wyniku poprzedniego zadania w warunku. Na przykład w poniższym YAML warunek eq(dependencies.A.result,'SucceededWithIssues')
umożliwia uruchomienie zadania B
po zakończeniu zadania A
, które kończy się pomyślnie mimo problemów.
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, gdy znajduje się w etapie kolejkowania, ale jeszcze nie działa, całe zadanie zostanie anulowane, łącznie ze wszystkimi innymi etapami. Aby uzyskać więcej informacji, zobacz Wyniki warunku, gdy kompilacja zostanie anulowana wcześniej w tym artykule.