September 28, 2024

Automatisierte Deployment Slots in Azure mit GitHub Actions: Pull Requests in Live-Umgebungen testen

Continuous Integration und Continuous Deployment (CI/CD) gehören in vielen Unternehmen bereits zum Standard. Dennoch suchen Entwicklungsteams ständig nach Wegen, um noch effizienter zu arbeiten und sicherzustellen, dass der Code in einer realitätsnahen Umgebung getestet wird, bevor er live geht. Die Möglichkeit, Pull Requests (PRs) direkt in einer „Live“-ähnlichen Umgebung zu testen, kann die Codequalität erheblich verbessern und Fehler frühzeitig erkennen lassen.

Azure Deployment Slots bieten hierfür eine elegante Lösung, indem sie isolierte Testumgebungen schaffen. In Kombination mit GitHub Actions kannst du PRs automatisch in diesen Slots deployen und testen, bevor sie in den "Main"-branch gemerged werden. In diesem Artikel zeige ich, wie du PR-spezifische Deployment Slots einrichtest und GitHub Actions für diese Automatisierung nutzt.

Was sind Azure Deployment Slots?

Azure App Service Deployment Slots sind separate Bereitstellungsumgebungen innerhalb einer App Service-Instanz. Sie ermöglichen es Ihnen, mehrere Versionen Ihrer Anwendung gleichzeitig zu hosten. Hauptvorteile:

  • Zero-Downtime-Deployments: Neue Versionen können in einem Slot bereitgestellt und getestet werden, bevor sie live geschaltet werden.
  • Einfaches Rollback: Bei Problemen kann einfach zum vorherigen Slot zurückgewechselt werden.
  • Isolierte Umgebungen: Jeder Slot hat seine eigenen Konfigurationen und Connection-Strings.

GitHub Actions und Pull Requests

GitHub Actions ist ein Tool zur Automatisierung von Software-Workflows direkt in Ihrem GitHub-Repository. Es ermöglicht das Erstellen von CI/CD-Pipelines, die auf verschiedene Ereignisse wie Pushes, Pull Requests oder zeitbasierte Trigger reagieren können. In Kombination mit Azure können Sie so Ihren gesamten Entwicklungs- und Deployment-Prozess automatisieren.

Die Idee: Branch-spezifische Deployment Slots

Stellen Sie sich vor, jeder Pull Request erstellt automatisch einen eigenen Deployment Slot. Dies ermöglicht:

  • Live-ähnliches Testing: Prüfen Sie Änderungen in einer Umgebung, die der Produktion nahekommt.
  • Frühes Erkennen von Fehlern: Durch Tests im Deployment Slot können Probleme erkannt werden, bevor sie in den Hauptbranch gelangen.
  • Automatisierung: Durch Integration mit GitHub Actions werden Slots automatisch erstellt und entfernt.

Schritt-für-Schritt-Anleitung

1. Workflow für Pull Requests einrichten

Um automatisch Deployment Slots für jeden Pull Request zu erstellen und zu verwalten, richten wir einen neuen GitHub Actions Workflow ein, der auf Pull Request-Ereignisse reagiert.

  1. Ordnerstruktur: Legen Sie im Root-Verzeichnis Ihres Repositories einen Ordner .github/workflows an, falls dieser nicht bereits existiert.
  2. Workflow-Datei erstellen: Erstellen Sie eine neue Datei namens pull_request_deployment.yml in diesem Ordner.
  3. Workflow konfigurieren: Nutzen Sie den folgenden YAML-Code, der Ihre bestehende Pipeline erweitert, um Deployment Slots für PRs zu verwalten.
1name: PR Deployment CI/CD
2
3on:
4  pull_request:
5    types: [opened, synchronize, reopened, closed]
6
7jobs:
8  build:
9    if: github.event.action != 'closed'
10    runs-on: windows-latest
11
12    steps:
13      - uses: actions/checkout@v4
14
15      - name: Set up .NET Core
16        uses: actions/setup-dotnet@v4
17        with:
18          dotnet-version: '8.x'
19
20      - name: Build with dotnet
21        run: dotnet build src/WebApplication/WebApplication.csproj --configuration Release
22
23      - name: dotnet publish
24        run: dotnet publish src/WebApplication/WebApplication.csproj -c Release -o ./deploy
25
26      - name: Upload artifact for deployment job
27        uses: actions/upload-artifact@v4
28        with:
29          name: .net-app
30          path: ./deploy
31
32  deploy:
33    if: github.event.action != 'closed'
34    runs-on: windows-latest
35    needs: build
36    environment:
37      name: 'PR-slot-deployment'
38      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
39    permissions:
40      id-token: write # This is required for requesting the JWT
41
42    steps:
43      - name: Download artifact from build job
44        uses: actions/download-artifact@v4
45        with:
46          name: .net-app
47          
48      - name: Login to Azure
49        uses: azure/login@v2
50        with:
51          client-id: ${{ secrets.AZURE_CLIENT_ID }}
52          client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
53          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
54          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
55
56      - name: Create Deployment Slot
57        run: |
58          $SLOT_NAME="pr-${{ github.event.number }}"
59          az webapp deployment slot create --name prdeploymentwebapp --resource-group prdeployment --slot $SLOT_NAME
60          
61      - name: Deploy to Azure Web App
62        id: deploy-to-webapp
63        uses: azure/webapps-deploy@v3
64        with:
65          app-name: 'prdeploymentwebapp'
66          slot-name: 'pr-${{ github.event.number }}'
67          package: .
68          
69  cleanup:
70    if: github.event.action == 'closed'
71    runs-on: windows-latest
72    environment:
73      name: 'PR-slot-deployment'
74      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
75    permissions:
76      id-token: write # This is required for requesting the JWT
77
78    steps:
79      - name: Login to Azure
80        uses: azure/login@v2
81        with:
82          client-id: ${{ secrets.AZURE_CLIENT_ID }}
83          client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
84          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
85          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
86
87      - name: Delete Deployment Slot
88        run: |
89          $SLOT_NAME="pr-${{ github.event.number }}"
90          az webapp deployment slot delete --name prdeploymentwebapp --resource-group prdeployment --slot $SLOT_NAME

