Bagikan melalui


Kondisi alur

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, langkah berjalan jika tidak ada dalam pekerjaannya yang gagal dan langkah segera mendahuluinya 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 Klasik, Anda dapat menentukan beberapa kondisi di mana tugas atau pekerjaan berjalan di Opsi Kontrol setiap tugas, dan di opsi Tambahan untuk pekerjaan dalam alur rilis.

Kondisi di mana tahap, pekerjaan, atau langkah berjalan

Dalam YAML definisi alur, Anda dapat menentukan kondisi berikut di mana tahap, pekerjaan, atau langkah berjalan:

  • Hanya ketika semua dependensi langsung dan tidak langsung sebelumnya 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 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 yang berhasil.

Saat Anda menentukan condition properti untuk tahap, pekerjaan, atau langkah, Anda menimpa default condition: succeeded(). Menentukan kondisi Anda sendiri dapat menyebabkan tahap, pekerjaan, atau langkah Anda berjalan meskipun build dibatalkan. Pastikan kondisi yang Anda tulis memperhitungkan status tahap atau pekerjaan induk.

Contoh YAML berikut menunjukkan kondisi always() dan failed() . Langkah dalam pekerjaan pertama berjalan bahkan jika dependensi gagal atau build dibatalkan. Pekerjaan kedua hanya berjalan jika pekerjaan pertama gagal.

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

Anda juga dapat mengatur dan menggunakan variabel dalam kondisi. Contoh berikut menetapkan dan menggunakan isMain variabel untuk ditunjuk 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 $[ ] sintaks, Anda tidak dapat menggunakan variabel tersebut dalam kondisi kustom dalam pekerjaan tersebut.

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

Kondisi hasil saat build dibatalkan

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

Tahap, pekerjaan, atau langkah berjalan setiap kali kondisinya mengevaluasi ke true. Jika kondisi Anda tidak memperhitungkan status induk tugas, tugas mungkin berjalan meskipun induknya dibatalkan. Untuk mengontrol apakah tahapan, pekerjaan, atau langkah-langkah dengan kondisi berjalan saat build dibatalkan, pastikan untuk menyertakan fungsi pemeriksaan status pekerjaan dalam kondisi Anda.

Contoh berikut menunjukkan hasil berbagai kondisi yang ditetapkan pada tahapan, pekerjaan, atau langkah-langkah saat build 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 di main cabang dan membatalkannya saat stage1 sedang berjalan, stage2 masih berjalan, karena eq(variables['Build.SourceBranch'], 'refs/heads/main') mengevaluasi ke 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 alur berikut, stage2 bergantung secara stage1 default. Pekerjaan B dalam stage2 memiliki satu condition set. Jika Anda mengantre build di main cabang dan membatalkannya saat stage1 sedang berjalan, stage2 tidak berjalan, meskipun berisi pekerjaan yang kondisinya dievaluasi ke true.

Alasannya adalah karena stage2 memiliki default condition: succeeded(), yang mengevaluasi kapan false stage1 dibatalkan. Oleh karena itu, stage2 dilewati, dan tidak ada pekerjaannya yang berjalan.

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 memiliki satu condition set.

Jika Anda mengantrekan build di main cabang dan membatalkannya saat stage1 sedang berjalan, stage2 tidak berjalan, meskipun berisi langkah dalam pekerjaan B yang kondisinya dievaluasi ke true. Alasannya adalah karena stage2 dilewati sebagai respons untuk 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 pekerjaan A berjalan, pekerjaan B masih berjalan, karena eq(variables['Build.SourceBranch'], 'refs/heads/main') mengevaluasi ke 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 berjalan ketika pekerjaan A berhasil dan sumber build adalah main cabang, Anda condition 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 di main cabang dan membatalkannya saat pekerjaan A berjalan, pekerjaan B tidak berjalan, meskipun langkahnya memiliki condition yang mengevaluasi ke true.

Alasannya adalah karena pekerjaan B memiliki default condition: succeeded(), yang mengevaluasi kapan false pekerjaan A dibatalkan. Oleh karena itu, pekerjaan B dilewati, dan tidak ada langkah-langkahnya yang dijalankan.

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

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 mengantre build di main cabang dan membatalkannya saat langkah 2.1 atau 2.2 berjalan, langkah 2.3 masih berjalan, karena eq(variables['Build.SourceBranch'], 'refs/heads/main') mengevaluasi ke 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 utama, bahkan jika tahap induk atau sebelumnya, pekerjaan, atau langkah gagal atau dibatalkan. eq(variables['Build.SourceBranch'], 'refs/heads/main')
Jalankan jika cabang sumber utama dan tahap induk atau sebelumnya, pekerjaan, atau langkah berhasil. and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
Jalankan jika cabang sumber tidak utama, dan tahap induk atau sebelumnya, pekerjaan, atau langkah berhasil. and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
Jalankan untuk cabang topik pengguna, jika tahap induk atau sebelumnya, pekerjaan, atau langkah berhasil. and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
Jalankan untuk build integrasi berkelanjutan (CI), jika tahap induk atau sebelumnya, pekerjaan, atau langkah 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 untuk build terjadwal, bahkan jika tahap induk atau 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 kembali true secara default kecuali alur 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 alur adalah I did a thing karena parameternya doThing 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 menentukannya dalam 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 mendatang untuk ditentukan dalam kondisi. Variabel yang dibuat dari langkah-langkah tersedia untuk langkah-langkah di masa mendatang secara default dan tidak perlu ditandai sebagai variabel output multi-pekerjaan.

Ada beberapa hal penting yang perlu diperhatikan tentang cakupan variabel yang dibuat dari langkah-langkah.

  • Variabel yang dibuat dalam langkah dalam pekerjaan dilingkupkan ke 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. Misalnya, dalam YAML berikut, kondisi eq(dependencies.A.result,'SucceededWithIssues') memungkinkan pekerjaan B berjalan karena pekerjaan A berhasil dengan 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 membatalkan build saya, tetapi masih berjalan. Mengapa?

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

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