Um die projektübergreifende Entwicklung zu erleichtern, hat das Team, das Webmail von Infomaniak entwickelt, den Code der Anwendungen in einem einzigen Repository (Monorepo) zusammengefasst. Damit sollen die Aktualisierungsprozesse verbessert, die Zusammenarbeit erleichtert und die Entwicklung des Ökosystems beschleunigt werden. Webmail ist ein umfangreiches Pilotprojekt mit mehreren miteinander verbundenen Anwendungen (kDrive, Mail, Calendar, Contacts) und täglich mehr als 1 Mio. Benutzern. Unsere Entwickler berichten über diese Umstellung, ihre Vorteile, ihre Herausforderungen und auch ihre negativen Auswirkungen.

Die Leistungsfähigkeit unserer Lösungen werden wir auch in unserer eigenen Organisation und unseren Prozessen untersuchen. Julien Arnoux, VP of Engineering bei Infomaniak

Warum auf eine Monorepo-Architektur umsteigen?

Der Lebenszyklus von Webmail erfordert, dass wir unsere Code-Repository-Strategie anpassen. Bisher wurden die verschiedenen Teile (Projekte, Bibliotheken) von Webmail in separaten Code-Repositorys entwickelt. Ein Team entwickelte den Code einer Bibliothek für sein Projekt eigenständig weiter, ohne Versionsänderungen in Echtzeit an andere laufende Projekte weiterzugeben. Die Betreuung wurde komplex:

«Entwickler, die an funktionsübergreifenden Änderungen arbeiteten, mussten systematisch die Versionen jeder einzelnen Bibliothek und manuell bearbeiteter Projekte ermitteln und abgleichen. Dies führte zu viel Aufwand. Die Idee war, all diese Zwischenschritten zu beseitigen und sich auf die eigentliche Entwicklung zu konzentrieren.» Zachary Volpi, Webmail-Entwickler bei Infomaniak

Die Projekte könnten auch nicht mehr synchron sein, wenn ein Team einen schnelleren Veröffentlichungszyklus hätte als andere abhängige Bibliotheken. Die schwerfälligen manuellen Veröffentlichungs- und Aktualisierungsvorgänge im Multirepo erhöhten zudem die aufwändigen Manipulationen und das Fehlerrisiko zulasten der Wertschöpfung. 

Die Vorteile der Monorepo-Architektur

Mit dieser neuen Basis wird unser DevOps-Ansatz noch effizienter. Automatisierte Zyklen ermöglichen das Kompilieren, Testen und Bereitstellen von Code ohne Fehler (insbesondere das Spektrum menschlicher Fehler). Diese Fortschritte ermöglichen es, alle Phasen der Anwendungsbereitstellung zu optimieren.

1. Vereinfachte gemeinsame Nutzung und Validierung des Codes 

Bei einer Monorepo-Architektur werden die Quellcode-Versionen zwischen allen Projektteilen geteilt. Eine einzige Änderung wird überall wirksam, ohne dass die Gefahr besteht, dass eine benachbarte Funktion beeinträchtigt wird. Es muss nicht mehr für jede Abhängigkeit die richtige Version angegeben werden. Unsere Skripte erkennen Projekte, die mit einem Update verknüpft sind, und starten die mit den geänderten Bereichen verbundenen Validierungsprozesse.

2. Vereinfachte Verwaltung von DevOps-Prozessen

Die Zentralisierung des Codes ermöglicht die Erstellung von Pipelinesfür das gesamte Projekt mit einer enormen Zeitersparnis. Unsere Pipelines Continuous Integration (CI) und Continuous Delivery (CD) werden mit bewährten, vorhersehbaren und wiederholbaren Prozessen rigoroser. Das erleichtert das Hinzufügen neuer Codeteile.

Nun können wir Pipelines je nach Phase (Build, Test, Bereitstellung) koppeln. Die Jobs werden parallel gestartet, was im Multirepo nicht möglich oder stark eingeschränkt war. Da jeder Testsatz gleich ist, erfolgt die Entwicklung von Funktionen, die mehrere Anwendungen betreffen, viel schneller.

3. Erleichterte Zusammenarbeit und bessere Übersicht

Entwickler können die Gesamtheit einer laufenden Änderung abrufen und integrieren, was das Gesamtverständnis verbessert. Sie müssen nicht mehr mehrere Projekte durchforsten, um versteckte Probleme aufzuspüren, alles ist griffbereit. Anschliessend ändern und testen wir, was die Validierungsschleife verkürzt. Auch der Kontextwechsel ist einfacher: Ein Entwickler, der an mehreren Projekten arbeitet oder die Arbeit eines Kollegen einbeziehen muss, kann die Unterschiede viel schneller vergleichen.

