Eine Zeile für die Cloud

Dr. Holger Schwichtenberg
2
Sep

Azure DevOps einfach per Kommandozeile steuern

Die Konfiguration und die Prozesse in Microsofts Clouddienst „Azure DevOps“ kann man auch per Kommandozeile statt per Klick-Orgien steuern. In diesem Artikel wird erklärt, wie es geht und was alles zu beachten ist.

Azure DevOps ist die Nachfolgemarke von Team Foundation Server (TFS) und Visual Studio Team Services (VSTS). Microsoft differenziert durch die Zusätze „Azure DevOps Server“ und „Azure DevOps Services“ zwischen der lokal installierbaren Version und der Cloudversion. Aktuelle Version des Servers ist 2019.0.1, siehe Release Notes. Das zum Redaktionsschluss aktuelle Release der Cloudvariante ist“ Sprint 154. Hierin findet man in den Release Notes den Eintrag „Azure DevOps CLI general availability“.

 

Von VSTS CLI zu Azure DevOps CLI

Die Steuerung von Azure DevOps per Kommandozeile (CLI, Command Line Interface) bietet sich für wiederkehrende Aufgaben oder Anwendungsintegration an. So könnte man zum Beispiel aus einer Monitoringsoftware heraus automatisch Bugs in Azure DevOps anlegen, wenn es zu Fehlern im laufenden Betrieb kommt. Per Kommandozeile lassen sich derzeit viele, aber nicht alle Funktionen von Azure DevOps steuern. Man kann zum Beispiel Projekte, Git Repositories, Pipelines, Work Items, Wikis, Banner sowie Teams, Gruppen und Benutzer anlegen und verwalten. Allerdings kann man keine Repositories mit Team Foundation Version Control (TFVC) damit administrieren. Auch das Hinzufügen von Benutzern zu Teams ist noch nicht im Angebot.
Das Azure DevOps CLI gibt es seit Februar 2019 als Preview, doch es ist nun am 8. Juli 2019 im Stadium „General Availability“ keineswegs fertig, wie der Beitrag noch aufzeigen wird. Es gab schon ein Vorgängerprodukt, das VSTS CLI, das trotz seines auf die Cloudvariante hindeutenden Namens auch mit dem lokalen TFS (ab Version 2017 Update 2) funktionierte.
Bei GitHub findet man noch einen Abzweig des alten Entwicklungsstands mit der Aussage „VSTS CLI is a new command line interface for Visual Studio Team Services (VSTS) and Team Foundation Server (TFS) 2017 Update 2 and later“. Diese Aussage ist jedoch veraltet; auf der echten Projektseite von Microsoft liest man dann auch klar: „The Azure CLI with the Azure DevOps Extension has replaced the VSTS CLI. The VSTS CLI has been deprecated and will no longer be receiving new features. We recommend that users of the VSTS CLI switch to the Azure CLI and add the Azure DevOps extension.“

 

Azure CLI als Grundlage

