執行跨平臺腳本

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

使用 Azure Pipelines,您可以在 macOS、Linux 和 Windows 機器上執行組建。 如果您在 .NET Core、Node.js和 Python 等跨平臺技術上進行開發,這些功能會帶來優點和挑戰。

例如,大部分的管線都包含一或多個您想要在建置程式期間執行的腳本。 但腳本通常不會在不同的平臺上以相同方式執行。 以下是如何處理這類挑戰的一些秘訣。

使用腳本步驟執行跨平臺工具

script 關鍵字是 命令列工作的快捷方式。 關鍵字會在 script Linux 和 macOS 上執行 Bash,並在 Windows 上cmd.exe。

當您的工作只將引數傳遞至跨平臺工具時,使用 script 可能會很有用。 例如,使用一組引數呼叫 npm 即可透過步驟輕鬆完成 scriptscript 在每個平臺的原生腳本解譯器中執行:macOS 和 Linux 上的 Bash,cmd.exe在 Windows 上執行。

steps:
- script: |
    npm install
    npm test

處理環境變數

環境變數會擲回第一個寫入跨平臺腳本的命令。 命令列、PowerShell 和 Bash 各有不同的讀取環境變數方式。 如果您需要存取 PATH 之類的作業系統提供值,則每個平臺都需要不同的技術。

不過,Azure Pipelines 提供跨平臺的方式來參考其知道稱為 宏語法的變數。 藉由圍繞 中的 $( ) 變數名稱,它會在平臺的殼層看到它之前展開。 例如,如果您想要回應管線的識別碼,下列腳本是跨平臺易記的:

steps:
- script: echo This is pipeline $(System.DefinitionId)

這也適用于您在管線中指定的變數。

variables:
  Example: 'myValue'

steps:
- script: echo The value passed in is $(Example)

考慮 Bash 或 pwsh

如果您有比上述範例更複雜的腳本需求,請考慮在 Bash 中撰寫這些腳本。 大部分的 macOS 和 Linux 代理程式都有 Bash 作為可用的殼層,而 Windows 代理套裝程式括 Git Bash 或Windows 子系統 Linux 版Bash。

針對 Azure Pipelines,Microsoft 裝載的代理程式一律有 Bash 可用。

例如,如果您需要決定組建是否由提取要求觸發:

trigger:
    batch: true
    branches:
        include:
        - master
steps:
- bash: |
    echo "Hello world from $AGENT_NAME running on $AGENT_OS"
    case $BUILD_REASON in
            "Manual") echo "$BUILD_REQUESTEDFOR manually queued the build." ;;
            "IndividualCI") echo "This is a CI build for $BUILD_REQUESTEDFOR." ;;
            "BatchedCI") echo "This is a batched CI build for $BUILD_REQUESTEDFOR." ;;
        *) $BUILD_REASON ;;
    esac
  displayName: Hello world

PowerShell Core (pwsh) 也是一個選項。 它要求每個代理程式都已安裝 PowerShell Core。

根據平臺切換

一般而言,建議您避免平臺特定的腳本,以避免發生管線邏輯重複之類的問題。 重複會導致額外的工作和額外的 Bug 風險。 不過,如果沒有任何方法可以避免平臺特定的腳本,您可以使用 condition 來偵測您目前使用的平臺。

例如,假設基於某些原因,您需要組建代理程式的 IP 位址。 在 Windows 上, ipconfig 取得該資訊。 在 macOS 上 ifconfig ,它是 。 在 Ubuntu Linux 上,它是 ip addr

設定下列管線,然後嘗試在不同的平臺上對代理程式執行。

steps:
# Linux
- bash: |
    export IPADDR=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/')
    echo "##vso[task.setvariable variable=IP_ADDR]$IPADDR"
  condition: eq( variables['Agent.OS'], 'Linux' )
  displayName: Get IP on Linux
# macOS
- bash: |
    export IPADDR=$(ifconfig | grep 'en0' -A3 | grep inet | tail -n1 | awk '{print $2}')
    echo "##vso[task.setvariable variable=IP_ADDR]$IPADDR"
  condition: eq( variables['Agent.OS'], 'Darwin' )
  displayName: Get IP on macOS
# Windows
- powershell: |
    Set-Variable -Name IPADDR -Value ((Get-NetIPAddress | ?{ $_.AddressFamily -eq "IPv4" -and !($_.IPAddress -match "169") -and !($_.IPaddress -match "127") } | Select-Object -First 1).IPAddress)
    Write-Host "##vso[task.setvariable variable=IP_ADDR]$IPADDR"
  condition: eq( variables['Agent.OS'], 'Windows_NT' )
  displayName: Get IP on Windows

# now we use the value, no matter where we got it
- script: |
    echo The IP address is $(IP_ADDR)