Ausführen plattformübergreifender Skripts

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

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

Die meisten Pipelines enthalten z. B. mindestens ein Skript, das während des Buildprozesses ausgeführt werden soll. Skripts werden jedoch häufig nicht auf unterschiedlichen Plattformen auf die gleiche Weise ausgeführt. Sie können die script Verknüpfung Schlüsselwort verwenden, um das Schreiben von Skripts zu vereinfachen und auch Bedingungen für bestimmte Plattformen mit Ihren Skripts zu verwenden.

Ausführen plattformübergreifender Tools mit einem Skriptschritt

Das Skriptschlüsselwort 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 von script kann nützlich sein, wenn Ihre Aufgabe ausschließlich Argumente an ein plattformübergreifendes Tool übergibt. Das Aufrufen von npm mit einer Reihe von Argumenten kann z. B. mit einem script-Schritt problemlos durchgeführt werden. script wird im nativen Skriptinterpreter jeder Plattform ausgeführt: Bash unter macOS und Linux, cmd.exe unter Windows.

steps:
- script: |
    npm install
    npm test

Verwenden von Umgebungsvariablen

Umgebungsvariablen sind der erste Knackpunkt beim Schreiben plattformübergreifender Skripts. Befehlszeile, PowerShell und Bash verfügen jeweils über unterschiedliche Methoden zum Lesen von Umgebungsvariablen. Wenn Sie auf einen vom Betriebssystem bereitgestellten Wert wie PATH zugreifen müssen, gibt es je nach Plattform unterschiedliche Methoden.

Azure Pipelines bietet jedoch eine plattformübergreifende Möglichkeit, auf Variablen zu verweisen, die es über die sogenannte Makrosyntax erkennt. Indem sie einen Variablennamen in $( ) umgibt, wird sie erweitert, bevor die Shell der Plattform diesen überhaupt sieht. Wenn Sie beispielsweise die ID der Pipeline echoen möchten, ist das folgende Skript plattformübergreifend geeignet:

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 Anforderungen an die Skripterstellung haben als die oben gezeigten Beispiele, sollten Sie es in Bash schreiben. Die meisten macOS- und Linux-Agents bieten Bash als verfügbare Shell, und Windows-Agents enthalten Git Bash oder den Windows-Subsystem für Linux-Bash.

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

Wenn Sie z. B. eine Entscheidung darüber treffen müssen, ob Ihr Build durch eine Pull Request ausgelöst wird:

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 Core (pwsh) ist auch eine Option. Es erfordert, dass für jeden Agent PowerShell Core installiert ist.

Wechseln je nach Plattform

Allgemein wird empfohlen, plattformspezifische Skripts zu vermeiden, um Probleme wie die Duplizierung Ihrer Pipelinelogik zu vermeiden. Duplizierung verursacht zusätzliche Arbeit und erhöht das Fehlerrisiko. Wenn es jedoch keine Möglichkeit gibt, plattformspezifische Skripts zu vermeiden, können Sie ein condition-Element verwenden, um zu erkennen, auf welcher Plattform Sie sich befinden.

Angenommen, Sie benötigen aus irgendeinem Grund die IP-Adresse des Build-Agents. Unter Windows ruft ipconfig diese Informationen ab. Unter macOS ist es ifconfig. Und unter Ubuntu Linux ist dies ip addr.

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

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)