Während das VSTS CLI ein in Python implementiertes, eigenständiges Werkzeug (vsts, installiert in C:\Program Files (x86)\Microsoft SDKs\VSTS\CLI) war, ist das Azure DevOps CLI eine Erweiterung zum allgemeinen Azure CLI (az). Auch az ist in Python geschrieben und installiert sich im Standard in C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2. Die 2 am Ende dieses Dateipfads weist darauf hin, dass das Azure CLI die zweite Generation der Kommandozeilenwerkzeuge für Azure darstellt. Die erste Generation hatte als Befehlsnamen „azure“. Die zweite Version (az) wurde zunächst Azure CLI 2.0 genannt. Seit Juni 2018 differenziert Microsoft nun aber mit Azure CLI und Azure Classic CLI zwischen den beiden Produkten.
Für einen Nutzer, der Azure DevOps per Kommandozeile steuern möchte, bedeutet dies, dass er zuerst auf seiner Festplatte das aktuelle Azure CLI installieren muss. Die jeweils neueste Version erhält man unter [7]. Für Windows findet man dort einen MSI-Installer. Unter macOS ist eine Installation per homebrew (brew update && brew install azure-cli) vorgesehen. Für Linux-basierte Betriebssysteme kann man apt, yum, zypper oder eine manuelle Installation verwenden.
Zum Redaktionsschluss ist beim Azure CLI die Version 2.0.68 vom 3. Juli 2019 aktuell. Um die Azure-DevOps-Erweiterung für das Azure CLI nutzen zu können, ist mindestens Version 2.0.49 erforderlich. Der Benutzer kann die Kommandozeilenshell seiner Wahl verwenden. Unter Windows z. B. Windows PowerShell, PowerShell Core, die klassische Windows-Shell (cmd), das neue Windows Terminal oder die bash Shell im Windows-Subsystem für Linux (WSL). Hier soll PowerShell 7.0 Preview 1 zum Einsatz kommen, um die objektorientierte Pipeline nutzen und die Ergebnisse des Azure CLI weiterverarbeiten zu können. Ältere Varianten der PowerShell funktionieren aber gleichermaßen. Die meisten der hier vorgestellten Befehle funktionieren freilich auch ohne PowerShell Pipelines in der cmd oder bash.
Um die aktuelle Version des Azure CLI abzufragen, gibt man az –version ein und erhält dann eine lange Tabelle mit allen im Azure CLI installierten Befehlsmodule und den Erweiterungen. Falls man noch eine ältere Version des CLI verwendet, d. h. eine neuere vorliegt, wird man am Ende dieser Liste praktischerweise darauf hingewiesen.
Normalerweise zeigt diese Versionsausgabe keine Erweiterungen. Eine Erweiterung muss man erst explizit installieren. Dafür braucht man kein MSI-Paket mehr, denn dafür hat das Azure CLI den Befehl az extension add. Die Azure-DevOps-CLI-Erweiterung installiert man im Azure CLI mit:

az extension add --name azure-devops

Um nur die Liste der installierten Erweiterungen zu sehen, gibt man ein:

az extension list --output table

Zur Aktualisierung des Azure CLI führt man das aktuelle MSI-Paket von [9] aus. Hierdurch werden aber nicht die installierten Erweiterungen aktualisiert, man muss sie mit az extension update separat aktualisieren, z. B. folgendermaßen:

az extension update --name azure-devops

Die aktuelle Version der Azure-DevOps-CLI-Erweiterung, die bei Redaktionsschluss verfügbar ist, trägt die Versionsnummer 0.11.0. Beim modernen, agilen Microsoft bedeutet „Azure DevOps CLI general availability“ also keineswegs, dass ein Produkt die Versionsnummer 1.0 erreicht hat.

 

Weitverzweigte Hilfe

Hilfe zu den verfügbaren Befehlen bekommt man mit: az -h. Zu beachten ist, dass man wegen der Vielzahl der Befehle in dieser Hilfeausgabe nur Befehlsgruppen (z. B. ad, artifacts, boards, devops, iot, pipelines, repos, sql, storage, network, vm, webapp) zu sehen bekommt. In eine bestimmte Befehlsgruppe steigt man ein, indem man den Namen der Befehlsgruppe zusätzlich angibt: az pipelines -h.
Nun bekommt man eine kürzere Hilfeliste mit den Befehlen dieser Befehlsliste, wobei wieder unterschieden wird zwischen direkten Befehlen und Untergruppen (Abb. 1). Und auch hier bedeutet „General Availability“ also nicht, dass ein Produkt insgesamt fertig ist. Die meisten Befehlsgruppen des Azure DevOps CLI verweilen auch in der Preview, wie man in Abbildung 1 sieht.


Abb. 1: Hilfe zum Befehlsgebiet der Pipeline-Verwaltung mit „az pipelines -h“: Viele Befehle sind immer noch in der Preview

So sagt die Hilfeausgabe in Abbildung 1, dass man zur Auflistung aller definierten Pipelines eingeben kann: az pipelines list. Man kann aber auch noch mehr Hilfe anfordern zur Untergruppe agents mit: az pipelines agent -h. Dort sieht man, dass es auch auf dieser Ebene wieder einen Befehl list gibt, um die Liste der verfügbaren Pipeline-Agents zu erhalten: az pipelines agent list. Die Befehlsebene bringt feine Unterschiede zu Tage:

  • Mit az pipelines list listet man die Definitionen aller JSON-basierten Build Pipelines und der neueren YAML Pipelines.
  • Mit az pipelines build definition list erhält man nur die JSON-basierten Build Pipelines.
  • Mit az pipelines Release definition list werden die klassische Release-Pipelines geliefert.
  • Durch Eingabe von az login öffnet sich der Standardwebbrowser auf dem Computer und bietet eine interaktive Anmeldung.
  • Durch Eingabe von az devops login –organization https://dev.azure.com/OrganisationsName wird man an der Kommandozeile aufgefordert, ein Personal Access Token (PAT) einzugeben. Dies kann man im Azure-DevOps-Webportal erstellen. Das PAT kann dort hinsichtlich der Rechte beschränkt werden.
  • Alternativ kann man das PAT auch in einer Umgebungsvariable hinterlegen; damit vermeidet man jeden weiteren Anmeldevorgang:

$env:AZURE_DEVOPS_EXT_PAT = bjlhfo7evyvre5rsxhyhxy6…..tv6hklzrrl3ydwfan2k7d5awq"

Voreinstellungen

Wer mit mehreren Organisationen und Projekten arbeitet, wird beim Azure DevOps CLI immer wieder bei den einzelnen Befehlen die Organisation und den Projektnamen festlegen müssen:

az pipelines list --organization https://dev.azure.com/ITVDemo --project "MiracleList"

Dabei ist man bei –organization gezwungen, den ganze URL anzugeben. Eine Abkürzung der Parameternamen ist möglich, soweit noch eindeutig:

az pipelines list --org https://dev.azure.com/ITVDemo --p "MiracleList"

Man kann aber die Organisation nicht mit –o abkürzen, da es auch noch den Parameter –output gibt. Die ständige Wiederholung dieser allgemeinen Parameter kann man durch eine zentrale Vorgabe vermeiden:

az devops configure --organization https://dev.azure.com/ITVDemo --project "MiracleList"

Dadurch kann man im Folgenden verkürzt schreiben: az pipelines list

Verschaffen Sie sich den Zugang zur .NET- und Microsoft-Welt mit unserem kostenlosen Newsletter!

Ausgabeformate zur Wahl

Azure DevOps CLI liefert im Standard alle Ausgaben im JSON-Format. Dies ist zwar für Maschinen gut weiterzuverarbeiten, doch für Menschen nicht gut lesbar. Insgesamt stehen zur Verfügung:

  • json (einfarbige JSON-Ausgabe)
  • jsonc (mehrfarbige JSON-Ausgabe)
  • none (keine Ausgabe)
  • table (ASCII-Tabelle)
  • tsv (tabulatorgetrennt)
  • yaml (YAML)

Das Ausgabeformat kann man bei jedem einzelnen Azure-CLI-Befehl mit dem Parameter –output, abgekürzt mit -o,festlegen. Wie Abbildung 3 zeigt, beschränkt sich die Tabellenausgabe auf die wesentlichen Spalten.

Das Standardausgabeformat kann der Benutzer persistent in der Datei C:\Users\BenutzerName\.azure\config ändern (Listing 1). Diese Datei kann er auch interaktiv mit dem Befehl az configure bearbeiten.

[cloud]
name = AzureCloud
[core]
first_run = yes
output = table
collect_telemetry = no
cache_ttl = 10
[logging]
enable_log_file = no

 

Weiterverarbeitung der Ergebnisse

Als eingefleischter Liebhaber der objektorientierten Programmierung und des objektorientierten Pipelinings mit Objekten in der PowerShell fehlt dem Autor dieses Beitrags in der Liste der Ausgabeformate natürlich object. Man muss sich die Frage stellen, warum Microsoft zur Implementierung Python verwendet hat. C# oder Visual Basic .NET gibt es ja nun seit einiger Zeit auch plattformneutral, und diese Sprachen hätten den Vorteil gehabt, dass sie auch direkt .NET-Objekte für die PowerShell produzieren könnten. Wie so oft erleben wir auch hier, dass bei Microsoft leider viele technische Entscheidungen eher willkürlich in einzelnen Fachbereichen statt zentral und strategisch getroffen werden.
Die Azure DevOps-CLI-Befehle in der PowerShell auszuführen, lohnt sich dennoch, denn die PowerShell kann leicht JSON in .NET-Objekte verwandeln; dafür gibt es seit Windows PowerShell 3.0 das eingebaute Commandlet ConvertFrom-Json. Dieses Commandlet wandelt eine Zeichenkette im JSON-Format in .NET-Objekte um. Intuitiv würde man als PowerShell-Benutzer dann schreiben:

az pipelines list -o JSON | convertfrom-JSON | where-object { $_.name -notlike "*Backend*" } | sort-object name | format-table name, url

Allerdings wundert man sich, dass zwar die Tabellenausgabe mit den beiden gewünschten Spalten vorhanden ist, aber weder der Filter mit dem Commandlet where-object noch die Sortierung mit sort-object wirkt. Das liegt am Commandlet ConvertFrom-Json, bei dem das PowerShell-Entwicklerteam bei der Implementierung etwas verbockt hat. Wenn sich an der Wurzel der JSON-Datei ein Array befindet, legt das Commandlet das Array in die Pipeline. Üblicherweise entpacken aber Commandlets ein Array in Einzelobjekte. Microsoft hat das Problem leider bis heute nicht behoben>/a>. Die Umgehung dieses Problems ist, entweder Foreach-Object explizit in die Pipeline zu setzen:

az pipelines list -o JSON | convertfrom-JSON | foreach-object { $_} | where-object { $_.name -notlike "*Backend*" } | sort-object name | format-table name, url

oder den vorderen Teil zu klammern:

(az pipelines list -o JSON | convertfrom-JSON) | where-object { $_.name -notlike "*Backend*" } | sort-object name| format-table name, url

Work Items behandeln

Einige der Azure-DevOps-CLI-Befehle haben bereits eingebaute Filter, so kann man beispielsweise Work Items mit der SQL-ähnlichen Work Item Query Language (WIQL) aussortieren:

az boards query --wiql "SELECT System.ID, System.Title, System.WorkItemType, System.AreaPath, System.AssignedTo, System.State from workitems order by System.ID asc"

Mit PowerShell-Variablen kann man diesen Befehl natürlich auch in mehrere Zeilen aufteilen:

$wiql = "SELECT System.ID, System.Title, System.WorkItemType, System.AreaPath, System.AssignedTo, System.State from workitems order by System.ID asc"
az boards query --wiql $wiql

Ebenso ist es möglich, WIQL-Filter und das Filtern mit Where-Object in der PowerShell zu kombinieren. Der folgende Befehl filtert erst alle an einen Benutzer zugewiesenen Work Items, die nicht erledigt sind. Dann erfolgt in der PowerShell Pipeline ein weiterer Filter auf das Wort „Angular“ im Titel:

$wiql = "SELECT System.ID, System.Title, System.AssignedTo, System.State from workitems WHERE [System.AssignedTo] = 'hs@IT-Visions.de' and state <> 'Done' order by System.ID asc"
(az boards query --wiql $wiql -o json | convertfrom-JSON).fields | where-object { $_."System.Title" -like "*Angular*" } | format-table "System.ID", "System.Title"

Der explizite Zugriff .fields ist hier notwendig, da die JSON-Struktur, die das Azure CLI liefert, etwas komplexer ist. An der Wurzel ist ein Array von Objekten. Die Objekte enthalten die Eigenschaften des Work Items aber nicht direkt, sondern ein Unterobjekt „fields“ (Listing 2).

[
  {
    "fields": {
      "System.AssignedTo": {
        "_links": {
          "avatar": {
            "href": "https://nlhsdemo.visualstudio.com/_apis/GraphProfile/MemberAvatars/msa.N2NlNTFmMWYtODBhYy03MzVlLThmOWEtY2FhNzgyNjAzNGQz"
          }
        },
        "descriptor": "msa.N2NlNTFmMWYtODBhYy03MzVlLThmOWEtY2FhNzgyNjAzNGQz",
        "displayName": "Dr. Holger Schwichtenberg",
        "id": "0a31ed99-da1e-4412-913b-5da20050c88f",
        "imageUrl": "https://nlhsdemo.visualstudio.com/_apis/GraphProfile/MemberAvatars/msa.N2NlNTFmMWYtODBhYy03MzVlLThmOWEtY2FhNzgyNjAzNGQz",
        "uniqueName": "hs@IT-Visions.de",
        "url": "https://spsprodcus1.vssps.visualstudio.com/A7fbad96a-dc90-4656-af24-f37c38c5694b/_apis/Identities/0a31ed99-da1e-4412-913b-5da20050c88f"
      },
      "System.Id": 18,
      "System.State": "New",
      "System.Title": "Sicherheit verbessern: Secrets, z.B. im ConnectStrings, müssen verschlüsselt gespeichert werden"
    },
    "id": 18,
    "relations": null,
    "rev": 5,
    "url": "https://itvdemo.visualstudio.com/_apis/wit/workItems/18"
  },
…
]

