運算式

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

在撰寫管線時,您可以在許多需要指定字串、布林值或數位值的地方使用運算式。 運算式最常見的用法是在判斷作業或步驟是否應該執行 的條件 中。

# Expressions are used to define conditions for a step, job, or stage
steps:
- task: ...
  condition: <expression>

運算式的另一個常見用法是定義變數。 運算式可以在 編譯時間執行時間進行評估。 編譯時間運算式可以在任何地方使用;運行時程表達式可用於變數和條件。 運行時程表達式是用來計算變數和狀態 (範例的內容的方法: condition) 。

# Two examples of expressions used to define variables
# The first one, a, is evaluated when the YAML file is compiled into a plan.
# The second one, b, is evaluated at runtime.
# Note the syntax ${{}} for compile time and $[] for runtime expressions.
variables:
  a: ${{ <expression> }}
  b: $[ <expression> ]

執行時間和編譯時間運算式語法之間的差異主要是可用的內容。 在編譯時間運算式 () ${{ <expression> }} 中,您可以存取 parameters 和靜態定義的 variables 。 在運行時程表達式 ($[ <expression> ]) 中,您可以存取更多 variables 但沒有參數。

在此範例中,運行時程表達式會設定 的值 $(isMain) 。 編譯運算式中的靜態變數會設定 的值 $(compileVar)

variables:
  staticVar: 'my value' # static variable
  compileVar: ${{ variables.staticVar }} # compile time expression
  isMain: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')] # runtime expression

steps:
  - script: |
      echo ${{variables.staticVar}} # outputs my value
      echo $(compileVar) # outputs my value
      echo $(isMain) # outputs True

運算式可以是常值、變數參考、相依性參考、函式或這些值的有效巢狀組合。

常值

在運算式中,您可以使用布林值、null、數位、字串或版本常值。

# Examples
variables:
  someBoolean: ${{ true }} # case insensitive, so True or TRUE also works
  someNumber: ${{ -1.2 }}
  someString: ${{ 'a b c' }}
  someVersion: ${{ 1.2.3 }}

Boolean

TrueFalse 是布林常值運算式。

Null

Null 是從字典遺漏傳回的特殊常值運算式,例如 (variables['noSuch']) 。 Null 可以是運算式的輸出,但不能直接在運算式內呼叫。

數字

從 '-'、'.' 或 '0' 到 '9' 開始。

String

必須是單引號。 例如:'this is a string'

若要表達常值單引號,請使用單引號來逸出它。 例如:'It''s OK if they''re using contractions.'

您可以針對多行字串使用管道字元 (|) 。

myKey: |
  one
  two
  three

版本

版本號碼,最多四個區段。 必須以數位開頭,且包含兩個或三個句點, (.) 個字元。 例如:1.2.3.4

變數

在運算式中,您可以使用下列兩種語法之一來存取變數:

  • 索引語法: variables['MyVar']
  • 屬性取值語法: variables.MyVar

若要使用屬性取值語法,屬性名稱必須:

  • a-Z從 或 開始_
  • 後面接著 a-Z0-9_

視執行內容而定,可以使用不同的變數。

  • 如果您使用 YAML 建立管線,則可以使用 管線變數
  • 如果您使用傳統編輯器建立組建管線,則可以使用 組建變數
  • 如果您使用傳統編輯器建立發行管線,則可以使用 發行變數

變數一律為字串。 如果您想要使用具類型的值,您應該改用 參數

注意

透過變數索引標籤 UI 設定這類變數時,使用具有傳統和 YAML 管線運算式的變數有一項限制。 定義為運算式的變數不應該相依于值運算式的另一個變數,因為它 不保證 這兩個運算式都會正確評估。 例如,我們有變數 a ,其值 $[ <expression> ] 做為變數 b 值的一部分。 因為處理變數的順序不保證變數 b 在評估之後可能會有不正確的變數 a 值。

只有在透過 YAML 管線中的 variables 關鍵字設定變數 時,才允許描述的建構。 您必須依照應處理的順序放置變數,才能在處理之後取得正確的值。