4. Verbesserte Codequalität

Wir müssen nicht mehr duplizieren, eine Bibliothek in ein übergeordnetes Projekt einbauen und ständig hin und her gehen. Wenn man den vollständige Code zur Hand hat, kann man Probleme schneller erkennen. Wir können auch Anwendungen entrümpeln, indem wir toten Code entfernen, ohne befürchten zu müssen, dass er anderweitig verwendet wird. Die gemeinsame Nutzung derselben Umgebung verringert die Abweichungen zwischen den Teams.

Wenn wir eine Bibliothek ändern, werden zuerst folgende Überprüfungen durchgeführt: Entspricht der Code den geltenden Normen? Funktioniert er wie geplant? Anschliessend führen wir die Tests der Anwendungen durch, die ihn verwenden, um die korrekte Integration zu überprüfen. Dabei handelt es sich um einen Zwiebelansatz (in Schichten), der von den einfachsten Tests (Einheitstests) zu den komplexesten Tests (End-to-End-Tests) übergeht.

5. Beschleunigung der Entwicklung

Monorepo erleichtert die regelmässige Freigabe neuer Funktionen. Wir erhalten die Änderungen anderer Entwickler viel schneller. Zusammen mit der Prozessautomatisierung werden dadurch die Produktionsfreigaben reibungsloser. Da die Rückmeldungsschleife beschleunigt ist, können wir schneller wiederholen.

Umstellung auf Monorepo: Was ändert sich?

Wie sich Monorepo auf unsere Organisation auswirkt, lässt sich am besten anhand einer Skizze veranschaulichen:

Verbesserung, die mehrere Änderungen an den verschiedenen im Projekt verwendeten Bibliotheken erfordert:

Mit Monorepo:

Einführung von Monorepo in einer Produktionsumgebung

Wir wollten den Übergang für unsere Kunden voll transparent und für die Projektmitarbeiter quasi transparent machen. 

«Im Gegensatz zu einem entstehenden Projekt hatte die Änderung der Organisation des Webmail-Codes enorme Auswirkungen, da die Anwendung in Produktion ist. Es ist, als würde man eine Baustelle auf einer Hauptstrasse eröffnen.» Zachary Volpi, Webmail-Entwickler bei Infomaniak 

Der Übergang musste in mehrere Schritte aufgeteilt werden, um eine zu grosse Änderung zu vermeiden, die eine Nichtverfügbarkeit des Dienstes hätte auslösen können, ohne die Möglichkeit zu haben, dies rückgängig zu machen. Deshalb haben wir eine lange Vorbereitungs- und Validierungsarbeit geleistet:

  • Aufteilung der Migration in mehrere Phasen unter Berücksichtigung der potenziellen Auswirkungen auf die Kollegen.
  • Test jedes Schrittes im Vorfeld wo möglich.
  • Einzelheiten zu jedem Schritt mit einer «einsatzbereiten» Aufgabenliste für den Tag X.
  • Planung der Meilensteine der Migration in Zeiten mit geringer Auslastung.
  • Simulation von Krisenszenarien, um Problemen vorherzusehen und Massnahmen zu planen.

Unser Team hat auch Verfahren zur Dokumentationvon Zwischenfällen erarbeitet, um ein gewisses Zurückgehen zu ermöglichen.

Die Wahl von PHP

Was DevOps ist, wird oft in Bash oder Python geschrieben, selten in PHP. Die DevOps Pipelines, die wir aufbauen wollten, sollten für alle anderen Kollegen nachvollziehbar sein. Unsere Anwendungen sind ebenfalls in PHP geschrieben und es ist durchaus möglich, es für das Skripting zu verwenden. Wir hatten auch bereits laufende Umgebungen, die für weitere Schritte konfiguriert und verfügbar waren. So war es einfacher, sie direkt wiederzuverwenden, statt mit leeren Blättern zu beginnen.

Den richtigen Umschaltrhythmus finden

Es sollten keine längere Übergangsphasen entstehen. Jede Aufgabe musste daher in einem ausreichend langen Intervall erfolgen, um die Sicherheit und Stabilität zu gewährleisten, aber relativ kurz, um das System nicht anfällig zu machen.

Die grössten Herausforderungen der Migration

Eine Migration ohne Umkehr

