共用方式為


管線條件

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

本文說明 Azure Pipelines 階段、作業或步驟執行的條件,以及如何指定不同的條件。 如需階段、作業和步驟的詳細資訊,請參閱 Azure Pipelines 的重要概念。

  • 根據預設,如果作業或階段不相依於任何其他作業或階段,或是其所有相依性都已完成且成功,則會執行作業或階段。 這項需求不僅適用於直接相依性,而且適用於其間接相依性,以遞歸方式計算。

  • 根據預設,如果作業中沒有任何項目失敗,且步驟緊接在完成前的步驟,就會執行。

您可以強制執行階段、作業或步驟,即使先前的相依性失敗,或指定自定義條件,也可以覆寫或自定義此行為。

注意

本文討論 YAML 管線功能。 針對傳統管線,您可以指定工作或作業在 每項工作的 [控制選項 ] 中執行的一些條件,以及在 發行管線中作業的其他選項 中執行。

階段、作業或步驟執行的條件

在管線定義 YAML 中,您可以指定執行階段、作業或步驟的下列條件:

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

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

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

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

  • 自定義條件。

根據預設,如果所有直接或間接相依性都成功,就會執行階段、作業和步驟。 此狀態與指定 condition: succeeded()相同。 如需詳細資訊,請參閱 成功狀態函式

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

下列 YAML 範例顯示 always()failed() 條件。 即使相依性失敗或組建取消,第一個作業中的步驟仍會執行。 只有在第一個作業失敗時,第二個作業才會執行。

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

您也可以在條件中設定和使用變數。 下列範例會設定並使用 isMain 變數來指定 mainBuild.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)

重要

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

自訂條件

如果內建條件不符合您的需求,您可以指定 自定義條件。 您可以在 YAML 管線定義中將條件寫入為表示式。

代理程式會評估以最內層函式開頭的表達式,然後向外繼續。 最終結果是布爾值,可判斷工作、作業或階段是否應該執行。 如需語法的完整指南,請參閱 表達式

如果您的任一條件使得工作即使在建置取消之後也能執行,請為取消逾時指定合理的值,讓使用者在取消執行之後有足夠的時間完成這些工作。

取消組建時的條件結果

取消組建並不表示其所有階段、作業或步驟都會停止執行。 哪些階段、作業或步驟會停止執行,取決於您指定的條件,以及您取消組建的管線執行時間點。 如果略過階段、作業或步驟的父系,不論其條件為何,工作都不會執行。

每當階段、作業或步驟的條件評估為 true時,就會執行。 如果您的條件未考慮任務的父系狀態,即使已取消其父代,工作仍可能會執行。 若要控制在取消組建時執行條件的階段、作業或步驟,請務必 在條件中包含作業狀態檢查函式

下列範例顯示取消組建時,在階段、作業或步驟上設定的各種條件結果。

階段範例 1

在下列管線中,根據預設stage2,會相依於 stage1,但stage2每當來源分支為 main時,都會有一個condition設定來執行,而不論狀態為何stage1

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

階段範例 2

在下列管線中, stage2 預設相依於 stage1 。 中的stage2作業B有一組condition。 如果您在分支上 main 將組建排入佇列,並在執行時 stage1 取消它, stage2 則不會執行,即使它包含條件評估為 true的作業也一樣。

原因是stage2預設 為 condition: succeeded(),其會在取消時stage1評估false為 。 因此, stage2 會略過,而且不會執行任何作業。

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

階段範例 3

在下列管線中,根據預設 stage2 ,取決於 stage1,而作業 B 內的步驟有一組 condition

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

作業範例 1

在下列 YAML 管線中,作業B預設取決於作業A,但每當來源分支為 main時,作業B就會condition設定為執行。 如果您在分支上 main 將組建排入佇列,並在作業 A 執行時取消它,作業 B 仍會執行,因為 eq(variables['Build.SourceBranch'], 'refs/heads/main') 評估為 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

如果只有在作業成功且組建來源是分支時,才想要執行作業BA,則應該是 。mainand(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))condition

作業範例 2

在下列管線中,作業 B 預設取決於作業 A 。 如果您在分支上main將組建排入佇列,並在作業A執行時取消它,即使其步驟評估conditiontrue,作業B也不會執行。

原因是作業B具有預設 condition: succeeded(),它會在取消作業A時評估false為 。 因此,會略過作業 B ,而且不會執行任何步驟。

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

步驟範例

您也可以有步驟的條件。

在下列管線中,每當來源分支為 main時,步驟 2.3 就會設定condition為 執行。 如果您在分支上 main 將組建排入佇列,並在步驟 2.1 或 2.2 正在執行時取消它,則步驟 2.3 仍會執行,因為 eq(variables['Build.SourceBranch'], 'refs/heads/main') 評估為 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')

條件設定

下表顯示產生各種結果的範例 condition 設定。

注意

Release.Artifacts.{artifact-alias}.SourceBranch 等於 Build.SourceBranch

所需的結果 範例條件設定
如果來源分支是主要分支,則執行 ,即使父系或先前階段、作業或步驟失敗或已取消也一樣。 eq(variables['Build.SourceBranch'], 'refs/heads/main')
如果來源分支是 main,且父分支或上一個階段、作業或步驟成功,請執行 。 and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/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')
如果變數設定為 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。

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

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

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

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

條件中的範本參數

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

例如,下列 parameters.yml 檔案會 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) }}

管線程式代碼會參考 parameters.yml 範本。 管線的輸出是因為 I did a thing 參數 doThing 為 true。

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

trigger:
- none

extends:
  template: parameters.yml

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

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

您可以讓變數可供未來的作業使用,並在條件中指定它。 未來作業可用的變數必須使用 標示為多作業輸出變數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."

在後續步驟條件中使用的步驟中建立的變數

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

有一些關於從步驟建立之變數範圍的重要事項

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

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

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

常見問題集

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

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

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

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

如果階段中設定的條件不包含 作業狀態檢查函式,您可能會遇到此問題。 若要解決此問題,請將作業狀態檢查函式新增至條件。

如果您在佇列階段但未執行時取消作業,則會取消整個作業,包括所有其他階段。 如需詳細資訊,請參閱 本文稍早取消 組建時的條件結果。