函式

下列內建函式可用於運算式。

  • True評估為所有參數是否為True
  • 最小參數:2。 最大參數:N
  • 將參數轉換成布林值以進行評估
  • 第一次之後的短線路 False
  • 範例: and(eq(variables.letters, 'ABC'), eq(variables.numbers, 123))

coalesce

  • 依序評估參數,並傳回不等於 Null 或空字串的值。
  • 最小參數:2。 最大參數:N
  • 範例: coalesce(variables.couldBeNull, variables.couldAlsoBeNull, 'literal so it always works')

contains

  • True評估左參數 String 是否包含右參數
  • 最小參數:2。 最大參數:2
  • 將參數轉換成字串以進行評估
  • 執行序數忽略大小寫比較
  • 範例: contains('ABCDE', 'BCD') (傳回 True)

containsValue

  • True評估左參數是否為數組,且任何專案都等於右參數。 也會評估 True 左參數是否為 物件,而任何屬性的值是否等於右參數。
  • 最小參數:2。 最大參數:2
  • 如果左參數是陣列,請轉換每個專案以符合右參數的類型。 如果左參數是 物件,請轉換每個屬性的值,以符合右參數的類型。 每個特定專案的相等比較會在 False 轉換失敗時進行評估。
  • 字串的序數忽略大小寫比較
  • 第一個比對之後的短線路

注意

YAML 管線中沒有常值語法可指定陣列。 此函式在一般管線中使用有限。 其適用于 管線裝飾專案內容 與系統提供的陣列,例如步驟清單。

您可以使用 containsValue 運算式在 物件中尋找相符的值。 以下範例示範如何尋找來源分支清單,以取得 的 Build.SourceBranch 相符專案。

parameters:
- name: branchOptions
  displayName: Source branch options
  type: object
  default:
    - refs/heads/main
    - refs/heads/test

jobs:
  - job: A1 
    steps:
    - ${{ each value in parameters.branchOptions }}:
      - script: echo ${{ value }}

  - job: B1 
    condition: ${{ containsValue(parameters.branchOptions, variables['Build.SourceBranch']) }}
    steps:
      - script: echo "Matching branch found"

convertToJson

  • 採用複雜的物件,並將它輸出為 JSON。
  • 最小參數:1。 最大參數:1。
parameters:
  - name: listOfValues
    type: object
    default:
      this_is:
        a_complex: object
        with:
          - one
          - two

steps:
- script: |
    echo "${MY_JSON}"
  env:
    MY_JSON: ${{ convertToJson(parameters.listOfValues) }}

腳本輸出:

{
  "this_is": {
    "a_complex": "object",
    "with": [
      "one",
      "two"
    ]
  }
}

counter

  • 此函式只能在定義變數的運算式中使用。 它不能當做步驟、作業或階段條件的一部分使用。
  • 評估每次執行管線時遞增的數位。
  • 參數:2。 prefixseed
  • 前置詞是字串運算式。 系統會針對前置詞的每個唯一值追蹤個別計數器值。 prefix應該使用 UTF-16 個字元。
  • Seed 是計數器的起始值

您可以在管線的每個執行中建立自動遞增一個計數器。 當您定義計數器時,您會提供 prefixseed 。 以下是示範此範例的範例。

variables:
  major: 1
  # define minor as a counter with the prefix as variable major, and seed as 100.
  minor: $[counter(variables['major'], 100)]

steps:
- bash: echo $(minor)

在管線第一次執行時,上述範例中的 值 minor 將會是 100。 第二次執行時,它會是 101,前提是 的值 major 仍然為 1。

如果您編輯 YAML 檔案,並將變數 major 的值更新為 2,則在管線的下一次執行中,的值 minor 會是 100。 後續執行會將計數器遞增至 101、102、103...

稍後,如果您編輯 YAML 檔案,並將 的值 major 設定回 1,則計數器的值會繼續該前置詞的離開位置。 在此範例中,它會在 102 繼續。

