﻿# 如何從 Azure Pipelines 的 Task 設定一個變數給下一個 Task 使用

在 Azure Pipelines 中，如果想將某個 Task 執行過程中產生的資訊傳遞到下一個 Task 使用，原來只要在 STDOUT 輸出一段特殊的語法就可以辦到，非常的簡單好上手。本篇文章將分享 Auzre Pipelines 變數的相關資訊。

### 命名限制

變數名稱只能包含以下字元：

-   英文字母 (`A-Za-z`)
-   小數點 (`.`)
-   數字 (`0-9`)
-   底線 (`_`)

另外，在 Azure Pipelines 有些內建的變數**前置詞**(Prefix)你一定不能使用，否則會被自動忽略：

-   `endpoint`
-   `input`
-   `secret`
-   `securefile`

### 變數語法

Azure Pipelines 支援三種變數類型：

-   巨集變數 (macro)
    -   `$(var)`
    -   執行時期才會展開變數
    -   如果找不到變數時，會直接輸出 `$(var)`，不會替換成**空字串**喔！
-   範本變數表達式 (template expression)
    -   `${{ variables.var }}`
    -   編譯時期就會展開變數
    -   如果找不到變數時，會直接輸出**空字串**！
-   執行變數表達式 (runtime expression)
    -   `$[variables.var]`
    -   執行時期才會展開變數
    -   如果找不到變數時，會直接輸出**空字串**！

所有變數宣告的同時，也會自動注入到執行時期的「環境變數」中，但是**變數名稱**會全部轉大寫，所有**小數點**也會轉成**底線**(`_`)。例如：變數 `foo.bar` 可以從 `FOO_BAR` 環境變數中取值，但不同的 Shell 環境語法都不同：

-   PowerShell: `$env:FOO_BAR`
-   批次檔命令: `%FOO_BAR%`
-   Bash 命令: `$FOO_BAR`

### 在不同 Task 之間傳遞變數

在 Azure Pipelines 中所有的 Tasks 一定是由上到下依序執行，如果想在不同的 Task 傳遞變數，一定是上面的 Task 先設定好變數，然後才能往下傳。而 Azure Pipelines 有兩種方式可以傳遞參數：

1.  透過特定 Task 內建的傳遞變數
    
    Azure Pipelines 大部分 Tasks 其實都是沒有變數的，下圖我以內建的 Shell Exec 工作來說明，這個 Task 並沒有內建變數，所以就算你設定了 `Reference name` 欄位也沒用，之後的 Task 一樣沒辦法取得任何資訊。
    
    ![2020-02-08\_13-33-09](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/2c605ab060337deb37e2-74079908-9dab4680-4a78-11ea-8e82-fc948a7f3fec.jpg)
    
    我以 [Azure App Service deploy](https://github.com/microsoft/azure-pipelines-tasks/blob/master/Tasks/AzureRmWebAppDeploymentV4/README.md) (`v4`) 工作為例，如果有變數的話，你只要在 `Output Variables` 裡面設定 `Reference name` 起來，下方就會提示你之後的 Task 可以用哪些變數。以下圖為例，之後的 Task 就可以利用 `$(Azure.AppServiceApplicationUrl)` 取得這個工作產生的變數值。
    
    ![2020-02-08\_13-38-08](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/dde204a129a3a62e3752-74079892-5ae96e80-4a78-11ea-85d2-f0aad04851ae.jpg)
    
2.  透過 Task 的輸出結果設定變數
    
    如果你想在 Shell script / PowerShell / 批次檔 執行中將某些值傳到之後的 Task 中，可以很簡單的透過 `echo` 輸出一些特殊字串，就可以告訴 Azure Pipelines 設定一些變數給之後的 Task 使用。
    
    我們以 Shell 命令為例，底下語法可以自動設定一個新變數 `myname` 並將其值設定為 `Will`，接下來的 Task 就可以利用 `$(myname)` 來取得變數值(`Will`)，真的非常簡單易用！👍
    
    ```bash
    echo ##vso[task.setvariable variable=myname]Will
    ```
    
    如果你想設定一個「**安全變數**」的話，以下我改用**批次檔**來示範，語法幾乎一樣，多加上 `issecret=true` 即可：
    
    ```bash
    @echo ##vso[task.setvariable variable=secret.pw;issecret=true]12345678
    ```
    
    設定好之後，就可以利用 `$(secret.pw)` 來取得字串(`12345678`)，如果這段字串會輸出到 Azure Pipelines 的紀錄中的話，就會自動替換成 `********` 隱碼處理。
    

### 相關連結

-   Azure Pipelines | Microsoft Docs
    -   [Logging commands](https://learn.microsoft.com/zh-tw/azure/devops/pipelines/scripts/logging-commands)
    -   [Predefined variables](https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml)
    -   [Define variables](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#use-output-variables-from-tasks)
    -   [Expressions](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops)
-   [How to pass variables in Azure Pipelines YAML tasks](https://medium.com/microsoftazure/how-to-pass-variables-in-azure-pipelines-yaml-tasks-5c81c5d31763)
