分享方式:


運算式

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

重要

從 Azure DevOps 內容版本選取器選取版本。

選取對應至您平臺和版本的本文版本。 版本選取器位於目錄上方。 查閱您的 Azure DevOps 平臺和版本

表達式可用於撰寫管線時需要指定字串、布爾值或數位值的許多位置。 當表達式傳回陣列時,會套用一般索引規則,而索引會以 0開頭。

表達式最常見的用法是在條件中判斷作業或步驟是否應該執行。

# 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 }}

布林值

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-Z 0-9_

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

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

注意

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

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

函式

下列內建函式可用於表達式中。

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

coalesce

  • 依序評估參數(由左至右),並傳回不等於 null 或空字串的第一個值。
  • 如果參數值全部為 Null 或空字串,則不會傳回任何值。
  • 最小參數:2。 最大參數:N
  • 範例: coalesce(variables.couldBeNull, variables.couldAlsoBeNull, 'literal so it always works')

contains

  • True評估左參數 String 是否包含右參數
  • 最小參數:2。 最大參數:2
  • 將參數轉換成 String 以進行評估
  • 執行序數忽略大小寫比較
  • 範例: 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"
    ]
  }
}

計數器

  • 此函式只能在定義變數的表達式中使用。 它不能當做步驟、作業或階段條件的一部分使用。
  • 評估每次執行管線時遞增的數位。
  • 參數: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 自訂日期和時間格式規範進行日期格式設定(yyyy、、、dddMyyMMHHH、 ) mmmsssfffffffK
  • 範例:format('{0:yyyyMMdd}', pipeline.startTime)。 在此情況下 pipeline.startTime 是特殊的日期時間物件變數。
  • 藉由翻倍的大括號逃脫。 例如:format('literal left brace {{ and literal right brace }}')

ge

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

gt

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

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

length

  • 傳回字串或陣列的長度,可能是來自系統或來自參數的陣列。
  • 最小參數: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)

not

  • 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、短線路)

replace

  • 傳回新字串,其中目前實例中字串的所有實例都會以另一個字串取代
  • 最小參數: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 }}
    
  • 使用 split() 搭配 replace():
    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 為 。

succeeded

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

succeededOrFailed

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

  • 針對作業:

    • 沒有任何自變數,不論相依性圖表中的任何作業都成功或失敗,都會評估 True 為 。
    • 使用作業名稱做為自變數,評估 True 這些作業是否成功或失敗。
    • 當相依性圖表中有先前略過的作業時,您可能會想要改用 not(canceled())

    這就像 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 執行。 在這裡,條件中的 elseiffoo會傳回 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

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

相依性語法概觀

參考具有相依性之輸出變數的語法會根據情況而有所不同。 以下是最常見案例的概觀。 有時替代語法也有效。

型別

說明

階段到階段相依性 (不同階段)

參考 中條件中不同階段中作業中上一個階段的 stages輸出變數。

  • 語法: and(succeeded(), eq(stageDependencies.<stage-name>.outputs['<job-name>.<step-name>.<variable-name>'], 'true'))
  • 範例: and(succeeded(), eq(stageDependencies.A.outputs['A1.printvar.shouldrun'], 'true'))

作業對作業相依性 (相同階段)

參考 相同階段中不同作業中的 stages輸出變數。

  • 語法: and(succeeded(), eq(dependencies.<job-name>.outputs['<step-name>.<variable-name>'], 'true'))
  • 範例: and(succeeded(), eq(dependencies.A.outputs['printvar.shouldrun'], 'true'))

作業對階段相依性 (不同階段)

參考 中不同階段的 job輸出變數。

  • 語法: eq(stageDependencies.<stage-name>.<job-name>.outputs['<step-name>.<variable-name>'], 'true')
  • 範例: eq(stageDependencies.A.A1.outputs['printvar.shouldrun'], 'true')

階段至暫存相依性 (部署作業)

在不同的階段中參考部署作業中的 stages輸出變數。

  • 語法: eq(dependencies.<stage-name>.outputs['<deployment-job-name>.<deployment-job-name>.<step-name>.<variable-name>'], 'true')
  • 範例: eq(dependencies.build.outputs['build_job.build_job.setRunTests.runTests'], 'true')

階段至暫存相依性 (含資源的部署作業)

參考部署作業中的輸出變數,其中包含 中不同階段中的 stages資源。

  • 語法: eq(dependencies.<stage-name>.outputs['<deployment-job-name>.<Deploy_resource-name>.<step-name>.<variable-name>'], 'true')
  • 範例: eq(dependencies.build.outputs['build_job.Deploy_winVM.setRunTests.runTests'], 'true')

根據部署策略,部署作業中的輸出變數也有不同的語法。 如需詳細資訊,請參閱 部署作業

階段至階段相依性

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

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

注意

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

使用此形式的 dependencies 來對應變數或階段層級的檢查條件。

在此範例中,有兩個階段:A 和 B。階段 A 有 條件 false ,因此永遠不會執行。 如果階段 A 的結果為 SucceededSucceededWithIssuesSkipped,則執行階段 B。 階段 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

階段也可以使用另一個階段的輸出變數。 在此範例中,也有兩個階段。 階段 A 包含將輸出變數 shouldrun 設定為 true的作業 A1。 當 為 trueshouldrun,會執行階段 B。 因為 shouldruntrue,因此會執行階段 B。

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)。 作業 a 一律會因為 而 condition: false略過。 作業 b 會執行,因為沒有任何相關聯的條件。 作業 c 會執行,因為其所有相依性都成功 (作業 b) 或已略過 (作業 a)。

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 輸出變數的值,以判斷它是否應該執行。

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

如果作業相依於部署作業在不同的階段所定義的變數,則語法會不同。 在下列範例中,如果部署作業設定runTeststrue,則作業run_testsbuild_job執行。 請注意,用於字典的 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:
        ...

部署作業輸出變數

如果階段相依於部署作業在不同階段中定義的變數,則語法會不同。 在下列範例中,階段test取決於的true部署build_job設定shouldTest。 請注意,在 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:
    - job: A
      steps:
        - script: echo Hello from job A

在上述範例中,條件會參考環境,而不是環境資源。 若要參考環境資源,您必須將環境資源名稱新增至相依性條件。 在下列範例中,條件會參考名為 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:
  - job: A
    steps:
     - script: echo Hello from job A

篩選的陣列

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

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

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

我們可以執行下列動作:

foo.*.id

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

這會傳回:

[ 1, 2, 3 ]

類型轉型

表達式中的值可能會從某個類型轉換成另一個類型,因為表達式會進行評估。 評估表達式時,參數會聯合至相關的數據類型,然後重新轉換成字串。

例如,在此 YAML 中,值TrueFalse 會轉換成 ,並在0評估表示式時轉換為 1 和 。 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 布林值 Null 數字 String 版本
布林值 - - Yes Yes -
Null Yes - .是 Yes -
Number Yes - - Yes 部分
String Yes 部分 Partial - Partial
版本 Yes - - Yes -

布林值

要編號:

  • 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 並使用 $minor task.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)"