Außerdem ist bei dem PowerShell-Befehl zu beachten, dass die WorkItem-Eigenschaftennamen in Anführungszeichen stehen müssen, falls sie Punkte enthalten (wie z. B. bei System.State und Microsoft.VSTS.Common.Severity). Den Punkt interpretiert die PowerShell genauso wie andere objektorientierte Sprachen als Trennzeichen zwischen Objekt und Eigenschaft. Hier Punkte im Namen zu verwenden, war nicht sehr weise von Microsoft.
Die Namen der Work-Item-Eigenschaften für die Prozesse Scrum und Agile findet man auf dem Azure-DevOps-Spickzettel, der dieser Ausgabe beiliegt. Vielfach findet man hier noch VSTS im Namen; hier wird Microsoft den alten Namen nicht loswerden, außer man riskiert Breaking Changes oder implementiert Aliase.

 

Praxisbeispiele

Zum Abschluss noch einige schöne Praxisbeispiele zum Einsatz des Azure DevOps CLI. Das erste Beispiel zeigt das Anlegen eines Work Items mit mehreren Eigenschaften (Listing 3). Von az boards work-item create wird eine JSON-Ausgabe angefordert, die mit Hilfe der PowerShell ausgewertet wird. Hier ist eine Klammer um ConvertFrom-Json nicht notwendig, denn der Azure-DevOps-CLI-Befehl liefert nur ein einzelnes Objekt, keine Menge. In dem Befehl fällt zudem auf, dass man einige wenige Eigenschaften direkt setzen kann über Parameter des CLI-Befehls; die meisten Eigenschaften kann man jedoch nur über den generischen Parameter –fields setzen. Auf –fields folgt eine Liste von durch ein Gleichheitszeichen getrennten Name-Wert-Paaren:

$wi = (az boards work-item create --type Bug --title "Absturz bei der Eingabe von 0 im Feld Preis" --description "Die Spalte Preis erlaubt nicht die Zahl 0!" --discussion "Das hatte ich in der letzten Version schon festgestellt!" --field "Microsoft.VSTS.TCM.ReproSteps=

  1. Maske ‚Rechnung‘ öffnen
  2. neue Rechnung
  3. Klick in Rechnungsposition, Spalte Preis
  4. 0 eingeben

“ „Microsoft.VSTS.Common.AcceptanceCriteria=

Die Eingabe 0 muss zu einer Warnmeldung beim Benutzer führen

“ „Microsoft.VSTS.TCM.SystemInfo=Windows 10 v1903“ –assigned-to „hs@IT-Visions.de“ -o json)
$workItemID = ($wi | ConvertFrom-Json).ID

Das zweite Beispiel zeigt die Änderung eines Work Items:

az boards work-item update --id 30 --field "Microsoft.VSTS.TCM.SystemInfo=Windows 10 v1903" "Microsoft.VSTS.Common.Priority=1" "Microsoft.VSTS.Common.Severity=2 - High"

Das dritte Beispiel zeigt die Zuordnung zwischen zwei Work Items:

az boards work-item relation add --id 21 --target-id 24 --relation-type "Tests"

Eine Liste aller möglichen Zuordnungstypen in einem Projekt erhält man mit:

az boards work-item relation list-type

Zum Schluss noch das Starten einer Build Pipeline:

az pipelines build queue --definition-name MiracleListAngularClientBuild

Weitere sinnvolle Anwendungen des Azure DevOps CLI finden Sie auf dem dieser Ausgabe des Windows Developer beiliegenden Spickzettel.

Azure-DevOps-Spickzettel


Der Azure-DevOps-Spickzettel von Dr. Holger Schwichtenberg zeigt Ihnen kurz und knapp, wie Sie mit wenigen Befehlen das Kommando über Azure DevOps übernehmen können.
 
 
Download for free

Ihr aktueller Zugang zur .NET- und Microsoft-Welt.
Der BASTA! Newsletter:

Behind the Tracks

.NET Framework & C#
Visual Studio, TFS, C# & mehr

Agile & DevOps
Best Practices & mehr

Web Development
Alle Wege führen ins Web

Data Access & Storage
Alles rund um´s Thema Data

HTML5 & JavaScript
Leichtegewichtig entwickeln

User Interface
Alles rund um UI- und UX-Aspekte

Microservices & APIs
Services, die sich über APIs via REST und JavaScript nutzen lassen

Security
Tools und Methoden für sicherere Applikationen

Cloud, Azure, Serverless
Cloud-basierte & Native Apps