Tech Talk: "Templating + Git = ❤" mit Dominik Aumayr von Ubitec

Tech Talk: "Templating + Git = ❤" mit Dominik Aumayr von Ubitec

Ja hallo, mein ist Name Dominik Aumayr und ich bin CTO bei Ubitec und ich darf heute einen Schwenk aus unserem Entwicklerleben bei Ubitec erzählen – nämlich ein Problem das wir gehabt haben, eine Herausforderung und wie wir dieses Problem gelöst haben.

Kurz zu uns: wir sind die Firma Ubitec, wir sitzen in Linz in der Tabakfabrik, sind derzeit zu 8 und wir bauen dialogbasierte Produkte und Services – kurz Chatbots – und decken dabei den vollständigen redaktionellen Lebenszyklus ab. Unsere Systeme laufen on premise und darum ist unser Kundenkreis formal aus dem öffentlichen Bereich wie zum Beispiel das Finanzministerium hat einen Chatbot von uns, wer schon mal seine Steuererklärung eingereicht hat, der FRED. Oder zum Beispiel beim ÖAMTC ist auch ein Chatbot von uns oder bei der Stadt Wien. Und in diesem Tun stoßen wir natürlich weil es on premises läuft auf einige Herausforderungen und für heute habe ich mir eine Aufgabenstellung mitgenommen.

Unsere Architektur schaut ganz grob so aus. Wir haben ein Kernsystem, das Ubitec bot framework – das ist gleich für alle unsere Chatbots. Und aus oder mit diesem Kersystem bauen wir dann die einzelnen Bot-Projekte. Also wir haben das Framework darüber und darunter die einzelnen Bot-Projekte – hier dargestellt mit einem Avatar jeweils, wir habe da eben 6 Projekte auf der Folie. Und weil sie on premise laufen gibt es verschiedene deployment-Schemen, manche werden mit Docker oder Docker Compose deployed, und manche mit Kubernetes und machen laufen mit OpenShift. Das heißt wir haben zwar eine homogene Basis für alle, aber natürlich gibt es projektspezifische Anpassungen zum Beispiel der Avatar, Farben usw., Funktionalitäten, API-Anbindungen und schlussendlich das Deployment – da ist auch wieder überall ein bisschen ein Unterschied. Und die Herausforderung die wir natürlich haben ist, wir haben jetzt quasi eine Projektstruktur, die ist für alle gleich, wir haben eine deployment-Konfiguration in verschiedenen Farben, die für alle gleich ist. Das heißt wir haben einen Standard aber es sind Individualisierungen möglich. Manche Kunden wollen zusätzliche Container zum Beispiel laufen lassen, mache haben gewissen Anforderungen an Deployment-Szenarien und so weiter und sofort. Und die stellen uns natürlich vor Herausforderungen. Wir können aus unserem Framework quasi ein Template generieren und das dann klonen aber wir passen das immer an den Kunden an.

In einem ersten Schritt möchte ich kurz die Tools zeigen wie wir quasi diese Grundherausforderungen lösen. Das erste Tool, das für uns sehr, sehr praktisch ist, ist ein Python-Paket. Das heißt Cookie Cutter. Es ist in Wirklichkeit der Command Line Utility mit dem man eben Templates bauen kann mit einer Templating Language, in dem Fall für die, die Python kennen Jinja2 und ich kann auf Basis dieser Templates Projektbäume generieren. Ich habe im ersten Screenshot ganz oben einmal so ein Template auf die Folie gegeben. Da sieht man mit curly braces gibt eben so Variablen, die man dort einsetzt, in dem Fall z.B. ein Bot-Slug oder Bot-Name oder Bot-Version, das ist wieder chatbotspezifisch für uns. Darunter sieht man dann, wie man eben solche Cookie Cutter Template aufruft. Wenn man das aufruft, dann fragt das Tool nach diesen Variablen. Die kann das dann eingeben und dann wird Baum draus generiert der Projektbaum. Diese Variablen können entweder im Dateiinhalt sein oder auch im Dateinamen. Für uns natürlich auch sehr spannend. In dem Fall heißt der Bot TechTalk für heute, hat ein Slug und da hat er Version 1.0. Und dann wird eben ein Projektbaum generiert, da sehr einfach dargestellt. Man hat eben Variablenersetzung und man kann dieses Generieren auch automatisieren. Jetzt haben wir für uns eben ein zentrales Template gebaut, wie so einen Botstruktur ausschaut, welche Dateien man da braucht, hat ein paar fragen auf Variablen gelegt wie zum Beispiel „Wie heißt der Bot“ und so weiter. Und damit generieren wir dann die einzelnen Projekte, so wie wir es auf der vorherigen Folie gesehen haben.