Diese Vorgehensweise hatte Auswirkungen auf den gesamten Workflow (Strukturierung der Schritte, Extraktion der gemeinsamen Teile, Speicherort der Dateien, Änderungshistorie) und alle Arbeitsumgebungen des Webmail-Teams (Produktionsumgebung, Entwicklungsumgebung, Testumgebung, Paket-Freigabe-Umgebung, Benachrichtigungen, usw.). Deshalb war es wichtig, dass die Übergangsphase nicht zu lange dauert.

Bei Multirepo muss jede Änderung an einer Komponente bei allen ihren Abhängigkeiten manuell angepasst und überprüft werden. In Monorepo ist fast alles automatisiert: Sobald eine Komponente verändert wird, aktualisiert sich das gesamte System automatisch. Es ist, als würde man in einem Auto von einem Schaltgetriebe auf ein Automatikgetriebe umschalten. Alles einfacher! Julien Arnoux, VP of Engineering bei Infomaniak

Alle Szenarien durchdenken und voraussehen

Es ist paradox, aber wir mussten durch eine hohe Komplexität gehen, um alles zu vereinfachen. Den Code zu zentralisieren bedeutet, alles neu zu überdenken. Um die Logiken für die Auslösung der Pipelines zu definieren, mussten wir ihre Auswirkungen auf jedes Projekt verstehen und die dazugehörige Kontexterkennung entwickeln, für:

  • die Phasen (Continuous Integration + Continuous Development)
  • die gemeinsamen Jobs der Apps und Bibliotheken
  • die verschiedenen Build-Phasen
  • die Durchführung der Tests und Validierungen der beteiligten Parteien

Die grösste Schwierigkeit bestand darin, dass nicht alle Schritte unter realen Bedingungen getestet werden konnten, insbesondere jene in der Produktionsumgebung. Dank der Konzentrationsmöglichkeiten der gitlab-ci-Definitionen konnten wir unsere verschiedenen Skripte nach Themen und Wirkungsbereichen trennen. Dies hat die Duplizierung von Dateien und andere Copy-Paste-Probleme drastisch reduziert.

Bilanz: Monorepo oder Multirepo? 

War es eine gute Idee, zu Monorepo umzusteigen? Die Antwort ist ja.

Die neue Organisation bringt grosse Vorteile:

  • Vereinfachtes Abrufen von Änderungen.
  • Gemeinsame Konfiguration bestimmter Tools.
  • Reduzierte Handhabung bei Änderungen an mehreren Anwendungen.
  • Vereinfachung der Entwicklung: alles an einem Ort und die Navigation zwischen den Bereichen ist viel einfacher.

Diese Entwicklung hat auch negative Auswirkungen:

  • Es ist weniger offensichtlich, sich zurechtzufinden als in einem klassischen Repository. Die Lernkurve eines Neueinsteigers wird dadurch etwas länger.
  • Es braucht gute Kenntnisse der CI / CD Tools, insbesondere gitlab-ci, um Anpassungen an den Pipelines vorzunehmen.

Die Entwickler, die die Umstellung auf Monorepo bewältigt haben

Julien Arnoux, VP of Engineering bei Infomaniak (aber immer noch mit den Händen in den Hosentaschen):

Ich entwickle seit meinem 15. Lebensjahr und liebe alles, was mit der Automatisierung unserer Workflows zu tun hat. Wenn ich entwickle und je nach Stimmung kann ich sowohl Hard-Rock / Metal als auch Drum’n’Bass hören. Eigentlich höre ich von allem ein bisschen, aber diese beiden Stile bringen mich in Schwung 😅

Zachary Volpi, Full-Stack-Entwickler im Webmail-Team:

Ich habe mit der Entwicklung im August 2014 begonnen. Mir gefällt es, den Einblick (und das Verständnis) in alle Aspekte der Anwendungsentwicklung zu haben. Ich suche immer nach Lösungen, um einen Prozess zu vereinfachen oder mehr Leistung zu erzielen. Um meine Sessions zu begleiten, passe ich die Musik an das an, was ich machen will: von Chill über Dub bis Metal. Was die Referenzen angeht, finde ich den logrocket-Blog sehr relevant. Sie haben sehr gut gestaltete Artikel zu sehr breiten und spezifischen Themen. Ansonsten folge ich direkt den Kanälen der Tools, die ich verwende (hauptsächlich auf X & LinkedIn).

Sollten Sie auch eine Monorepo-Architektur verwenden?

Sprechen Sie mit unseren Entwicklern auf X.