指定條件

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

您可以指定每個階段、作業或步驟據以執行的條件。 根據預設,如果作業或階段不相依於任何其他作業或階段,或者 它相依的所有 作業或階段都已完成且成功,則會執行作業或階段。 這不僅包含直接相依性,而且包含其相依性,而且會以遞歸方式計算。 根據預設,一個步驟在其作業中沒有任何項目失敗,且其上一個步驟已完成時,就會執行。 您可以自訂此行為,具體方法是,即便先前的相依性失敗仍強制執行階段、作業或步驟,或指定自訂條件。

您可以指定步驟、作業或階段據以執行的條件。

  • 只有當具有相同代理程式集區的所有先前直接和間接相依性都成功時。 如果您有不同的代理程式集區,則這些階段或作業將會同時執行。 如果 YAML 中沒有設定條件,則這是預設值。

  • 即使先前的相依性失敗、除非已取消執行。 succeededOrFailed()在此條件的 YAML 中使用。

  • 即使先前的相依性失敗、即使已取消執行。 always()在此條件的 YAML 中使用。

  • 只有在先前的相依性失敗時。 failed()在此條件的 YAML 中使用。

  • 自訂條件

根據預設,如果所有直接和間接相依性都成功,步驟、作業和階段就會執行。 就像您指定了“condition: succeeded()” (請參閱 成功狀態函式)。

jobs:
- job: Foo

  steps:
  - script: echo Hello!
    condition: always() # this step will always run, even if the pipeline is canceled

- job: Bar
  dependsOn: Foo
  condition: failed() # this job will only run if Foo fails

您也可以在條件中使用變數。

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)

系統會評估條件,以決定是否要啟動階段、作業或步驟。 這表示在該工作單位內的運行時間不會計算任何專案。 例如,如果您有使用語法使用運行時間表達式 $[ ] 來設定變數的作業,則無法在自定義條件中使用該變數。

TFS 不支援YAML。

注意

當您為階段/作業/步驟指定自己的 condition 屬性時,會覆寫其預設 condition: succeeded()。 這可能會導致您的階段/作業/步驟執行,即使取消組建也一樣。 撰寫您自己的條件時,請務必考慮父階段/作業的狀態。

啟用自定義條件

如果內建條件不符合您的需求,您可以指定 自定義條件

條件會撰寫為 YAML 管線中的運算式。 代理程式會從最內層的函式開頭評估運算式,並進行後續操作。最終結果將是布林值,用以決定工作、作業或階段是否應執行。 如需語法的完整指南,請參閱表達式文章。

您是否有任何條件即便在使用者取消組建後仍可能讓工作執行? 若是如此,請為取消逾時指定合理的值,讓這類工作在使用者取消執行之後有足夠的時間完成。

取消建置時的管線行為

取消組建時,並不表示其所有階段、作業或步驟都會停止執行。 決策取決於您指定的階段、作業或步驟 conditions ,以及您取消組建的管線執行時間點。

如果您的條件未考慮階段/作業/步驟的父系狀態,則如果條件評估為 true、您的階段、作業或步驟就會執行, 即使取消其父系也一樣 。 如果略過其父系,則不會執行您的階段、作業或步驟。

讓我們看看一些範例。

根據預設,在此管線中, stage2 會相依 stage1 於 和 stage2 有一組 conditionstage2 只有在來源分支為 main時才會執行。

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

如果您在分支上 main 將組建排入佇列,並在執行時 stage1 取消,仍會執行, stage2 因為 eq(variables['Build.SourceBranch'], 'refs/heads/main') 評估為 true

在這裡管線中, stage2 相依於 stage1。 作業 B 有一組 condition

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

如果您在分支上main將組建排入佇列,而且在執行時stage2stage1取消,則不會執行,即使它包含條件評估為true的作業B也一樣。 原因是stage2預設 為 condition: succeeded(),其會在取消時stage1評估false為 。 因此, stage2 會略過,而且不會執行任何作業。

假設您有下列 YAML 管線。 請注意,根據預設,相依stage1於 ,且script: echo 2其具有設定conditionstage2

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

如果您在分支上 main 將組建排入佇列,並在執行時 stage1 取消它, stage2則不會 執行,即使它包含作業 B 中的步驟,其條件評估為 true。 原因是 stage2 因為已略過以回應 stage1 取消。

