Bagikan melalui


Kondisi jalur

Layanan Azure DevOps | Azure DevOps Server 2022 - Azure DevOps Server 2019

Artikel ini menjelaskan kondisi di mana tahap, pekerjaan, atau langkah Azure Pipelines berjalan, dan cara menentukan kondisi yang berbeda. Untuk konteks selengkapnya tentang tahapan, pekerjaan, dan langkah-langkah, lihat Konsep utama untuk Azure Pipelines.

  • Secara default, pekerjaan atau tahap berjalan jika tidak bergantung pada pekerjaan atau tahap lain, atau jika semua dependensinya selesai dan berhasil. Persyaratan ini tidak hanya berlaku untuk dependensi langsung, tetapi untuk dependensi tidak langsung mereka, dihitung secara rekursif.

  • Secara default, sebuah langkah akan berjalan jika tidak ada kesalahan dalam pekerjaannya dan langkah sebelumnya telah selesai.

Anda dapat mengambil alih atau menyesuaikan perilaku ini dengan memaksa tahap, pekerjaan, atau langkah untuk dijalankan meskipun dependensi sebelumnya gagal, atau dengan menentukan kondisi kustom.

Catatan

Artikel ini membahas kemampuan alur YAML. Untuk alur kerja Klasik, Anda dapat menentukan beberapa kondisi di mana tugas atau pekerjaan dijalankan di Opsi Kontrol setiap tugas, dan di Opsi Tambahan untuk pekerjaan dalam alur rilis.

Kondisi di mana tahap, pekerjaan, atau langkah dijalankan

Dalam YAML definisi pipeline, Anda dapat menentukan kondisi-kondisi berikut untuk menjalankan tahap, job, atau langkah:

  • Hanya ketika semua dependensi sebelumnya, baik langsung maupun tidak langsung, dengan kumpulan agen yang sama berhasil. Jika Anda memiliki kumpulan agen yang berbeda, tahap atau pekerjaan tersebut berjalan bersamaan. Kondisi ini adalah default jika tidak ada kondisi yang diatur dalam YAML.

  • Bahkan jika dependensi sebelumnya gagal, kecuali jika eksekusi dibatalkan. Gunakan succeededOrFailed() dalam YAML untuk kondisi ini.

  • Bahkan jika dependensi sebelumnya gagal, dan bahkan jika eksekusi dibatalkan. Gunakan always() dalam YAML untuk kondisi ini.

  • Hanya ketika dependensi sebelumnya gagal. Gunakan failed() dalam YAML untuk kondisi ini.

  • Kondisi kustom.

Secara default, tahapan, pekerjaan, dan langkah-langkah berjalan jika semua dependensi langsung dan tidak langsung berhasil. Status ini sama dengan menentukan condition: succeeded(). Untuk informasi selengkapnya, lihat fungsi status berhasil.

Saat Anda menentukan properti condition untuk tahap, pekerjaan, atau langkah, Anda mengganti default condition: succeeded(). Menentukan kondisi Anda sendiri bisa membuat tahap, pekerjaan, atau langkah Anda tetap berjalan walaupun build dibatalkan. Pastikan kondisi yang Anda tulis memperhitungkan kondisi tahap atau pekerjaan induk.

Contoh YAML berikut menunjukkan kondisi always() dan failed() . Langkah dalam pekerjaan pertama tetap berjalan meskipun dependensi gagal atau build dibatalkan. Dalam tugas skrip kedua, exit 1 memaksa pekerjaan Foo menjadi gagal. Tugas kedua hanya berjalan jika tugas pertama gagal.

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

Anda juga dapat mengatur dan menggunakan variabel dalam kondisi. Contoh berikut menetapkan dan menggunakan variabel isMain untuk menunjuk main sebagai 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)

Penting

