Executar scripts multiplataforma

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

Com o Azure Pipelines, você pode executar os builds em computadores macOS, Linux e Windows. Se você desenvolver tecnologias multiplataforma, como .NET Core, Node.js e Python, essas funcionalidades trarão benefícios e desafios.

Por exemplo, a maioria dos pipelines inclui um ou mais scripts que você deseja executar durante o processo de build. Mas os scripts geralmente não são executados da mesma maneira em plataformas diferentes. Você pode usar o atalho de palavra-chave script para facilitar a escrita de scripts e também pode usar condições para direcionar plataformas específicas com seus scripts.

Executar ferramentas multiplataforma com uma etapa de script

A palavra-chave de script é um atalho para a tarefa de linha de comando. A palavra-chave script executa Bash no Linux e macOS e cmd.exe no Windows.

Usar script pode ser útil quando sua tarefa apenas passa argumentos para uma ferramenta multiplataforma. Por exemplo, chamar npm com um conjunto de argumentos pode ser facilmente realizado com uma etapa script. script é executado no interpretador de script nativo de cada plataforma: Bash no macOS e Linux, cmd.exe no Windows.

steps:
- script: |
    npm install
    npm test

Lidar com variáveis de ambiente

As variáveis de ambiente lançam o primeiro obstáculo na gravação de scripts multiplataforma. Linha de comando, PowerShell e Bash têm maneiras diferentes de ler variáveis de ambiente. Se você tiver que acessar um valor fornecido pelo sistema operacional, como PATH, precisará de técnicas diferentes por plataforma.

No entanto, o Azure Pipelines oferece uma maneira multiplataforma de se referir a variáveis conhecidas chamadas de sintaxe de macro. Ao envolver um nome de variável em $( ), ele é expandido antes que o shell da plataforma o veja. Por exemplo, se você quiser ecoar a ID do pipeline, o script a seguir é compatível com várias plataformas:

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

Isso também funciona para variáveis especificadas no pipeline.

variables:
  Example: 'myValue'

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

Considerar Bash ou pwsh

Se você tiver necessidades de script mais complexas do que os exemplos mostrados acima, considere escrevê-las no Bash. A maioria dos agentes macOS e Linux tem Bash como um shell disponível, e os agentes Windows incluem o Git Bash ou Subsistema do Windows para Linux Bash.

Para o Azure Pipelines, os agentes hospedados pela Microsoft sempre têm o Bash disponível.

Por exemplo, se você precisar tomar uma decisão sobre se sua compilação será acionada por uma solicitação de pull:

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

O PowerShell Core (pwsh) também é uma opção. Ele requer que cada agente tenha o PowerShell Core instalado.

Alternar com base na plataforma

Em geral, recomendamos que você evite scripts específicos da plataforma para evitar problemas como a duplicação da lógica do pipeline. A duplicação gera trabalho extra e risco extra de bugs. No entanto, se não houver como evitar scripts específicos da plataforma, você poderá usar um condition para detectar em qual plataforma você está.

Por exemplo, suponha que, por algum motivo, você precise do endereço IP do agente de build. No Windows, ipconfig obtém essas informações. No macOS, é ifconfig. E no Ubuntu Linux, é ip addr.

Configure o pipeline abaixo e tente executá-lo em agentes em diferentes plataformas.

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)