Continuous Delivery mit Azure DevOps, Teil 3: Ausrollen per Geisterhand

Seite 3: Testen nicht vergessen

Inhaltsverzeichnis

Nun könnte man die Anwendung manuell auf dem Staging-System testen. Die Continuous-Delivery-Idee geht jedoch davon aus, dass vollautomatisch getestet wird. Abbildung 2 zeigt, dass nach dem Azure App Service Deployment nun noch zwei Arten von Tests ausgeführt werden:

  • Die bereits im zweiten Teil der Serie ausgeführten Unit-Tests kommen nochmals zum Einsatz, dieses Mal aber als Integrationstests gegen die nun existierende Datenbank. Hierbei sind nun keine Tests mehr auszuschließen.
  • Zudem werden mit dem Werkzeug Postman erstellte HTTP-Tests gegen das REST-API des MiracleList-Backends gefeuert.

Wie beim EFCTools-Werkzeug gilt, dass diese Artefakte auf dem Release-System verfügbar sein müssen. Dafür wird abermals die Build-Pipeline des Backends erweitert. Man könnte auch eine hier eigene Pipeline dafür erstellen, aber da sich meistens die Tests ändern, wenn sich der Programmcode ändert, ergibt es Sinn, eine Build Pipeline zu verwenden.

Die Unit-Tests werden wie EFCTools unverpackt in ein Ausgabeverzeichnis gelegt:

--output $(build.artifactstagingdirectory)/UnitTests

Die Postman-Tests sind kein Programmcode, sondern nur zwei JSON-Dateien: Eine definiert die Tests, die andere Umgebungsvariablen. Diese sind nur mit dem Task "Copy Files" zur Release-Pipeline durchzureichen (s. Abb. 4).

Erweiterte Build-Pipeline für das Backend (Abb. 4)

Die Release-Pipeline startet dann also vierte Aufgabe die Unit-Tests als Integrationstest gegen die echte Datenbank. Die dafür notwendige Verbindungszeichenfolge zu der SQL-Azure-Datenbank liegt ja schon in der Umgebungsvariablen.

Für die Ausführung der Postman-Tests auf dem Release-System benötigt man dort Newman, das Node.js-Kommandozeilenwerkzeug von Postman. Dazu wird erst Node.js 8.x installiert, dann Newman mit npm install -g newman. Vor dem Start von Newman läuft noch ein Task des Typs "Replace Tokens" [https://github.com/colindembovsky/cols-agent-tasks/tree/master/Tasks/ReplaceTokens]. Dieser sorgt dafür, dass in der Datei MiracleList-APITests.postman_environment.json die URL des Azure Web App Service aus der Staging-Umgebung gesetzt wird. Die Konfiguration ist hier:

Source Path = $(System.DefaultWorkingDirectory)/MiracleListBackend-CI/PostmanTests/
Target File Pattern = MiracleList-APITests.postman_environment.json
Token Regex = __(\w+)__

Den Aufbau der Datei APITests.postman_environment.json zeigt das folgende Listing:

{
"id": "cc10b4f4-0bed-7d54-87f5-4122f1aaf9cb",
"name": "Staging",
"values": [
{
"enabled": true,
"key": "servername",
"value": "__URL__",
"type": "text"
},
{
"enabled": true,
"key": "taskID",
"value": "",
"type": "text"
},
{
"enabled": true,
"key": "categoryID",
"value": "",
"type": "text"
}
],
"timestamp": 1518979100772,
"_postman_variable_scope": "environment",
"_postman_exported_at": "2018-02-18T18:38:27.354Z",
"_postman_exported_using": "Postman/5.5.2"
}

Hier wird dann der Platzhalter __URL__ durch eine Umgebungsvariable mit gleichem Namen ersetzt. Diese ist unter "Variables" zu definieren (s. Abb. 5).

Variablen mit Scope in der Release-Pipeline (Abb. 5)

Nun kann Newman auf Basis der durchgereichten beziehungsweise modifizierten JSON-Dateien starten:

newman run MiracleList-APITests.postman_collection.json -e MiracleList-APITests.postman_environment.json --disable-unicode --reporters cli,junit --reporter-junit-export TestResults/newman-run-report.xml

Wenn diese Release-Pipeline durchgelaufen ist, sollte die Software reif für die Produktion sein. Nun ergänzt man eine weitere Stage mit Namen "Produktion", die man durch Klonen der "Staging"-Stage gewinnen kann. Auszutauschen sind der Web App Service Name und die Verbindungszeichenfolge. Letztere ist in den Variablen abgelegt und steuert man durch die Spalte "Scope" (s. Abb. 5). Hier wählt man, ob die Variable für das ganze Release oder nur eine Stage gelten soll. Da die Stage "Produktion" ein Klon von "Staging" ist, werden hier also alle Tests nochmals ausgeführt.

Es stellt sich aber die Frage, was passiert, wenn die Tests zwar auf dem Staging-System erfolgreich waren, aber nun aus irgendeinem Grund in der Produktion fehlschlagen. Dann wäre eine fehlerhafte Anwendung in der Produktion. Um das zu vermeiden, gibt es in Azure Web Apps sogenannte Slots. Voraussetzung ist, dass man mindestens den Tarif "S1" bei Microsoft bucht. Damit kann man dann mehrere Slots einrichten, die jeweils eine eigene Subdomain bekommen. Wenn man einen Slot "Staging" einrichtet, ist er unter https://miraclelistbackend-produktion-staging.azurewebsites.net adressierbar. Den Hauptslot nennt Microsoft immer "Production". Er ist aber nicht unter https://miraclelistbackend-produktion-production.azurewebsites.net, sondern nur bei https://miraclelistbackend-produktion.azurewebsites.net erreichbar.

Der Trick ist nun, beim „Azure App Service Deploy“-Task diesen "Staging"-Slot des Produktionssystems anzugeben (s. Abb. 6) und dann die Tests gegen diesen Slot laufen zu lassen.

In der Stage "Produktion" erfolgt die Auslieferung in den "Staging"-Slot des Produktionssystems (Abb. 6).

Erst wenn die Tests erfolgreich waren, folgt in der Stage "Produktion" ein elfter Schritt, den es in dem Staging-System nicht gab: Der Slot "Staging" wird in den Slot "Production" überführt (s. Abb. 7).

Austausch zwischen den Slots "Staging" und "Produktion" (Abb. 7)

Abbildung 1 zeigt, wie die gewünschte manuelle Bestätigung für das Release auf die Produktionssystem aktiviert wird. Man kann einstellen, dass eine oder mehrere Personen einzeln oder gemeinschaftlich (ggf. in der genannten Reihenfolge) bestätigen müssen. Die Personen erhalten entsprechende E-Mails. Außerdem lässt sich eine Verfallszeit einstellen: Wenn das Release nicht binnen einiger Tage bestätigt wurde, wird es verworfen. Abbildung 8 zeigt einen laufenden Durchgang des Releases, der auf Bestätigung zum Deployment in die Produktion wartet.

Nach erfolgreichem Staging-Durchlauf wartet das Release nun auf die manuelle Bestätigung zur Auslieferung in die Produktion (Abb. 8).