Weiteres Tool für uns natürlich auch sehr wichtig. Alle Botprojekte und dieses ubitec-Bot-Framework als Template leben in eigenen Git-Repositories. Ganz klar zu Versionsverwaltung, Änderungsnachverfolgung und wir haben eben Tags für neue Versionen vom Kernsystem, vom ubitec-Bot-Framework und auch tags für neue Versionen von den Projekten. Im oberen Screenshot sieht man dass wir dort z.B. was geändert haben. Git es natürlich sehr praktisch um das nachzuverfolgen. Das ist einmal unsere Ausgangslage wie wir einmal diese grundlegende Herausforderung gelöst haben, damit wir ein Kernsystem haben, ein Templates und dann die Projektbäume generieren – für die einen eben Cookie Cutter und für diese Individualisierung und Nachverfolgung Git.

Soweit glaube ich einmal sehr Standard. Aber was passiert wenn sich das Template ändert? Dann müsste ich ja theoretisch hergehen und alle Bot-Projekte händisch nachändern wenn sich im Nachhinein die Versionen und irgendwelche Inhalte von unserem ubitec-Bot-Framework vom Template geändert hat z.B. eine neue Datei ist hinzugekommen, der Dateiinhalt ändert sie usw.

Was machen wir? Wir haben uns Gedanken gemacht wie wir das lösen können und haben die Tools genutzt die wir eben schon im Einsatz haben. Wie vorher erwähnt, Änderungen im Template ansich werden in Git getrackt. Wieder im oberen Screenshot sieht man diff, da man z.B. die Description im helm/chart file geändert, haben noch weitere Files im helm/chart file eingefügt fürs deployment-Schema, da hat sich offenbar irgendwas geändert und es ist was dazugekommen. Und irgendwann haben wir uns entschieden: Okay, dieses Template ist jetzt nicht mehr Version 1, sondern wir haben jetzt eine neue Version, Version 2, darum sieht man darunter die Git tag list. Wir haben 2 Tags, Version 1 und Version 2.

Und jetzt ist natürlich die Herausforderung: wie bringen wir diese Änderungen in all unsere Bot-Templates die ja alle schon generiert worden sind in unsere quasi Bot-Projekte? Wir nutzen dazu ein Feature aus Cookie Cutter und einen Trick dabei. Und zwar Cookie Cutter kann nicht nur interaktiv solche Templates ausfüllen, indem man Cookie Cutter wie am Anfang aufruft und es fragt dann nach diesen variablen Werten, sondern man kann ein JSON-file angeben wo diese variablen Werte drinstehen. Das nennt sich replay-file und wenn man das mit dem ausführt, dann ist es nicht interaktiv. Es läuft von selber und generiert den Projektbaum automatisch. Und den Trick den wir nutzen dabei ist, wir legen dieses replay-file in das Template selber hinein. Das heißt das replay-file wird mit dem Template selber generiert. Das ist der obere Screenshot. Dort steht z.B. der Bot-Name, der Bot-Slug und die Bot-Version, wie wir es am Anfang gesehen haben. Und wenn das das erste Mal generierte wird, wird automatisch dieses replay-file mitgeneriert. Auf einmal sind wir in der Situation, dass sich der Bot oder dieses Bot-Project selber neu generieren kann, weil es eben selber sein replay-file hat.

