管線條件
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
本文說明 Azure Pipelines 階段、作業或步驟執行的條件,以及如何指定不同的條件。 如需階段、作業和步驟的詳細資訊,請參閱 Azure Pipelines 的重要概念。
預設情況下,如果作業或階段不依賴任何其他作業或階段,或其所有依賴已完成且成功,則會執行作業或階段。 這項需求不僅適用於直接相依性,而且適用於其間接相依性,以遞歸方式計算。
預設情況下,如果工作中的步驟尚未失敗,並且緊接在已完成步驟之後,該步驟將會執行。
您可以通過強制執行某個階段、作業或步驟,即使先前的相依性失敗,或者透過指定自訂條件,來覆寫或自訂此行為。
注意
本文討論 YAML 管線功能。 針對傳統的管線,您可以在每項工作的控制選項中指定執行作業或工作的某些條件,並在發行管線中作業的其他選項中指定。
階段、作業或步驟執行的條件
在管線定義 YAML 中,您可以指定執行階段、作業或步驟的下列條件:
只有當具有相同代理程式集區的所有先前直接和間接相依性都成功時。 如果您有不同的代理程式集區,這些階段或作業會同時執行。 如果未在 YAML 中設定任何條件,則此條件為預設值。
即使先前的相依性失敗,執行依然繼續,除非該執行被取消。 請在 YAML 中使用
succeededOrFailed()
來設定此條件。即使先前的相依性失敗,即使執行被取消,過程仍會繼續。 請在此條件的 YAML 中使用
always()
。只有在先前的依賴項失敗時。 在 YAML 中使用
failed()
以符合此條件。
- 自定義條件。
根據預設,如果所有直接或間接相依性都成功,就會執行階段、作業和步驟。 此狀態與指定 condition: succeeded()
相同。 如需詳細資訊,請參閱 成功狀態函式。
當您指定 condition
階段、作業或步驟的屬性時,會覆寫預設 condition: succeeded()
。 指定您自己的條件可能會導致您的階段、作業或步驟執行,即使建置被取消亦然。 請確認您所撰寫的條件已考慮到父階段或工作的狀態。
下列 YAML 範例顯示 always()
和 failed()
條件。 即使相依性失敗或組建取消,第一個作業中的步驟仍會執行。 在第二個指令碼任務中,exit 1
命令 Foo
任務失敗。 只有在第一個作業失敗時,第二個作業才會執行。
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
您也可以在條件中設定和使用變數。 下列範例會設定並使用 isMain
變數來指定 main
為 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)
重要
系統會評估條件,以判斷是否要啟動階段、作業或步驟。 因此,在該工作單位中於運行時計算的結果均不可用。 例如,如果您的任務使用 $[ ]
語法的運行時表達式來設定變數,則無法在該任務的自定義條件中使用該變數。
自訂條件
如果內建條件不符合您的需求,您可以指定 自定義條件。 您可以在 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
的步驟。 原因是為了回應 stage1
的取消,stage2
已略過。
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
,但作業B
已設定為每當來源分支為main
時執行。 如果您在分支上 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
如果您希望只有當作業A
成功且構建來源是main
分支時,作業B
才執行,則應將condition
設為and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
。
作業範例 2
在下列管線中,作業 B
預設取決於作業 A
。 如果您在main
分支上將組建排入佇列並在作業A
執行期間取消它,則即便其步驟含有評估結果為true
的condition
,作業B
也不會執行。
原因是當作業 A
取消時,作業 B
被評估為 false
。 因此,會略過作業 B
,而且不會執行任何步驟。
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())
步驟範例
您也可以為步驟設置條件。
在下列管線中,只要來源分支是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: and(succeeded(), ${{ eq(parameters.doThing, true) }})
condition
在前述管線中結合了兩個函式:succeeded()
和${{ eq(parameters.doThing, true) }}
。 函 succeeded()
式會檢查上一個步驟是否成功。 函 succeeded()
式會傳 true
回 ,因為沒有上一個步驟。
函式 ${{ eq(parameters.doThing, true) }}
會檢查參數是否 doThing
等於 true
。 由於 doThing
的預設值是 true
,除非管線設定了不同的值,否則條件會預設傳回 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')
允許作業 B
在作業 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
我取消了組建,但它仍在執行中。 為什麼?
如果階段中設定的條件不包含 作業狀態檢查函式,您可能會遇到此問題。 若要解決此問題,請將作業狀態檢查函式新增至條件。
如果您在佇列階段但未執行時取消作業,則會取消整個作業,包括所有其他階段。 如需詳細資訊,請參閱本文稍早提到的主題 組建被取消時的條件結果。