| von Markus Küsters

Gemeinsam besseren Code entwickeln: Der Schlüssel zum Erfolg mit dem GitHub-Workflow-Testen

Einleitung

In der dynamischen Landschaft der modernen Softwareentwicklung hat sich GitHub als unschätzbares Zentrum für Entwickler etabliert, um sich zusammenzuschließen und ihre innovativen Ideen zum Leben zu erwecken. Mit seiner umfangreichen Sammlung von Repositories und einer blühenden Community fördert GitHub eine Atmosphäre der Zusammenarbeit, die es Teams ermöglicht, nahtlos zusammenzuarbeiten. Aber das ist noch nicht alles – hier kommen GitHub Actions ins Spiel, der leistungsstarke Motor, der die Automatisierung zum Leben erweckt.

Durch GitHub Actions werden kontinuierliche Integrations- und Bereitstellungspipelines mühelos orchestriert, was Entwicklern ermöglicht, ihre Workflows zu optimieren und sich auf das zu konzentrieren, was sie am besten können: gute Software zu entwickeln. GitHub Actions fungieren als Rückgrat, das diese Workflows ausführt und sicherstellt, dass jede Änderung und Aktualisierung sorgfältig getestet und implementiert wird.

DevOps-Teams spielen eine entscheidende Rolle, indem sie wieder verwendbare (reusable) Workflows maßgeschneidert für Entwicklungsteams bereitstellen. Diese Workflows sind mit wesentlichen Qualitätsrichtlinien ausgestattet und folgen bewährten Branchenpraktiken, um Codequalität und Konsistenz zu gewährleisten. In diesem Blogbeitrag untersuchen wir den Schlüssel zum Erfolg dieser kollaborativen Codierpraxis – das automatisierte Testen dieser reusable Workflows.

Der Schlüssel: Testen von reusable Workflows

Da die Verwendung von reusable Workflows in einer Organisation immer häufiger vorkommt, ist es von größter Bedeutung, ihre Robustheit und Zuverlässigkeit sicherzustellen. Diese Workflows werden von vielen Teams und Projekten verwendet, sodass es unerlässlich ist, sie strengen Testverfahren zu unterziehen, um potenzielle Fehler und Inkonsistenzen zu identifizieren und zu beheben.

Automatisiertes Testen bietet einen skalierbaren und effizienten Ansatz, um die Funktionalität und Leistung dieser Workflows zu validieren. Durch ihre Ausführung mit vordefinierten Inputs und der Überprüfung des Outputs anhand der erwarteten Ergebnisse können DevOps-Teams Vertrauen in deren Korrektheit und Wiederholbarkeit gewinnen.

Implementierung: Verwendung von Workflows zum Testen von Workflows

Das Testen eines reusable Workflows mithilfe eines anderen Workflows ist der logische Schritt, um dessen Zuverlässigkeit und Effektivität sicherzustellen. Durch die Erstellung einer umfassenden Testcodebasis können DevOps-Ingenieure die Leistung des reusable Workflows mit verschiedenen Inputs validieren.

Der Prozess umfasst das Ausführen des Test-Workflows sowohl mit "gutem" Code als auch mit "schlechtem" Code, um verschiedene Szenarien zu simulieren. Für den "guten" Code bewertet der Test-Workflow, ob der reusable Workflow ihn erfolgreich verarbeitet und die erwarteten Outputs und Ergebnisse generiert. Andererseits ist der "schlechte" Code absichtlich darauf ausgelegt, bestimmte Qualitätsrichtlinien im reusable Workflow zu missachten und potenzielle Probleme oder Fehler zu simulieren.

Durch die Integration dieser Testfälle deckt der Test-Workflow effektiv Sicherheitslücken oder Schwächen auf, sodass DevOps-Ingenieure potenzielle Fallstricke identifizieren und beheben können. Letztendlich befähigt diese iterative Teststrategie DevOps-Teams, den reusable Workflow zu optimieren und seine Robustheit bei der Verwendung für verschiedenste Projekte mit unterschiedlichen Benutzeranforderungen zu verbessern.

Schritt 1: Reusable Workflow

Das reusable-workflows-Repository hat die folgende Struktur:

reusable-workflows
├── .github
│   └── workflows
│       └── python-flake8.yaml
└── README.md

Der reusable Workflow sieht folgendermaßen aus: (einige Zeilen wurden für Lesbarkeit gekürzt)

# .github/workflows/python-flake8.yaml
name: python-flake8

on:
  workflow_call: # Trigger des reusable Workflows
    inputs:
      flake8_options: ...
      working_directory: ...
      continue_on_error: ... # Dieser Input ist erforderlich, um die quality-gates zu testen

    outputs:
      flake8: # Dieser Output ist erforderlich, um das flake8 quality-gate zu testen
        description: Ergebnis von flake8
        value: ${{ jobs.flake8.outputs.result }}

Der Input continue_on_error und der Output flake8 sind wesentliche Bestandteile, um das automatisierte Testen zu ermöglichen.

jobs:
  flake8:
    runs-on: ubuntu-latest
    # continue-on-error ist auf true gesetzt, wenn das quality-gate getriggert wird
    continue-on-error: ${{ inputs.continue_on_error }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
      - name: flak8e installieren
        run: pip install flake8

Oben ist sichtbar, dass continue-on-error (Dokumentation) [1] konfiguriert wird. Ist es auf true gesetzt, wird die Ausführung des Workflows nicht abgebrochen, auch wenn das quality-gate (flake8) fehlschlägt.

      - name: flak8e ausführen
        id: flake8
        working-directory: ${{ inputs.working_directory }}
        run: flake8 . ${{ inputs.flake8_options }}

    outputs:
      # Dieser Output speichert das Ergebnis von flak8e
      result: ${{ steps.flake8.outcome }}

Der letzte Schritt führt flak8e aus, und das Ergebnis (Dokumentation) [2] wird im Workflow-Output gespeichert.

Schritt 2: Test-Workflow

Das Repository reusable-workflows-testing hat die folgende Struktur:

reusable-workflows-testing
├── .github
│   └── workflows
│       └── test-python-flake8.yaml
├── README.md
└── python-flake8
    ├── fail
    │   └── fail.py
    └── success
        └── success.py

Dieses Repository enthält den Test-Workflow (.github/workflows/test-python-flake8.yaml) und weiteren Code im Ordner python-flake8, der dazu dient, das quality-gate zu bestehen (im Ordner success/) oder es zu triggern (im Ordner fail/).

Dieser Test-Workflow wurde so konfiguriert, dass er täglich ausgeführt wird, sodass das DevOps-Team bei Problemen schnell benachrichtigt werden kann:

# .github/workflows/test-python-flake8.yaml
name: test-python-flake8

on:
  # dieser Workflow wird einmal pro Tag ausgelöst
  schedule:
    - cron: "0 3 * * *"

jobs:
  flake8-success:
    uses: WoodmarkConsultingAG/reusable-workflows/.github/workflows/python-flake8.yaml@main
    with:
      # der Workflow wird mit dem Code im Ordner "success" ausgeführt
      working_directory: python-flake8/success/
      # continue_on_error ist false, da wir einen erfolgreichen Durchlauf erwarten
      continue_on_error: false

  flake8-fail:
    uses: WoodmarkConsultingAG/reusable-workflows/.github/workflows/python-flake8.yaml@main
    with:
      # der Workflow wird mit dem Code im Ordner "fail" ausgeführt
      working_directory: python-flake8/fail/
      # continue_on_error ist true, da wir versuchen flake8 zu triggern
      continue_on_error: true

Der reusable Workflow python-flake8.yaml wird in den obigen Tests zweimal aufgerufen, einmal mit Code, der erfolgreich bestehen sollte, und einmal mit Code, der das quality-gate triggern sollte. Der Input continue_on_error ist true, wenn das quality-gate getriggert werden soll.

  check-results:
    runs-on: ubuntu-latest
    if: always()
    needs:
      - flake8-success
      - flake8-fail
    steps:
      - name: Ergebnis von flake8-fail prüfen
        run: |
          if ${{ needs.flake8-fail.outputs.flake8 != 'failure' }}; then
            echo "Fehler: flake8 ist nicht fehlgeschlagen, obwohl es erwartet wurde"
            exit 1
          else
            echo "flake8-fail ist wie erwartet fehlgeschlagen"
            exit 0
          fi

Der letzte Job im Workflow besteht darin, die Ergebnisse der vorherigen Tests zu überprüfen. Die Überprüfung erfolgt durch Betrachtung der Ergebnisse:

  • Falls das quality-gate nicht ausgelöst wurde (was bedeutet, dass der Output ist kein Fehlschlag), dann funktioniert unser quality-gate nicht wie erwartet, und das Gesamtergebnis des Tests ist ein Fehlschlag.
  • Falls das quality-gate ausgelöst wurde (was bedeutet, dass der Output ein Fehlschlag ist), dann funktioniert unser quality-gate wie erwartet, und das Gesamtergebnis des Tests ist ein Erfolg.

Schritt 3: Guter Code, Schlechter Code

Das letzte Puzzlestück ist der Code, mit dem die Tests ausgeführt werden. In diesem Fall wurden sehr einfache Beispiele mit Einzeilern gewählt, aber je nach Anwendungsfall und quality-gate werden möglicherweise komplexere Beispiele benötigt.

# python-flake8/success/success.py
print("Erfolg!")
 

Der obige Code sollte keine Probleme mit flake8 verursachen.

# python-flake8/fail/fail.py
Beispiel = lambda: 'Beispiel'

Dieser Code löst speziell den "flake8 Fehler E731" [3] aus. Dies wird genutzt, um sicherzustellen, dass flake8 wie beabsichtigt fehlschlägt.

Ergebnisse

Test Python Flake 8

Das obige Bild zeigt die GitHub Actions-Benutzeroberfläche während der Ausführung unseres Test-Workflows. Der Job "flake8-success" wird grün dargestellt, während der Job "flake8-fail" rot markiert ist, was exakt unseren Erwartungen entspricht. Im Endergebnis werden der Job "check-results" und der Gesamtstatus grün angezeigt, was die erfolgreiche Ausführung unseres Tests bestätigt.

Diese Testergebnisse geben uns ein hohes Maß an Vertrauen in die Funktionalität unseres reusable Workflows. Sollte es erforderlich sein, können wir weitere Tests definieren, um Effektivität noch besser zu gewährleisten.

Zusammenfassung

Automatisiertes Testen von reusable Workflows in GitHub

Da die Verwendung von reusable Workflows in DevOps-Teams immer verbreiteter wird, ist es von größter Bedeutung, deren Robustheit und Zuverlässigkeit zu gewährleisten. Reusable Workflows werden in der Regel von vielen Entwicklern und Projekten genutzt, wodurch es unerlässlich ist, sie rigorosen Testverfahren zu unterziehen.

Reusable Workflows, die von anderen genutzt werden, erfordern eine umfassende Teststrategie, um potenzielle Fehler und Inkonsistenzen zu identifizieren und zu beheben. Das automatisierte Testen bietet einen skalierbaren und effizienten Ansatz, um die Funktionalität und Performance dieser Workflows zu validieren. Durch die Ausführung mit vordefinierten Inputs und die Überprüfung der Outputs anhand der erwarteten Ergebnisse können Entwickler das Vertrauen in die Korrektheit und Wiederholbarkeit dieser essenziellen Komponenten gewinnen.

Quality-Gates, die die Codequalität in reusable Workflows prüfen, erfordern während des Testens besondere Aufmerksamkeit. Um deren Zuverlässigkeit zu gewährleisten, werden die Quality-Gates getriggert und anschließend überprüft, ob sie wie beabsichtigt funktionieren. Dieser Prozess stellt sicher, dass die Ergebnisse den Erwartungen entsprechen und die Workflows wie beabsichtigt funktionieren.

Zusammenfassend ist die Einführung des automatisierten Testens zur Bewertung von reusable Workflows in GitHub-Repositories ein entscheidender Schritt zur Verbesserung des gesamten Softwareentwicklungsprozesses. Durch die Gewährleistung der Funktionalität und der Effektivität der Workflows schaffen Entwickler eine solide Grundlage für das Implementieren und projektübergreifende Teilen von reusable Workflows.

Quellen

[1] https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idcontinue-on-error
[2] https://docs.github.com/en/actions/learn-github-actions/contexts#steps-context
[3] https://www.flake8rules.com/rules/E731.html

Teile diesen Artikel mit anderen

Über den Autor

Markus ist spezialisiert auf die Themen DevOps, Testautomatisierung und IaC (Infrastructure as Code). In seinen Kundenprojekten entwickelt er Lösungen für den Softwareentwicklungszyklus, wie z.B. maßgeschneiderte CI/CD-Runner und Testautomatisierungs-Workflows, um die Codequalität sicherzustellen.

Zur Übersicht Blogbeiträge