Kondisi dievaluasi untuk menentukan apakah akan memulai tahap, pekerjaan, atau langkah. Oleh karena itu, tidak ada yang dihitung pada runtime di dalam unit kerja tersebut yang tersedia. Misalnya, jika Anda memiliki pekerjaan yang mengatur variabel menggunakan ekspresi runtime dengan sintaksis $[ ], Anda tidak dapat menggunakan variabel tersebut dalam kondisi kustom pada pekerjaan yang sama.

Kondisi kustom

Jika kondisi bawaan tidak memenuhi kebutuhan Anda, Anda dapat menentukan kondisi kustom. Anda menulis kondisi sebagai ekspresi dalam definisi alur YAML.

Agen mengevaluasi ekspresi yang dimulai dengan fungsi paling dalam dan melanjutkan ke arah luar. Hasil akhir adalah nilai boolean yang menentukan apakah tugas, pekerjaan, atau tahap harus berjalan atau tidak. Untuk panduan lengkap untuk sintaks, lihat Ekspresi.

Jika salah satu kondisi Anda memungkinkan tugas berjalan bahkan setelah build dibatalkan, tentukan nilai yang wajar untuk waktu habis pembatalan sehingga tugas ini memiliki cukup waktu untuk diselesaikan setelah pengguna membatalkan eksekusi.

Hasil kondisi ketika pembangunan dibatalkan

Membatalkan build tidak berarti bahwa semua tahapan, tugas, atau langkah-langkahnya berhenti. Tahap, pekerjaan, atau langkah mana yang berhenti tergantung pada kondisi yang Anda tentukan, dan pada titik jalannya alur kerja di mana Anda membatalkan build. Jika tahap, pekerjaan, atau induk langkah dilewati, tugas tidak berjalan, terlepas dari kondisinya.

Tahap, pekerjaan, atau langkah berjalan setiap kali kondisinya bernilai true. Jika kondisi tersebut tidak memperhitungkan status induk tugas, tugas tersebut mungkin tetap berjalan meskipun induknya dibatalkan. Untuk mengontrol apakah tahap, pekerjaan, atau langkah dengan kondisi akan dijalankan ketika build dibatalkan, pastikan untuk menyertakan fungsi pemeriksaan status pekerjaan dalam kondisi Anda.

Contoh-contoh berikut menunjukkan hasil dari berbagai kondisi yang ditetapkan pada tahap-tahap, tugas, atau langkah-langkah saat pembangunan dibatalkan.

Contoh tahap 1

Dalam alur berikut, secara default stage2 akan bergantung pada stage1, tetapi stage2 memiliki set condition untuk dijalankan setiap kali cabang sumber adalah main, terlepas dari stage1 statusnya.

Jika Anda mengantre build pada cabang main dan membatalkannya saat stage1 sedang berjalan, stage2 tetap berjalan, karena eq(variables['Build.SourceBranch'], 'refs/heads/main') dievaluasi menjadi 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

Contoh tahap 2

Dalam pipeline berikut, stage2 secara default bergantung pada stage1. Pekerjaan B dalam stage2 memiliki condition set. Jika Anda mengantrikan build di cabang main dan membatalkannya ketika stage1 sedang berjalan, maka stage2 tidak berjalan, meskipun terdapat pekerjaan yang kondisinya dievaluasi menjadi true.

Alasannya adalah karena stage2 mempunyai default condition: succeeded(), yang mengevaluasi menjadi false ketika stage1 dibatalkan. Oleh karena itu, stage2 dilewati, dan tidak ada pekerjaannya yang dijalankan.

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

Contoh tahap 3

Dalam alur berikut, secara default stage2 bergantung pada stage1, dan langkah di dalam pekerjaan B telah diatur condition.

Jika Anda mengantrekan build di cabang main dan membatalkannya saat stage1 sedang berjalan, stage2 tidak berjalan, meskipun berisi langkah dalam pekerjaan B yang memiliki kondisi true. Alasannya karena stage2 dilewati sebagai respons terhadap stage1 dibatalkan.

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')

Contoh pekerjaan 1