若要防止在取消組建時執行階段、作業或步驟 conditions ,請務必在撰寫 conditions時考慮其父系的狀態。 如需詳細資訊,請參閱 作業狀態函式

範例

針對主要分支執行,即使已取消,即使失敗也一樣

eq(variables['Build.SourceBranch'], 'refs/heads/main')

如果成功,請針對主要分支執行

and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))

如果分支不是 main,則執行 ,如果成功

and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))

如果成功,請針對用戶主題分支執行

and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))

如果成功,請執行 持續整合 (CI) 組建

and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))

如果提取要求的分支原則執行組建,則執行 ,如果失敗

and(failed(), eq(variables['Build.Reason'], 'PullRequest'))

如果已排程組建,即使失敗,即使已取消,仍執行

eq(variables['Build.Reason'], 'Schedule')

Release.Artifacts。{artifact-alias}。SourceBranch 相當於 Build.SourceBranch

如果變數設定為 true,則一律執行,即使已取消,即使失敗也一樣

eq(variables['System.debug'], true)

如果變數為 null,請執行 (空字串)

由於所有變數都會被視為 Azure Pipelines 中的字串串,因此空字串相當於 null 此管線中的字串。

variables:
- name: testEmpty
  value: ''

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

使用範本參數作為條件的一部分

當您在具有條件的相同管線中宣告參數時,將會在考量條件之前進行參數擴充。 在此情況下,您可以在條件中內嵌參數。 此 YAML 檔案中的腳本將會執行,因為 parameters.doThing 為 true。

condition管線中的 結合兩個函式:succeeded()eq('${{ parameters.doThing }}', true)。 函 succeeded() 式會檢查上一個步驟是否成功。 函 succeeded() 式會傳回 true,因為沒有上一個步驟。

eq('${{ parameters.doThing }}', true) 式會檢查 doThing 參數是否等於 true。 由於 doThing 的預設值為 true,除非管線中設定不同的值,否則條件預設會傳回 true。

如需更多範本參數範例,請參閱 範本類型和使用方式

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

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

當您將參數傳遞至範本時,您必須在範本中設定參數的值,或使用 templateContext將屬性傳遞至範本

# 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) }}
# azure-pipeline.yml
parameters:
- name: doThing
  default: true 
  type: boolean

trigger:
- none

extends:
  template: parameters.yml

此管線的輸出是因為 I did a thing 參數 doThing 為 true。

在後續作業的條件中使用某個作業的輸出變數

您可以讓變數可供未來的作業使用,並在條件中指定它。 未來作業可用的變數必須使用標示為多作業輸出變數isOutput=true

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

在後續步驟中使用從某個條件中的步驟建立的管線變數

您可以讓變數可供未來的步驟使用,並在條件中加以指定。 根據預設,從步驟建立的變數可供未來步驟使用,且不需要使用 標示為多作業輸出變數isOutput=true

關於上述方法和 範圍,有一些重要事項需要注意:

  • 在作業的步驟中建立的變數,範圍會限定為相同作業中的步驟。
  • 在步驟中建立的變數只能在後續步驟中作為環境變數使用。
  • 在步驟中建立的變數無法在定義它們的步驟中使用。

以下是在步驟中建立管線變數,並在後續步驟的條件和腳本中使用 變數的範例。

steps:

# This step creates a new pipeline variable: doThing. This variable will be available to subsquent steps.
- bash: |
    echo "##vso[task.setvariable variable=doThing]Yes"
  displayName: Step 1

# This step is able to use doThing, so it uses it in its condition
- script: |
    # You can 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'))

常見問題集

如果前一個作業成功但發生問題時觸發作業?

您可以使用上一個作業的結果。 例如,在此 YAML 檔案中,條件 eq(dependencies.A.result,'SucceededWithIssues') 可讓作業執行,因為作業 A 成功發生問題。

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

我取消了組建,但它仍在執行中。 發生了什麼事?

如果階段中設定的條件不包含作業狀態檢查函式,您將會遇到此問題。 若要解決此問題,請將作業狀態檢查函式新增至條件。 如果您在佇列中取消作業,但未執行,則會取消整個作業,包括所有其他階段。

深入了解 當組建取消時管線的行為。