以下是另一個將變數設定為作為計數器的範例,該計數器從 100 開始,每次執行都會遞增 1,並每天重設為 100。

注意

pipeline.startTime 無法在運算式外部使用。 pipeline.startTime 會將 格式格式化 system.pipelineStartTime 為日期和時間物件,以便使用運算式。 的預設時區 pipeline.startTime 是 UTC。 您可以 變更組織的時區

jobs:
- job:
  variables:
    a: $[counter(format('{0:yyyyMMdd}', pipeline.startTime), 100)]
  steps:
  - bash: echo $(a)

以下是讓計數器維護 PR 和 CI 執行個別值的範例。

variables:
  patch: $[counter(variables['build.reason'], 0)]

計數器的範圍設定為管線。 換句話說,其值會針對該管線的每個執行遞增。 沒有專案範圍的計數器。

endsWith

  • True評估左參數 String 是否以右參數結尾
  • 最小參數:2。 最大參數:2
  • 將參數轉換成 String 以進行評估
  • 執行序數忽略大小寫比較
  • 範例: endsWith('ABCDE', 'DE') (傳回 True)

eq

  • True評估參數是否相等
  • 最小參數:2。 最大參數:2
  • 將右參數轉換為符合左參數的類型。 如果轉換失敗,則傳 False 回 。
  • 字串的序數忽略大小寫比較
  • 範例: eq(variables.letters, 'ABC')

format

  • 評估尾端參數,並將其插入前置參數字串中
  • 最小參數:1。 最大參數:N
  • 範例: format('Hello {0} {1}', 'John', 'Doe')
  • 針對日期格式設定使用.NET 自訂日期和時間格式規範, (yyyyyyMMM 、、、 dd 、) dHHHmmmsssfffffffK
  • 範例: format('{0:yyyyMMdd}', pipeline.startTime). 在此情況下 pipeline.startTime ,是特殊的日期時間物件變數。
  • 以雙括弧逸出。 例如: format('literal left brace {{ and literal right brace }}')

ge

  • True評估左參數是否大於或等於右參數
  • 最小參數:2。 最大參數:2
  • 將右參數轉換為符合左參數的類型。 轉換失敗時發生錯誤。
  • 字串的序數忽略大小寫比較
  • 範例: ge(5, 5) (傳回 True)

gt

  • True評估左參數是否大於右參數
  • 最小參數:2。 最大參數:2
  • 將右參數轉換為符合左參數的類型。 轉換失敗時發生錯誤。
  • 字串的序數忽略大小寫比較
  • 範例: gt(5, 2) (傳回 True)

in

  • True評估 left 參數是否等於任何右參數
  • 最小參數:1。 最大參數:N
  • 將右參數轉換為符合左參數的類型。 相等比較會 False 評估轉換是否失敗。
  • 字串的序數忽略大小寫比較
  • 第一次比對後的最少運算
  • 範例: in('B', 'A', 'B', 'C') (傳回 True)

Join

  • 串連右參數陣列中的所有專案,並以左參數字串分隔。
  • 最小參數:2。 最大參數:2
  • 陣列中的每個專案都會轉換成字串。 複雜物件會轉換成空字串。
  • 如果正確的參數不是陣列,結果就是轉換成字串的正確參數。

在此範例中,會在陣列中的每個專案之間加入分號。 參數類型是 物件。

parameters:
- name: myArray
  type: object
  default:
    - FOO
    - BAR
    - ZOO

variables:
   A: ${{ join(';',parameters.myArray) }}

steps:
  - script: echo $A # outputs FOO;BAR;ZOO

le

  • True評估左參數是否小於或等於右參數
  • 最小參數:2。 最大參數:2
  • 將右參數轉換為符合左參數的類型。 轉換失敗時發生錯誤。
  • 字串的序數忽略大小寫比較
  • 範例: le(2, 2) (傳回 True)

長度

  • 傳回字串或陣列的長度,可能是來自系統或來自參數的字串或陣列。
  • 最小參數:1。 最大參數 1
  • 範例: length('fabrikam') 傳回 8