Dalam alur YAML berikut, pekerjaan B tergantung pada pekerjaan A secara default, tetapi pekerjaan B memiliki set condition untuk dijalankan setiap kali cabang sumber adalah main. Jika Anda mengantre build di main cabang dan membatalkannya saat tugas A berjalan, tugas B masih berjalan, karena eq(variables['Build.SourceBranch'], 'refs/heads/main') dievaluasi menjadi 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

Jika Anda ingin pekerjaan B hanya dijalankan ketika pekerjaan A berhasil dan sumber build adalah cabang main, maka condition Anda harus and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')).

Contoh pekerjaan 2

Dalam alur berikut, pekerjaan B bergantung pada pekerjaan A secara default. Jika Anda mengantrekan build pada cabang main dan membatalkannya saat pekerjaan A sedang proses, pekerjaan B tidak dilanjutkan, meskipun langkahnya memiliki condition yang dievaluasi menjadi true.

Alasannya adalah pekerjaan B menjadi false ketika pekerjaan A dibatalkan. Oleh karena itu, pekerjaan B diabaikan, dan tidak ada langkah-langkah yang dijalankan.

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())

Contoh langkah

Anda juga dapat memiliki kondisi pada langkah-langkah.

Dalam alur berikut, langkah 2.3 memiliki set condition untuk dijalankan setiap kali cabang sumber adalah main. Jika Anda memulai build pada branch main dan membatalkannya saat langkah 2.1 atau 2.2 berjalan, langkah 2.3 masih berjalan, karena eq(variables['Build.SourceBranch'], 'refs/heads/main') dievaluasi menjadi 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')

Pengaturan kondisi

Tabel berikut ini memperlihatkan contoh condition pengaturan untuk menghasilkan berbagai hasil.

Catatan

Release.Artifacts.{artifact-alias}.SourceBranch setara dengan Build.SourceBranch.

Hasil yang diinginkan Contoh pengaturan kondisi
Jalankan jika cabang sumber adalah 'main', bahkan jika tahap induk atau sebelumnya, pekerjaan, atau langkah telah gagal atau dibatalkan. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Jalankan apabila cabang sumber adalah 'main' dan tahap induk, tahap sebelumnya, pekerjaan, atau langkah berhasil. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Jalankan jika cabang sumber bukan 'main', dan tahap induk, pekerjaan, atau langkah sebelumnya berhasil. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Jalankan proses untuk cabang topik pengguna, jika tahap induk atau tahap sebelumnya, pekerjaan, atau langkah berhasil. and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
Jalankan untuk build integrasi kontinu (CI), jika tahap induk, pekerjaan, atau langkah sebelumnya berhasil. and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
Jalankan jika build dipicu oleh kebijakan cabang untuk permintaan pull, dan tahap induk atau sebelumnya, pekerjaan, atau langkah gagal. and(failed(), eq(variables['Build.Reason'], 'PullRequest'))
Jalankan build yang dijadwalkan, bahkan jika tahap induk atau tahap sebelumnya, pekerjaan, atau langkah gagal atau dibatalkan. eq(variables['Build.Reason'], 'Schedule')
Jalankan jika variabel diatur ke true, bahkan jika tahap induk atau sebelumnya, pekerjaan, atau langkah gagal atau dibatalkan. eq(variables['System.debug'], true)

Catatan

Anda dapat mengatur kondisi untuk dijalankan jika variabel null (string kosong). Karena semua variabel diperlakukan sebagai string di Azure Pipelines, string kosong setara dengan null dalam alur berikut:

variables:
- name: testEmpty
  value: ''

jobs:
  - job: A
    steps:
    - script: echo testEmpty is blank
    condition: eq(variables.testEmpty, '')

Parameter dalam kondisi

Ekspansi parameter terjadi sebelum kondisi dipertimbangkan. Oleh karena itu, ketika Anda mendeklarasikan parameter dalam alur yang sama dengan kondisi, Anda dapat menyematkan parameter di dalam kondisi. Skrip dalam YAML berikut berjalan karena parameters.doThing benar.

parameters:
- name: doThing
  default: true
  type: boolean

