跨平台脚本

Azure DevOps Services |Azure DevOps Server |Azure DevOps Server 2022 |Azure DevOps Server 2020

Azure Pipelines 可以在 Linux、macOS 和 Windows 计算机上运行管道。 如果使用 .NET Core、Node.js或 Python 等跨平台开发技术,这些跨平台生成功能将带来优势和挑战。 例如,大多数管道都包含在生成过程中运行的一个或多个脚本,但脚本语法通常因平台而异。

本文介绍如何使用跨平台脚本来支持不同的生成平台。 可以使用 Azure Pipelines script 步骤轻松编写跨平台脚本。 还可以使用 条件 将脚本定向到特定平台。

脚本步骤

脚本关键字是命令行任务的快捷方式,该任务在 Linux 和 macOS 上运行 Bash 或在 Windows 上运行 cmd.exe。

可用于 script 将参数轻松传递到跨平台工具。 该 script 步骤在每个平台的本机脚本解释器、macOS 和 Linux 上的 Bash 或 Windows 上的 cmd.exe 中运行。 以下示例使用一个 script 步骤来调用 npm 一组参数。

steps:
- script: |
    npm install
    npm test

环境变量

命令行、PowerShell 和 Bash 以不同的方式解析 环境变量 。 若要访问系统提供的值(如 PATH),必须为每个平台使用不同的语法。

Azure Pipelines 使用 宏语法 作为跨平台方式来引用运行时的变量。 采用宏语法的变量在运行时进行处理(执行任务之前)。 变量在平台 shell 遇到它之前展开。

若要在管道中使用宏语法,请将变量名称括起来,如下所示: $(<variable name>) 以下跨平台示例脚本输出管道的 ID。

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

此语法也适用于在管道中定义的变量。

variables:
  Example: 'myValue'

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

Bash 任务

如果需要更复杂的脚本,请考虑在 Bash 中编写它们,并在管道中使用 Bash 任务 。 大多数 macOS 和 Linux 代理使用 Bash 作为 shell,Windows 代理可以使用适用于 Linux Bash 的 Git Bash 或 Windows 子系统默认情况下,Microsoft托管代理 已预安装 Bash。

以下示例运行一个 Bash 脚本任务,该任务有助于决定是否触发构建。

trigger:
    batch: true
    branches:
        include:
        - main
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 也是脚本的选项。 快捷方式 pwsh 在 macOS、Linux 或 Windows 上运行 PowerShell 7.x。 代理必须安装 PowerShell 7.x。 默认情况下,Microsoft托管代理 已安装 PowerShell 7.x。

基于平台的切换

特定于平台的脚本重复管道逻辑会导致额外的工作和增加错误风险。 但是,如果无法避免特定于平台的脚本,则可以使用 条件 来检测你正在使用的平台。

例如,若要获取生成代理的 IP 地址,必须在 macOS 上使用 ifconfig,在 Ubuntu Linux 上使用 ip addr,在 Windows PowerShell 上使用 Get-NetIPAddress 这个 cmdlet。 以下管道通过设定条件从不同平台上的代理获取信息。

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

# use the value
- script: |
    echo The IP address is $(IP_ADDR)