Industrie: Lebensmittelauslieferung
Verwendete JetBrains-Produkte: TeamCity
Organisationsgröße: 10,000
Land: Niederlande
„Wir waren auf der Suche nach einer Managed-Lösung für die Gesamtheit unserer CI-Anwendungsfälle. Darüber hinaus benötigten wir selbstgehostete Agents, um die Kontrolle über die verwendete Software und die genauen Tools zu haben. TeamCity Cloud mit selbstgehosteten Agents ist eine maßgeschneiderte Lösung, die von den mehr als 300 Entwickler*innen unseres Teams gerne genutzt wird und unsere Produktivität auf ein neues Niveau hebt.“
— Ivan Babiankou, Staff Software Engineer, Picnic
Mein Name ist Ivan Babiankou und ich bin Staff Software Engineer bei Picnic. Ich gehöre dem Java-Plattformteam an. Ich war an der Auswahl des Nachfolgers für unsere vorherige CI-Lösung und an der Implementierung der Migration beteiligt.
Picnic revolutioniert die Art und Weise, wie Menschen Lebensmittel einkaufen. Nach dem Start in einer einzigen niederländischen Stadt versorgt Picnic heute mehr als 200 Städte in drei Ländern – Deutschland, Frankreich und den Niederlanden. Picnic setzt auf einen reinen App-Ansatz ohne physische Läden, um Millionen Benutzer*innen einen schnellen und einfachen Lebensmitteleinkauf zu ermöglichen.
Neben der Mobil-App für Endbenutzer*innen entwickeln wir die meisten anderen geschäftskritischen Systeme, einschließlich einer internen Lösung für die Lagerverwaltung. Wir bauen auch alle Tools, um die Routen der Fahrer zu planen, sie beim sicheren Fahren zu unterstützen, die Routen für die Kommissionierung von Einkaufsaufträgen im Lager zu optimieren usw.
Derzeit beschäftigt Picnic über 300 Entwickler*innen. Der Tech-Stack des Unternehmens umfasst unter anderem GitHub, Java, Python, Swift, Kotlin, TypeScript, Angular, React, Android, iOS, MongoDB und Spring Boot.
Wir haben Ende 2021 begonnen, uns mit JetBrains TeamCity zu beschäftigen, da wir aus unserer bisherigen CI-Lösung herausgewachsen waren. Wir hatten zwei große Probleme: langsame Builds und lange Build-Warteschlangen. Zu Spitzenzeiten verbrachten Builds zum Teil eine Stunde in der Warteschlange, bevor sie ausgeführt wurden.
In unserer alten Lösung haben wir diese Situation hauptsächlich durch eine erhebliche Erhöhung der Anzahl und Größe der Build-Agents behoben, um die Gesamtdauer der Builds zu reduzieren. Diese Lösung war jedoch nicht skalierbar, da sie für das Grundproblem der Build-Geschwindigkeit keine Abhilfe bot. Wir beschlossen, nach einer neuen Lösung zu suchen, die das besser und schneller erledigen konnte.
Als Ersatz für unsere CI-Lösung suchten wir nach einem System, das unseren gesamten Tech-Stack unterstützt und uns hilft, das Builden und Testen unserer Anwendungen zu standardisieren. Wir verwenden Java und Python für Backend-Anwendungen, GitHub als Versionsverwaltung sowie Kotlin, Swift und React Native für die Mobilentwicklung.
Wir begannen mit einer Vorauswahl von zehn Lösungsanbietern und reduzierten sie auf eine Shortlist von drei Kandidaten: CircleCI, TeamCity und GitHub Actions. Unser Hauptziel war die Minimierung der Warteschlangenzeiten und die Verbesserung der CI-Leistung durch Verkürzung der Build-Zeiten.
Eine weitere Anforderung waren selbstgehostete Agents. Während der Analyse stellten wir fest, dass unsere alte Lösung die Tools auf den Agents nicht besonders schnell upgraden konnte. Bei jedem einzelnen Build verbrachten wir 2 bis 5 Minuten nur mit der Installation von Tools. Wenn man bedenkt, dass ein durchschnittlicher Build etwa 9 Minuten dauert, ergibt es keinen Sinn, davor weitere 3 Minuten mit der Installation von Tools zu verbringen. So kamen wir auf die Idee, selbstgehostete Agents einzusetzen, die über die neuesten Tools, eine angemessene Leistung und so ziemlich alles andere verfügen, was wir brauchen, um unsere Builds einfach starten zu können.
Dass die CI-Lösung in der Cloud gehostet wird, war für uns ebenfalls eine Voraussetzung. Bei Picnic versuchen wir, so wenige Systeme wie möglich zu managen. In Bezug auf CI wollten wir eine Managed-Lösung haben, die wir nicht selbst betreiben müssen. Gleichzeitig geben uns selbstgehostete Agents in der Cloud die Kontrolle darüber, welche Software wir ausführen und welche Tools wir genau verwenden. Dies gibt uns eine flexible Kontrolle über die gesamte Build-Umgebung – die verwendete Hardware ebenso wie die vorinstallierten Tools –, ohne den CI-Server selbst verwalten zu müssen.
Wir haben etwa 300 CI-Benutzer*innen, von denen die meisten aktiv sind und in fast 200 Projekten recht intensive Commit-Aktivitäten durchführen. Diese Projekte folgen in TeamCity einer ziemlich hierarchischen Struktur mit über 120 VCS-Roots.
Daneben haben wir 40 Build-Agents für maximal 40 parallel ausgeführte Builds. Wir führen fast 1.100 Builds pro Tag durch, wobei die gesamte Buildzeit pro Tag knapp 10.000 Minuten beträgt. Die Agents benötigen etwa zwei Minuten zum Hochfahren, und die Builds stehen selten länger als diese zwei Minuten in der Warteschlange.
Im Laufe eines Monats summiert sich das auf fast 300.000 Minuten an Buildzeit.
Wir verwenden TeamCity für die gesamte interne Entwicklung. Sobald wir einen PR in GitHub eröffnen, erstellt das CI einen Build, führt Unit-, Integrations- und Komponententests durch und gibt uns Feedback. Das ist ungefähr der Endpunkt. TeamCity wird bis zu dem Punkt verwendet, an dem es ein Build-Artefakt erzeugt. Dieses wird dann für eine spätere Bereitstellung in ein Repository gepusht.
Alle Linux- und regulären Build-Agents laufen in unserer AWS-Cloud. Für iOS-Anwendungen haben wir ein paar Mac-Minis, die in unserem Büro an das Netzwerk angeschlossen und mit TeamCity verbunden sind. Eigentlich hatte das iOS-Team TeamCity bereits lokal im Einsatz, noch bevor wir zu TeamCity Cloud gewechselt sind.
Wir betreiben Agents mit On-Demand-Instanzen. Spot-Instanzen sind jedoch eine sehr attraktive Option für die künftige Optimierung.
Wir erstellen unsere eigenen Images und verwenden Cloud-Profile in TeamCity, um selbstgehostete Agents auszuführen. Dabei handelt es sich um EC2-Systeme in AWS. Wir verwenden TeamCity und Packer, um AWS-Images der Agents zu erstellen.
Dann verwenden wir diese Agents mit Startvorlagen und Cloud-Profilen in TeamCity, um Build-Agents nach Bedarf zu starten. Im Moment sind diese kurzlebig und werden nur für einen einzigen Build verwendet.
Wir stellten fest, dass die Wartezeit in der Warteschlange 2 Minuten betrug. Davon entfielen 1,5 Minuten auf das Provisioning des Build-Agents in AWS. Langlebige, wiederverwendbare Agents würden uns dieses Problem ersparen. Wenn das geschafft ist, würden wir beginnen, uns Spot-Instanzen näher anzusehen.
Wir deaktivieren grundsätzlich die Bearbeitung in der TeamCity-Bedienoberfläche. Eines unserer Ziele ist es, Pipelines zu standardisieren. Das erreichen wir, indem wir Konfigurationen als Code definieren.
Alle Build-Konfigurationen werden in ihren jeweiligen Repositories als Kotlin-Code gespeichert. Wir haben auf der Basis der Kotlin-DSL in TeamCity unsere eigene DSL entwickelt, mit der wir Pipelines in maximal 20 Zeilen Code definieren können.
Nehmen wir zum Beispiel den Hauptbuild, mit dem die Java-Anwendung erstellt wird. Er führt alle Tests und Komponententests aus. Wenn alle erfolgreich abgeschlossen wurden, werden die Build-Artefakte in das entsprechende Repository hochgeladen.
Außerdem haben wir einen separaten Job für die statische Codeanalyse und einen weiteren für die statische Analyse der Nightlies, die in SonarCloud verwendet werden sollen. Diese sind alle Teil einer Standard-Pipeline. Das ist es, was Sie bei Java-Anwendungen vom Start weg bekommen, wenn Sie nur die grundlegenden Dinge für Ihre Pipelines definieren.
Einige unserer Teams haben sehr viele Komponententests (BDD). Diese schreiben wir in Python, während die Hauptanwendung in Java entwickelt wird. Die App wird als Docker-Image verpackt. Anschließend starten wir auf dem Build-Agent eine Docker-Compose-Umgebung mit echter Infrastruktur (Datenbanken usw.), während für Drittanbieterdienste Mockups verwendet werden. Die Behave-Tests werden in der App ausgeführt, die ihrerseits in Docker Compose läuft.
Mit der von TeamCity bereitgestellten Kotlin-DSL lassen sich beliebige Anpassungen an der Build-Pipeline vornehmen. Wir können die Schritte, die Trigger und vieles andere ändern.
Standardmäßig geben wir den Teams einen Goldstandard für die Pipelines gemäß der Ansicht des Plattformteams vor. Zum Beispiel führen wir die Komponententests als Teil der Build-Pipeline auf demselben Agent und in demselben Job durch.
Einige Teams haben Hunderte von Komponententests, die leider noch nicht parallelisiert sind. In diesen Fällen erlauben wir es, die Behave-Komponententests in Testsuiten aufzuteilen und als Build-Kette zu konfigurieren.
Der Hauptbuild erzeugt das Artefakt und führt Unit-Tests und einfache Schnelltests aus. Wenn das erfolgreich abgeschlossen ist, können Sie so viele Testsuiten wie benötigt parallel durchführen, wobei mehrere Instanzen auf unterschiedlichen Agents verwendet werden.
Hier sind die Dinge, die uns bei der Nutzung von TeamCity am meisten gefallen:
Einrichtung von Standard-Build-Agents. Als wir uns zum ersten Mal mit TeamCity beschäftigten, fiel uns auf, dass das System rechenoptimierte Agents mit angeschlossener SSD verwendet. Dies ermöglicht eine Top-Performance im Vergleich zu anderen CIs. Zwar verwenden wir die bereitgestellten Agents nicht, aber dies hat uns dazu veranlasst, auch für unsere eigenen Agents rechenoptimierte Instanzen zu verwenden, die eine bessere Leistung erbringen.
Wir lieben außerdem die Leistungsmonitor-Funktion. Eines der größten Probleme für die Teams, die diese Pipelines verwenden, war die Frage: Wie entscheiden wir, ob wir eine kleine, mittlere oder große Instanz verwenden sollen? Ein Blick auf den Leistungsmonitor verschafft einem sehr hilfreiche Erkenntnisse zu dieser Frage. Dies vereinfacht das Debugging.
Was die Schwierigkeiten angeht, so wäre es toll, Kennzahlen für die Gesamtheit der Projekte zu haben, deren Builds wir in TeamCity erstellen, denn im Moment stellt TeamCity diese Informationen nur projektweise bereit. Wir haben keine Möglichkeit, die Werte zum Beispiel für alle Java-Projekte zu sehen.
Außerdem ist die Kotlin-DSL mit einer recht steilen Lernkurve verbunden, insbesondere für Entwickler*innen, die nicht mit Java vertraut sind.
Nachdem wir nun alle Projekte zu TeamCity migriert haben, möchten wir gerne weiter mit Build-Agents, Spot-Instanzen usw. experimentieren.
Um dies auf eine angenehme Art und Weise zu bewerkstelligen, möchten wir Build-Kennzahlen gerne systematisch erfassen. Alle diese Kennzahlen sind in TeamCity verfügbar. Was uns aufhält, ist die mangelnde Möglichkeit, diese Metriken für die Gesamtheit der Projekte zu sehen und ihre Entwicklung im Zeitverlauf zu verfolgen.
Anhand dieser Informationen könnten wir Entscheidungen für weitere Optimierungen treffen: Was wir zuerst angehen und verbessern sollten, und wie unsere Änderungen die Leistung verbessern oder verschlechtern. Fürs Erste überlegen wir, einen externen Service zu entwickeln, der all diese Informationen zusammenfasst. Wenn das standardmäßig verfügbar wäre, wäre das noch viel besser!
Wir werden uns auch mit der Optimierung befassen und versuchen, die zusätzlichen Minuten für das Hochfahren des Agents einzusparen, indem wir entweder langlebige Agents verwenden oder einen Agent-Pool einführen, in dem die Agents „vorgewärmt“ werden.
Eine weitere Sache, an der wir bei Picnic arbeiten, ist die Entwicklung von mehr End-to-End-Tests. Das ist ein weiteres Projekt, das über TeamCity laufen wird. Sobald wir das haben, müssen wir uns neu überlegen, ob wir unser CI/CD-System nicht vollständig auf TeamCity umstellen wollen.
Tadeas Kriz, CTO und Mitgründer von Brightify
Unsere Code-Reviews haben sich erheblich verbessert, und mithilfe der Webhooks von Space zu TeamCity können wir nach einem erfolgten Review einen Build vom jeweiligen Branch erstellen und für unsere Qualitätssicherung bereitstellen, damit der Branch vor dem Merge getestet werden kann. Abwesenheiten lassen sich jetzt auch einfacher verfolgen.
Piotr Polus, Technischer Leiter Frontend, Miquido
Wir haben uns aus drei Gründen für JetBrains entschieden: unkomplizierte Nutzung, Konfigurierbarkeit und einfache Verfügbarkeit von Plugins.
Wooseong Kim, APAC Channel Lead und Partnership Manager, Tangunsoft
JetBrains hilft Ihnen dabei, sauberen, professionellen, wartungsfreundlichen Code von höchster Qualität zu schreiben.