steps:
- script: echo I did a thing
  condition: and(succeeded(), ${{ eq(parameters.doThing, true) }})

condition dalam alur sebelumnya menggabungkan dua fungsi: succeeded() dan ${{ eq(parameters.doThing, true) }}. Fungsi succeeded() memeriksa apakah langkah sebelumnya berhasil. Fungsi succeeded() mengembalikan true karena tidak ada langkah sebelumnya.

Fungsi ${{ eq(parameters.doThing, true) }} memeriksa apakah doThing parameter sama dengan true. Karena nilai default untuk doThing adalah true, kondisi akan mengembalikan true secara default kecuali pipa menetapkan nilai yang berbeda.

Parameter templat dalam kondisi

Saat meneruskan parameter ke templat, Anda perlu mengatur nilai parameter di templat Anda atau menggunakan templateContext untuk meneruskan parameter ke templat.

Misalnya, file parameters.yml berikut mendeklarasikan doThing parameter dan nilai default:

# 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) }}

Kode alur mereferensikan templat parameters.yml . Output pipeline adalah I did a thing karena parameter doThing adalah benar.

# azure-pipeline.yml
parameters:
- name: doThing
  default: true 
  type: boolean

trigger:
- none

extends:
  template: parameters.yml

Untuk contoh parameter templat lainnya, lihat Referensi penggunaan templat.

Variabel output pekerjaan yang digunakan dalam kondisi pekerjaan berikutnya

Anda dapat membuat variabel tersedia untuk pekerjaan di masa mendatang dan menetapkannya dalam sebuah kondisi. Variabel yang tersedia untuk pekerjaan di masa mendatang harus ditandai sebagai variabel output multi-pekerjaan dengan menggunakan isOutput=true, seperti dalam kode berikut:

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."

Variabel yang dibuat dalam langkah yang digunakan dalam kondisi langkah berikutnya

Anda dapat membuat variabel yang tersedia untuk langkah-langkah selanjutnya dan dapat ditetapkan dalam kondisi tertentu. Variabel yang dibuat dari langkah-langkah tersedia secara default untuk langkah-langkah berikutnya dan tidak perlu ditandai sebagai variabel keluaran untuk beberapa pekerjaan.

Ada beberapa hal penting yang perlu diperhatikan mengenai cakupan variabel yang dihasilkan dari langkah-langkah.

  • Variabel yang dibuat dalam suatu langkah dalam pekerjaan terbatas pada langkah-langkah dalam pekerjaan yang sama.
  • Variabel yang dibuat dalam langkah tersedia dalam langkah berikutnya hanya sebagai variabel lingkungan.
  • Variabel yang dibuat dalam langkah tidak dapat digunakan dalam langkah yang menentukannya.

Contoh berikut menunjukkan pembuatan variabel alur dalam langkah dan menggunakan variabel dalam kondisi dan skrip langkah berikutnya.

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'))

FAQ

Bagaimana cara memicu pekerjaan jika pekerjaan sebelumnya berhasil dengan masalah?

Anda dapat menggunakan hasil pekerjaan sebelumnya dalam kondisi tertentu. Misalnya, dalam YAML berikut, kondisi eq(dependencies.A.result,'SucceededWithIssues') memungkinkan pekerjaan B berjalan setelah pekerjaan A berhasil meskipun ada masalah.

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

Saya sudah membatalkan build saya, tetapi masih tetap berjalan. Mengapa?

Anda dapat mengalami masalah ini jika kondisi yang dikonfigurasikan dalam tahap tidak menyertakan fungsi pengecekan status pekerjaan. Untuk mengatasi masalah ini, tambahkan fungsi pemeriksaan status pekerjaan ke kondisi tersebut.

Jika Anda membatalkan pekerjaan saat berada dalam tahap antrean namun tidak sedang berjalan, pekerjaan tersebut dibatalkan total, termasuk semua tahap lainnya. Untuk informasi selengkapnya, lihat Hasil kondisi saat build dibatalkan sebelumnya di artikel ini.