lower

  • 將字串或變數值轉換為所有小寫字元
  • 最小參數:1。 最大參數 1
  • 傳回字串的對等小寫
  • 範例: lower('FOO') 傳回 foo

lt

  • True評估 left 參數是否小於右參數
  • 最小參數:2。 最大參數:2
  • 將右參數轉換為符合左參數的類型。 轉換失敗時發生錯誤。
  • 字串的序數忽略大小寫比較
  • 範例: lt(2, 5) (傳回 True)

ne

  • True評估參數是否不相等
  • 最小參數:2。 最大參數:2
  • 將右參數轉換為符合左參數的類型。 如果轉換失敗,則傳 True 回 。
  • 字串的序數忽略大小寫比較
  • 範例: ne(1, 2) (傳回 True)

  • True評估參數是否為False
  • 最小參數:1。 最大參數:1
  • 將值轉換為布林值以供評估
  • 範例: not(eq(1, 2)) (傳回 True)

notIn

  • True評估 left 參數是否不等於任何右參數
  • 最小參數:1。 最大參數:N
  • 將右參數轉換為符合左參數的類型。 相等比較會 False 評估轉換是否失敗。
  • 字串的序數忽略大小寫比較
  • 第一次比對後的最少運算
  • 範例: notIn('D', 'A', 'B', 'C') (傳回 True)

  • True評估是否有任何參數為True
  • 最小參數:2。 最大參數:N
  • 將參數轉換成布林值以進行評估
  • 第一次之後的最少運算 True
  • 範例: or(eq(1, 1), eq(2, 3)) (傳回 True,)