Und dann kommt da ein weitere Trick dazu: wir nutzen Git und Git diff. Weil wir ja verschiedene Versionen des Templates im ubitec-Bot-Framework in verschiedenen tags haben, nutzen wir Git diff um zweimal einen Replay zu machen. Einmal von der alten Version mit den Werten vom Bot-Projekt, einmal von der neueren Version mit den Werten vom Bot-Projekt. In dem Fall ist es der Checkout von zwei Branches oder zwei Tags. Version 1, dann Replay. Version 2 und ein Replay. Und jetzt haben wir diesen einzelnen Boot auf Basis des Templates Version 1 neu gemacht und auf Basis Version 2 und dann machen wir einfach ein Git-diff drauf und schauen was ist der Unterschied zwischen den beiden Directories? Damit bekommen wir ein Diff File mit allen Änderungen zwischen den beiden Versionen aber mit den konkreten Werten vom jeweiligen Bot-Projekt. Ein Bot heißt so, der andere so. Diese Änderungen sind da schon drinnen.

Und dann – weil wir natürlich faule Programmier sind – gehen wir einen Schritt weiter und machen einen Git Apply dann auf das originale Projekt vom Bot applyen dort natürlich die Änderungen aus Diff-file und so können wir dann, wenn wir es dann auch noch irgendwie in einem Shells Script verstecken und dann in die CI schmeißen, das komplett automatisieren.

Das heißt wir haben dort projektspezifische Einstellungen, haben wir schon gesehen im Template mit diesen Fragen, haben ein Replay file. Wir können dann eben den Diff-machen und in der applyen und haben dann einen Haufen Effekte. Erstens, die meisten Sachen werden automatisch applyen werden und gehen durch ohne dass man eingreifen muss. Wenn man wirklich kundenspezifische irgendwas anpasst, das Chart File schaut bei dem einen Kunden komplett anders aus zum Beispiel, dann wird es Konflikte geben, aber wieder – wir nutzen Git, dass heißt es ist alles schön dargestellt und meist auch sehr hilfreich. Und vieles geht auch automatisch. Einen Schritt weiter ist dann, dass wir das einbauen in unsere CI-Pipelines. Nämlich dort sind dann Server Hooks wenn wir einen Tag pushen vom Template, der geht dann alle Kundenprojekte, macht diese Schritte alle automatisch und macht dann noch einen Merge Request auf bei uns in GitLab mit diesen Änderungen. Das heißt unsere Devs müssen eigentlich händisch nichts mehr machen, sondern nur mit dem Merge Request anschauen. Die meisten sie eh Standardprojekte, da gehts durch und die paar die wir customized haben da muss man dann Diff anschauen und dann die Changes mergen entsprechend.

Das heißt, unsere Lösung für dieses Architektur Diagramm besteht aus diesen drei Schritten. Wir haben eben einen Cookie Cutter Template in unserem Bot Framework drinnen. Wir haben dann eben diese Kundenprojekte, die auch ein eigenes Git-Repo sind. Dann Deployment-Schemen haben wir schon gesehen. Und können dann, weil wir eben Git nutzen und das Template haben mit dem replay-file automatisch diese Änderungen im Template auf diese Bot-Projekte anwenden.

Wie sieht die Zukunft aus? Cookie Cutter, das nutzen wir schon lange es funktioniert für uns super, Git natürlich auch – kennt eh jeder Dev. Diesen CI-Teil, da habe ich geflunkert, den haben wir noch nicht. Aber vielleicht auch das ein Grund für den Talk: Wenn dich das interessiert – wir suchen immer neue Engineers, die uns helfen nicht nur Code zu schreiben, sondern auch unsere Infrastrukturen besser zu machen. Und das wäre natürlich eine super Aufgabe diesen CI-Teil bei uns zu implementieren. Ich habe die zwei URLs zu unserer Job-Center und natürlich zu devjobs.at.

Genau, vielen Dank fürs Zuschauen. Das war eine Aufgabe aus unserem Leben bei Ubitec wo wir Bots bauen und wenn ich das interessiert, einfach mal vorbeikommen! Besten Dank.