Ausführen von plattformübergreifenden Skripts

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

Mit Azure-Pipelines können Sie Ihre Builds auf macOS-, Linux- und Windows-Computern ausführen. Wenn Sie plattformübergreifende Technologien wie .NET Core, Node.js und Python entwickeln, bringen diese Funktionen sowohl Vorteile als auch Herausforderungen.

Die meisten Pipelines enthalten beispielsweise mindestens ein Skript, das Sie während des Buildvorgangs ausführen möchten. Skripts werden jedoch häufig nicht auf unterschiedliche Plattformen ausgeführt. Nachfolgend finden Sie einige Tipps zum Behandeln dieser Herausforderung.

Ausführen von plattformübergreifenden Tools mit einem Skriptschritt

Das Skriptwort ist eine Verknüpfung für die Befehlszeilenaufgabe. Das script Schlüsselwort führt Bash unter Linux und macOS und cmd.exe unter Windows aus.

Die Verwendung script kann nützlich sein, wenn Ihre Aufgabe nur Argumente an ein plattformübergreifendes Tool übergeben. Das Aufrufen npm mit einem Satz von Argumenten kann beispielsweise mit einem script Schritt problemlos erreicht werden. script wird in jedem systemeigenen Skript-Dolmetscher der einzelnen Plattform ausgeführt: Bash auf macOS und Linux, cmd.exe unter Windows.

steps:
- script: |
    npm install
    npm test

Behandeln von Umgebungsvariablen

Umgebungsvariablen werfen die ersten Falten in das Schreiben plattformübergreifender Skripts. Befehlszeile, PowerShell und Bash verfügen jeweils über verschiedene Methoden zum Lesen von Umgebungsvariablen. Wenn Sie auf einen vom Betriebssystem bereitgestellten Wert wie PATH zugreifen müssen, benötigen Sie verschiedene Techniken pro Plattform.

Azure Pipelines bietet jedoch eine plattformübergreifende Möglichkeit, auf Variablen zu verweisen, die sie über die benannte Makrosyntax weiß. Durch die Umgebung eines Variablennamens in $( )wird es erweitert, bevor die Shell der Plattform es jemals sieht. Wenn Sie beispielsweise die ID der Pipeline echoen möchten, ist das folgende Skript plattformübergreifend:

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

Dies funktioniert auch für Variablen, die Sie in der Pipeline angeben.

variables:
  Example: 'myValue'

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

Berücksichtigen von Bash oder pwsh

Wenn Sie komplexere Skriptanforderungen haben als die oben gezeigten Beispiele, sollten Sie sie in Bash schreiben. Die meisten macOS- und Linux-Agents verfügen über Bash als verfügbare Shell, und Windows-Agents enthalten Git Bash oder Windows-Subsystem für Linux Bash.

Für Azure-Pipelines verfügen die von Microsoft gehosteten Agents immer über Bash.

Wenn Sie beispielsweise eine Entscheidung darüber treffen müssen, ob Ihr Build durch eine Pullanforderung ausgelöst wird:

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) ist auch eine Option. Es erfordert, dass jeder Agent PowerShell Core installiert hat.

Auf Basis der Plattform wechseln

Im Allgemeinen empfiehlt es sich, plattformspezifische Skripts zu vermeiden, um Probleme wie die Duplizierung Ihrer Pipelinelogik zu vermeiden. Die Duplizierung verursacht zusätzliche Arbeit und zusätzliches Risiko von Fehlern. Wenn es jedoch keine Möglichkeit gibt, plattformspezifische Skripts zu vermeiden, können Sie eine condition verwenden, um zu erkennen, welche Plattform Sie verwenden.

Angenommen, Sie benötigen aus irgendeinem Grund die IP-Adresse des Build-Agents. Ruft unter Windows ipconfig diese Informationen ab. Auf macOS ist ifconfiges . Und auf Ubuntu Linux ist ip addres .

Richten Sie die folgende Pipeline ein, und versuchen Sie dann, sie auf verschiedenen Plattformen für Agents auszuführen.

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)