取代

  • 傳回新的字串,其中目前實例中的所有字串實例都會取代為另一個字串
  • 最小參數:3。 最大參數:3
  • replace(a, b, c):傳回 ,並將 b 的所有實例取代為 c
  • 範例: replace('https://www.tinfoilsecurity.com/saml/consume','https://www.tinfoilsecurity.com','http://server') (傳 http://server/saml/consume 回)

split

  • 根據指定的分隔符號將字串分割成子字串
  • 最小參數:2。 最大參數:2
  • 第一個參數是要分割的字串
  • 第二個參數是分隔字元
  • 傳回子字串的陣列。 當分隔符號連續出現或字串結尾時,陣列會包含空字串
  • 範例:
    variables:
    - name: environments
      value: prod1,prod2 
    steps:  
      - ${{ each env in split(variables.environments, ',')}}:
        - script: ./deploy.sh --environment ${{ env }}
    
  • 搭配 replace () 使用 split () 的範例:
    parameters:
    - name: resourceIds
      type: object
      default:
      - /subscriptions/mysubscription/resourceGroups/myResourceGroup/providers/Microsoft.Network/loadBalancers/kubernetes-internal
      - /subscriptions/mysubscription02/resourceGroups/myResourceGroup02/providers/Microsoft.Network/loadBalancers/kubernetes
    - name: environments
      type: object
      default: 
      - prod1
      - prod2
    
    trigger:
    - main
    
    steps:
    - ${{ each env in parameters.environments }}:
      - ${{ each resourceId in parameters.resourceIds }}:
          - script: echo ${{ replace(split(resourceId, '/')[8], '-', '_') }}_${{ env }}
    

startsWith

  • True評估左參數字串是否以右參數開頭
  • 最小參數:2。 最大參數:2
  • 將參數轉換成 String 以進行評估
  • 執行序數忽略大小寫比較
  • 範例: startsWith('ABCDE', 'AB') (傳回 True)

upper

  • 將字串或變數值轉換為所有大寫字元
  • 最小參數:1。 最大參數 1
  • 傳回字串的大寫對等專案
  • 範例: upper('bah') 傳回 BAH

xor

  • True評估是否只有一個參數True
  • 最小參數:2。 最大參數:2
  • 將參數轉換成布林值以進行評估
  • 範例: xor(True, False) (傳回 True)

作業狀態檢查函式

您可以使用下列狀態檢查函式作為條件中的運算式,但不能在變數定義中使用。

always

  • 一律評估為 True (,即使取消) 也一樣。 注意:重大失敗可能仍會防止工作執行。 例如,如果取得來源失敗。

已取消

  • 如果管線已取消,評估為 True

失敗

  • 針對步驟,相當於 eq(variables['Agent.JobStatus'], 'Failed')
  • 針對作業:
    • 在沒有引數的情況下,只有在相依性圖形中的任何先前作業失敗時,才會評估 True 為 。
    • 使用作業名稱做為引數時,只有在其中任何一個作業失敗時,才會評估 True 為 。

成功

  • 針對步驟,相當於 in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')
  • 使用作業時,請與 搭配 dependsOn 使用,而且您想要評估先前的工作是否成功。 作業的設計目的是要以平行方式執行,而階段會循序執行。
  • 針對作業:
    • 在沒有引數的情況下,只有在相依性圖表中的所有先前作業都成功或部分成功時,才會評估 True 為 。
    • 使用作業名稱做為引數時,如果所有作業都成功或部分成功,則 True 評估為 。
    • 如果管線已取消,則評估為 False

succeededOrFailed

  • 針對步驟,相當於 in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed')

  • 針對作業:

    • 在沒有引數的情況下,不論相依性圖形中的任何作業成功或失敗,都會評估 True 為 。
    • 使用作業名稱做為引數,評估 True 這些作業是否成功或失敗。

    這就像 always() ,不同之處在于它會在管線取消時進行評估 False

條件式插入

您可以使用 ifelseifelse 子句,有條件地指派變數值或設定工作的輸入。 您也可以在符合條件時有條件地執行步驟。

您可以使用 if 來有條件地指派變數值或設定工作的輸入。 您也可以在符合條件時有條件地執行步驟。

elseifelse 子句可從 Azure DevOps 2022 開始提供,不適用於 Azure DevOps Server 2020 和舊版 Azure DevOps。

條件僅適用于使用範本語法時。 深入瞭解 變數語法

針對範本,您可以在新增序列或對應時使用條件式插入。 深入瞭解 範本中的條件式插入

有條件地指派變數

variables:
  ${{ if eq(variables['Build.SourceBranchName'], 'main') }}: # only works if you have a main branch
    stageName: prod

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo ${{variables.stageName}}

有條件地設定工作輸入

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: PublishPipelineArtifact@1
  inputs:
    targetPath: '$(Pipeline.Workspace)'
    ${{ if eq(variables['Build.SourceBranchName'], 'main') }}:
      artifact: 'prod'
    ${{ else }}:
      artifact: 'dev'
    publishLocation: 'pipeline'

有條件地執行步驟

如果沒有設定變數,或 的值 foo 不符合 if 條件,語句 else 將會執行。 在這裡,的值 foo 會在 條件中 elseif 傳回 true。

variables:
  - name: foo
    value: contoso # triggers elseif condition

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo "start"
- ${{ if eq(variables.foo, 'adaptum') }}:
  - script: echo "this is adaptum"
- ${{ elseif eq(variables.foo, 'contoso') }}: # true
  - script: echo "this is contoso" 
- ${{ else }}:
  - script: echo "the value is not adaptum or contoso"

Each 關鍵字

您可以使用 each 關鍵字來迴圈查看具有物件類型的參數。

parameters:
- name: listOfStrings
  type: object
  default:
  - one
  - two

steps:
- ${{ each value in parameters.listOfStrings }}:
  - script: echo ${{ value }}

此外,您可以逐一查看 物件內的巢狀專案。

parameters:
- name: listOfFruits
  type: object
  default:
  - fruitName: 'apple'
    colors: ['red','green']
  - fruitName: 'lemon'
    colors: ['yellow']
steps:
- ${{ each fruit in parameters.listOfFruits }} :
  - ${{ each fruitColor in fruit.colors}} :
    - script: echo ${{ fruit.fruitName}} ${{ fruitColor }}

相依性

運算式可以使用相依性內容來參考先前的作業或階段。 您可以使用相依性來:

  • 參考上一個作業的作業狀態
  • 參考上一個階段的階段狀態
  • 在相同階段中參考上一個作業中的輸出變數
  • 參考階段中上一個階段的輸出變數
  • 在下列階段中,在上一個階段中參考作業中的輸出變數

內容會針對作業和階段呼叫 dependencies ,且運作方式與變數非常類似。 在作業內,如果您參考另一個階段中作業的輸出變數,則內容稱為 stageDependencies

如果您在輸出變數中遇到引號字元 ('") 的問題,請參閱 此疑難排解指南

階段到階段相依性

在結構上, dependencies 物件是作業和階段名稱與 resultsoutputs 的對應。 以 JSON 表示,看起來會像這樣:

"dependencies": {
  "<STAGE_NAME>" : {
    "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
    "outputs": {
        "jobName.stepName.variableName": "value"
    }
  },
  "...": {
    // another stage
  }
}

使用此形式的 來 dependencies 對應變數或檢查階段層級的條件。 在此範例中,階段 B 會執行階段 A 是否成功或略過。

注意

下列範例使用標準管線語法。 如果您使用部署管線,變數和條件變數語法將會有所不同。 如需要使用的特定語法的相關資訊,請參閱 部署作業

stages:
- stage: A
  condition: false
  jobs:
  - job: A1
    steps:
    - script: echo Job A1
- stage: B
  condition: in(dependencies.A.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
  jobs:
  - job: B1
    steps:
    - script: echo Job B1

階段也可以使用另一個階段的輸出變數。 在此範例中,階段 B 相依于階段 A 中的變數。

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
     # or on Windows:
     # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
       name: printvar

- stage: B
  condition: and(succeeded(), eq(dependencies.A.outputs['A1.printvar.shouldrun'], 'true'))
  dependsOn: A
  jobs:
  - job: B1
    steps:
    - script: echo hello from Stage B

注意

根據預設,管線中的每個階段都相依于 YAML 檔案中的階段之前。 如果您需要參考目前階段之前的階段,您可以將區段新增 dependsOn 至階段,以覆寫此自動預設值。

一個階段內的作業對作業相依性

在單一階段內的作業層級, dependencies 資料不包含階段層級資訊。

"dependencies": {
  "<JOB_NAME>": {
    "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
    "outputs": {
      "stepName.variableName": "value1"
    }
  },
  "...": {
    // another job
  }
}

在此範例中,一律會略過作業 A,並執行作業 B。 作業 C 將會執行,因為其所有相依性都會成功或被略過。

jobs:
- job: a
  condition: false
  steps:
  - script: echo Job A
- job: b
  steps:
  - script: echo Job B
- job: c
  dependsOn:
  - a
  - b
  condition: |
    and
    (
      in(dependencies.a.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
      in(dependencies.b.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
    )
  steps:
  - script: echo Job C

在此範例中,作業 B 相依于作業 A 的輸出變數。

jobs:
- job: A
  steps:
  - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
  # or on Windows:
  # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
    name: printvar

- job: B
  condition: and(succeeded(), eq(dependencies.A.outputs['printvar.shouldrun'], 'true'))
  dependsOn: A
  steps:
  - script: echo hello from B

跨階段的作業對作業相依性

在作業層級,您也可以參考上一個階段中作業的輸出。 這需要使用 stageDependencies 內容。

"stageDependencies": {
  "<STAGE_NAME>" : {
    "<JOB_NAME>": {
      "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
      "outputs": {
          "stepName.variableName": "value"
      }
    },
    "...": {
      // another job
    }
  },
  "...": {
    // another stage
  }
}

在此範例中,如果略過作業 A1,作業 B1 將會執行。 作業 B2 會檢查作業 A1 輸出變數的值,以判斷是否應該執行。

trigger: none

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
     # or on Windows:
     # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
       name: printvar

- stage: B
  dependsOn: A
  jobs:
  - job: B1
    condition: in(stageDependencies.A.A1.result, 'Skipped') # change condition to `Succeeded and stage will be skipped`
    steps:
    - script: echo hello from Job B1
  - job: B2
    condition: eq(stageDependencies.A.A1.outputs['printvar.shouldrun'], 'true')
    steps:
     - script: echo hello from Job B2

如果作業相依于部署作業在不同階段中定義的變數,則語法會不同。 在下列範例中,如果 build_job 部署作業設定 runTeststrue ,則作業 run_tests 會執行。 請注意,用於字典的 outputs 索引鍵為 build_job.setRunTests.runTests

stages:
- stage: build
  jobs:
  - deployment: build_job
    environment:
      name: Production
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            name: setRunTests
            inputs:
              targetType: inline
              pwsh: true
              script: |
                $runTests = "true"
                echo "setting runTests: $runTests"
                echo "##vso[task.setvariable variable=runTests;isOutput=true]$runTests"

- stage: test
  dependsOn:
  - 'build'
  jobs:  
    - job: run_tests
      condition: eq(stageDependencies.build.build_job.outputs['build_job.setRunTests.runTests'], 'true')
      steps:
        ...

視作業輸出而定的階段

如果在建置之後不需要變更,您可能會想要在特定情況下略過管線中的階段。 例如,當您使用 Terraform 方案,而且您想要觸發核准,且只有在計畫包含變更時才適用。

當您在階段上使用這個條件時,必須使用 dependencies 變數,而不是 stageDependencies

下列範例是一個簡單的腳本,可設定變數 (在階段中的步驟中使用 Terraform Plan) 的實際資訊,然後只有在變數具有特定值時才叫用第二個階段。

stages:
- stage: plan_dev
  jobs:
  - job: terraform_plan_dev
    steps:
    - bash: echo '##vso[task.setvariable variable=terraform_plan_exitcode;isOutput=true]2'
      name: terraform_plan
- stage: apply_dev
  dependsOn: plan_dev
  condition: eq(dependencies.plan_dev.outputs['terraform_plan_dev.terraform_plan.terraform_plan_exitcode'], '2')
  jobs:
  - job: part_b
    steps:
    - bash: echo "BA"

如果階段相依于部署作業在不同階段中定義的變數,則語法會不同。 在下列範例中,階段 test 取決於 的部署 build_job 設定 shouldTesttrue 。 請注意,在 condition 階段的 test 中, build_job 會出現兩次。

stages:
- stage: build
  jobs:
  - deployment: build_job
    environment:
      name: Production
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            name: setRunTests
            inputs:
              targetType: inline
              pwsh: true
              script: |
                $runTests = "true"
                echo "setting runTests: $runTests"
                echo "##vso[task.setvariable variable=runTests;isOutput=true]$runTests"

- stage: test
  dependsOn:
  - 'build'
  condition: eq(dependencies.build.outputs['build_job.build_job.setRunTests.runTests'], 'true')
  jobs:
    ...

在上述範例中,條件會參考環境,而不是環境資源。 若要參考環境資源,您必須將環境資源名稱新增至相依性條件。 在下列範例中,條件會參考名為 vmtest 的環境虛擬機器資源。

stages:
- stage: build
  jobs:
  - deployment: build_job
    environment:
      name: vmtest
      resourceName: winVM2
      resourceType: VirtualMachine
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            name: setRunTests
            inputs:
              targetType: inline
              pwsh: true
              script: |
                $runTests = "true"
                echo "setting runTests: $runTests"
                echo "##vso[task.setvariable variable=runTests;isOutput=true]$runTests"

- stage: test
  dependsOn:
  - 'build'
  condition: eq(dependencies.build.outputs['build_job.Deploy_winVM2.setRunTests.runTests']
, 'true')
  jobs:
    ...

篩選的陣列

在專案集合上操作時,您可以使用 * 語法來套用篩選的陣列。 篩選的陣列會傳回所有物件/元素,而不論其名稱為何。

例如,請考慮名為 foo 的物件陣列。 我們想要取得陣列中每個物件中屬性值的 id 陣列。

[
    { "id": 1, "a": "avalue1"},
    { "id": 2, "a": "avalue2"},
    { "id": 3, "a": "avalue3"}
]

我們可以執行下列動作:

foo.*.id

這會告訴系統以篩選陣列的形式運作 foo ,然後選取 id 屬性。

這會傳回:

[ 1, 2, 3 ]

類型轉換

當評估運算式時,運算式中的值可能會從某個類型轉換成另一個類型。 評估運算式時,參數會聯合至相關的資料類型,然後切換回字串。

例如,在此 YAML 中,和 的值 TrueFalse 會在評估運算式時轉換為 10 。 當左參數小於右參數時,函式 lt()True 傳回 。

variables:
  firstEval: $[lt(False, True)] # 0 vs. 1, True
  secondEval: $[lt(True, False)] # 1 vs. 0, False

steps:
- script: echo $(firstEval)
- script: echo $(secondEval)

在此範例中,值 variables.emptyString 和空字串都會評估為空字串。 函式 coalesce() 會依序評估參數,並傳回不等於 Null 或空字串的第一個值。

variables:
  coalesceLiteral: $[coalesce(variables.emptyString, '', 'literal value')]

steps:
- script: echo $(coalesceLiteral) # outputs literal value

下面會進一步列出詳細的轉換規則。

From / To Boolean Null 數字 String 版本
布林值 - - -
Null - -
Number - - 部分
String 部分 Partial - Partial
版本 - - -

Boolean

若要編號:

  • False0
  • True1

若要字串:

  • False'False'
  • True'True'

Null

  • 至布林值: False
  • 若要編號: 0
  • 若要字串: '' (空字串)

數字

  • 若要布林值: 0False ,任何其他數位→ True
  • 至版本:必須大於零,而且必須包含非零十進位。 必須小於 Int32.MaxValue (十進位元件也) 。
  • 至字串:將數位轉換成沒有千位分隔符號且沒有小數分隔符號的字串。

String

  • 若要布林值: '' (空字串) → False ,任何其他字串→ True
  • 若要為 null: '' (空字串) → Null ,任何其他字串都無法轉換
  • 若要編號: '' (空字串) → 0,否則會使用InvariantCulture執行 C# Int32.TryParse 和下列規則:AllowDecimalPoint |AllowLeadingSign |AllowLeadingWhite |AllowThousands |AllowTrailingWhite。 如果 TryParse 失敗,則無法轉換。
  • 版本:執行 C# 的 Version.TryParse 。 至少必須包含主要和次要元件。 如果 TryParse 失敗,則無法轉換。

版本

  • 至布林值: True
  • 若要字串:Major.Minor 或 Major.Minor.Build 或 Major.Minor.Build.Revision。

常見問題集

我想要執行運算式不支援的動作。 我有哪些擴充管線功能的選項?

您可以使用包含運算式的腳本自訂管線。 例如,此程式碼片段會採用 變數, BUILD_BUILDNUMBER 並使用 Bash 加以分割。 此腳本會針對主要和次要執行數位輸出兩個新的變數 $MAJOR_RUN$MINOR_RUN 。 然後,會使用這兩個變數來建立兩個管線變數, $major 並使用 $minortask.setvariable。 這些變數可供下游步驟使用。 若要跨管線共用變數,請參閱 變數群組

steps:
- bash: |
    MAJOR_RUN=$(echo $BUILD_BUILDNUMBER | cut -d '.' -f1)
    echo "This is the major run number: $MAJOR_RUN"
    echo "##vso[task.setvariable variable=major]$MAJOR_RUN"

    MINOR_RUN=$(echo $BUILD_BUILDNUMBER | cut -d '.' -f2)
    echo "This is the minor run number: $MINOR_RUN"
    echo "##vso[task.setvariable variable=minor]$MINOR_RUN"

- bash: echo "My pipeline variable for major run is $(major)"
- bash: echo "My pipeline variable for minor run is $(minor)"