Erklärung:

  • Trigger: Der Workflow wird bei Pull Request-Ereignissen wie opened, synchronize, reopened und closed ausgelöst.
  • Build Job: Baut und veröffentlicht die Anwendung, lädt das Artefakt für den Deploy-Job hoch.
  • Deploy Job: Erstellt einen Deployment Slot mit dem Namen pr-<PR-Nummer>, deployt die Anwendung in diesen Slot und stellt die URL der Live-Umgebung bereit.
  • Cleanup Job: Wird nur ausgelöst, wenn der Pull Request geschlossen wird (gemerged oder abgelehnt). Löscht den entsprechenden Deployment Slot.

2. Pull Request erstellen

Die Pipeline wird automatisiert starten, sobald der Pull Request erstellt wurde.

Automatisierte Bereitstellung eines PRs mit GitHub Actions

3. Tests in der "Live"-Umgebung durchführen

Nachdem die Anwendung in den Deployment Slot deployt wurde, können Sie sowohl manuelle als auch automatisierte Tests in dieser Umgebung durchführen. Die URL des Slots lautet in der Regel:

https://prdeploymentwebapp-pr-12.azurewebsites.net

Deployment slots Übersicht nach PR Deployment


Manuelle Tests:

Öffnen Sie die obige URL in Ihrem Browser und führen Sie die notwendigen Tests durch.

4. Clean up der Deployment slots

Nach dem Schließen eines Pull Requests, wird der Slot automatisch entfernt. Dadurch wird sichergestellt, dass keine Altlasten unnötig lange verfügbar bleiben.

Cleanup Prozess in den GitHub Actions

Best Practices und Fallstricke

Anzahl der Deployment Slots

  • Kostenkontrolle: Jeder Slot verbraucht Ressourcen. Begrenzen Sie die Anzahl der gleichzeitigen Slots, insbesondere in großen Projekten mit vielen parallelen Pull Requests.
  • Aufräumen: Stellen Sie sicher, dass temporäre Slots nach Gebrauch gelöscht werden, um unnötige Ressourcen zu vermeiden.

Umgang mit vielen Pull Requests

  • Limits in Azure: Azure hat Grenzwerte für die Anzahl der Slots pro App Service Plan (Standardmäßig bis zu 20 Slots). Planen Sie entsprechend, um Engpässe zu vermeiden.
  • Skalierung: Bei hohem PR-Aufkommen könnten Ressourcen knapp werden. Überlegen Sie, den App Service Plan zu skalieren oder automatisierte Slot-Löschungen zu optimieren.

Optimierung des Workflows

  • Parallele Jobs: Nutzen Sie die Parallelität von GitHub Actions, um Workflows zu beschleunigen.
  • Schnelle Bereitstellungen: Minimieren Sie die Anzahl der Schritte und optimieren Sie die Build-Prozesse, um die Bereitstellungszeiten zu verkürzen.
  • Automatisierte Tests: Durch die automatisierte Bereitstellung der Anwendung können ebenfalls E2E-Tests mit z.B. Cypress durchgeführt werden.

Rollback-Strategien

  • Automatisches Rollback: Implementieren Sie Mechanismen, um bei fehlschlagenden Deployments automatisch zum vorherigen Slot zurückzuwechseln.
  • Monitoring und Alerts: Überwachen Sie die Deployments und richten Sie Alerts ein, um schnell auf Probleme reagieren zu können.

Fazit

Mit diesen Anpassungen Ihrer GitHub Actions Pipeline nutzen Sie Azure Deployment Slots effektiv, um Pull Requests in isolierten, live-ähnlichen Umgebungen zu testen. Dies erhöht die Qualität Ihres Codes und reduziert das Risiko von Fehlern in der Produktionsumgebung erheblich.

Zusammenfassung der Anpassungen:

  • PR-spezifische Slots: Jeder Pull Request erhält einen eigenen Deployment Slot, der nach Abschluss des PRs automatisch entfernt wird.
  • Automatisierte Slot-Verwaltung: Erstellung und Löschung von Slots automatisiert durch GitHub Actions.

Diese Maßnahmen tragen dazu bei, den Deployment-Prozess zu optimieren, die Effizienz zu steigern und die Zuverlässigkeit Ihrer Anwendungen zu erhöhen.

Ressourcen: