Blog

Wie ich Gitlab verwende - Multiprojekt-Pipelines für Cypress E2E-Tests

Joel Grimberg

Joel Grimberg

Aktualisiert Oktober 16, 2025
5 Minuten

Gitlab ist meine Anlaufstelle, wenn ich ein Repo erstellen und mit anderen teilen, CICD einrichten und einige Beispiele für meine Cypress-Abenteuer erstellen möchte. Sei es, dass ich eine Demo, einen Cypress- oder CICD-Konzeptnachweis erstellen muss oder einfach nur einen Ort, an dem ich ein Repo mit der Welt teilen kann - Gitlab ist der Ort, an dem Sie mich beim Wandern auf einem digitalen Pfad finden können. Notiz an mich selbst: einen Blog darüber schreiben, warum ich Gitlab so sehr liebe.

Als einer der Gründer des niederländischen Cypress Meetup ist es sicher keine große Überraschung, dass ich ein großer Fan von Cypress bin. Das hat alles mit der problemlosen Einrichtung des Test-Frameworks zu tun. Es funktioniert einfach großartig, ohne dass man es braucht.

Eine der großen Stärken von Cypress ist, dass es ein offizielles Cypress Dashboard bietet, mit dem Sie Ihre Tests aufzeichnen, parallelisieren und ausbalancieren können, und viele weitere Funktionen hat. Wieder eine Notiz an mich selbst: Schreiben Sie über einige Erkenntnisse.

Dieser Blog enthält also eine Notiz an mich selbst: Teilen Sie mit meinem zukünftigen Ich und der Welt eine Anleitung zum Einrichten einer Multiprojekt-Pipeline in Gitlab, die am Ende meinen Cypress-Integrationstest (oder E2E-Test) steuert.

Da Leser unterschiedliche Auffassungen davon haben können, was E2E- oder Integrationstests bedeuten, möchte ich der Klarheit halber zunächst erklären, was ich in diesem Blog mit einem E2E-Test meine. Nehmen wir an, ich habe ein Backend-Service-Repository und ein Frontend-Service-Repository. Beide Dienste befinden sich in meinem eigenen Kontrollbereich. Ich arbeite an beiden Diensten und sie sind eng miteinander verbunden. In diesem Szenario möchte ich einige Tests erstellen, die Szenarien abdecken, die sowohl das Frontend als auch das Backend betreffen. Kein Mocking / Stubbing in diesen Tests. In diesem Szenario sind meine Integrationstests Tests, die das Stubbing beinhalten. Wenn ich also das Frontend teste, stubbe ich das Backend und stelle sicher, dass mein Backend nicht laufen muss, wenn ich die Integrationstests ausführe, und mein Mock fungiert als Backend und gibt einige gefälschte Daten zurück.

Im Falle eines E2E-Tests möchte ich sicherstellen, dass meine E2E-Tests laufen, wenn ich das Backend aktualisiere, damit ich eine Rückmeldung über die Integration der Dienste erhalte. Ich möchte mich darauf verlassen können, dass die Kernfunktionen meines Systems weiterhin wie erwartet 'E2E' funktionieren, wenn ich meinen Backend-Dienst einsetze.

Jetzt stellt sich also die Frage: Wo speichere ich meine E2E-Tests. Ich möchte sicherlich kein drittes Repository haben, in dem ich nur meine E2E-Testsuite speichere, da dies meine Tests von jeglicher Funktionalität abkoppeln würde. Meine Lösung für dieses Problem: Wenn die E2E-Tests hauptsächlich frontendgesteuert sind, möchte ich sie auch im Frontend-Repository speichern. Damit kann ich sogar einige gemeinsame Funktionalitäten des Frontend-Repos nutzen (z.B. i18n oder andere util-Funktionen). Innerhalb des Frontend-Repositorys wird es sein.

Nächste Herausforderung: Ich muss etwas herausfinden: Wenn ich einen Quellcode im Backend-Repository ändere, wie löse ich dann die E2E-Tests im Frontend-Repository aus. Die Antwort ist nicht vom Winde verweht, sondern wird von Gitlab gegeben: mit Multiprojekt-Pipelines.

Eine Multiprojekt-Pipeline ist eine Pipeline, bei der die Pipeline eine andere Pipeline auslöst, die in einem anderen Repository definiert ist.

backend-service gitlab-ci.yml:

 

test-service:
  stage: test
  trigger:
    project: "joelgrimberg/frontend-service"
    strategy: depend
  variables:
    PIPELINE_TYPE: "multi-project-pipeline"
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: always
    - if: $CI_COMMIT_BRANCH == "main" #run in main-branch 
            pipeline
      when: on_success
    - when: manual
  allow_failure: true

Da manche Leute es etwas ausführlicher mögen und gerne eine Geschichte hinter einem Yaml lesen, finden Sie hier die Erklärung des Yaml:

Diese yaml-Datei zeigt einen run-e2e-test-Auftrag, der innerhalb einer e2e-est-Stufe ausgeführt wird. Der Job wird durch eine Merge-Anforderung (diese basiert auf der pipeline_source) oder als manuelle Aktion ausgelöst. Wenn dieser Job ausgelöst wird, löst er die (standardmäßige) Frontend-Pipeline aus, in der die E2E-Tests definiert sind.

strategy: depend ist eine sehr nützliche Einstellung, denn sie stellt sicher, dass die übergeordnete Pipeline fehlschlägt, wenn die ausgelöste Pipeline, die im 'anderen Repository' definiert ist, fehlschlägt. In unserem Fall: Die Backend-Pipeline löst den e2e-Test im Frontend-Repository aus und wenn dieser Test fehlschlägt, schlägt auch die Backend-Pipeline fehl.

Jetzt möchte ich der Frontend-Repository-Pipeline etwas Magie hinzufügen, denn ich möchte einige Aufträge von der Frontend-Pipeline ausschließen. Ich möchte nur die E2E-Tests aus dem Frontend-Repository ausführen und nicht die gesamte 'Haupt'-Pipeline. Ich möchte nicht, dass die Build- und Integrationstests des Frontends ausgeführt werden. Ich möchte nur den neuen Backend-Service mit dem aktuellen (Haupt-)Frontend testen.

E2E-Test in meiner Frontend-Pipeline-Konfiguration:

e2e tests:
  stage: run-e2e-test
  resource_group: e2e-test
  script:
    - NODE_ENV='production'
    - npm run cypress:e2e
  rules:
    - if: $PIPELINE_TYPE == "multi-project-pipeline"
      when: always
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: always
    - if: $CI_COMMIT_BRANCH == "main" #run in main-branch pipeline
      when: on_success
    - if: $CI_COMMIT_BRANCH != "main" #do not run in feature-branch pipeline
      when: never
    - when: manual
  allow_failure: false

Also gut. Schauen wir uns das Ganze etwas genauer an. Die in dieser yaml-Datei verwendeten Regeln sind Gitlabs neue Methode, um zu definieren, wann ein Job ausgeführt werden soll. Gitlab prüft alle Regeln innerhalb einer Jobdefinition von oben nach unten. Wenn die Regel === true ist, werden die anderen Regeln nicht mehr geprüft, da es keinen Grund gibt, weitere Regeln in diesem Job zu prüfen, und der Job wird zur Pipeline hinzugefügt.

Die resource_group sorgt dafür, dass jeweils nur ein Auftrag dieser Art ausgeführt wird. Wenn also 2 Backend-Service-Pipelines gleichzeitig einen E2E-Test auslösen, wartet die zweite, bis die erste abgeschlossen ist. So wird sichergestellt, dass keine Kollisionen auftreten.

Wenn also in meinem Beispiel eine Variable mit dem Schlüssel 'multi-project-pipeline' vorhanden ist, wird sie der Pipeline hinzugefügt. Wenn Sie sich meinen Backend-Service gitlab-ci.yml noch einmal ansehen, werden Sie feststellen, dass ich diesen Schlüssel der auslösenden (übergeordneten) Pipeline hinzugefügt habe. Daher wird dieser Auftrag der Pipeline-Konfiguration hinzugefügt und als untergeordnete Pipeline ausgeführt. Ich muss lediglich sicherstellen, dass die anderen Aufträge in der ausgelösten Pipeline (Konfiguration der Frontend-Pipeline) nicht ausgeführt werden, wenn die Frontend-Pipeline von der Backend-Pipeline ausgelöst wird:

    - if: $CI_PIPELINE_SOURCE == "parent_pipeline"
      when: never

Die vollständige Einrichtung finden Sie hier:

Frontend-Repository: Frontend-Dienst

Backend-Repository: Backend-Service

Verfasst von

Joel Grimberg

Contact

Let’s discuss how we can support your journey.