Udostępnij za pośrednictwem


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.