Wie testen und implementieren wir unseren Code, nachdem wir ihn in wiederverwendbare Teile zerlegt haben?

9

Wir haben mit einem Entwickler und einem SVN-Repo begonnen, das unseren gesamten Code enthält:

^/foo/trunk/module-a
^/foo/trunk/module-b
^/foo/trunk/module-b/submodule-b1
^/foo/trunk/website1

(Zu der Zeit war dies eine große Verbesserung). Nachdem dies eine Chance hatte, ein bisschen zu wachsen, hatten wir Probleme mit zirkulären Abhängigkeiten, langsamen Testsuiten und allgemeinen Schwierigkeiten bei der Wiederverwendung von Code (da sich z. B. der Funktionsumfang von website1 in das ansonsten generische Modul-a eingeschlichen hatte).

Um die Codebasis zu modularisieren und zu erwarten, dass wir in Kürze zu Git wechseln (und irgendwo gelesen haben, dass Git SVN-Mega-Repos nicht mag), sind wir zu einer viel detaillierteren Struktur übergegangen:

^/module-a/trunk/
^/module-b/trunk/
^/module-b/trunk/sumbmodule-b1
^/earlier-sub-sub-sub-module-c/trunk
etc. (about 120 such modules)

Das war konzeptionell großartig. Modularer Code, viel schnellere Testsuiten, einfacher zu dokumentieren usw. Wir haben einige unserer allgemeineren Komponenten als Open-Source-Komponenten bereitgestellt und alle Module pip-installierbar gemacht ( pip install -e .um sie in der developmentvirtuellen Umgebung zu installieren ).

Wir haben ein ^/srv/trunkRepository erstellt, das die Ordnerstruktur der Laufzeitumgebung enthält, d. H. ^/srv/trunk/libfür die Module, /srv/trunk/srcfür die Überreste von ^/foo/trunk, ^/srv/trunk/wwwfür Websites usw.

Und schließlich (basierend auf einer Idee von perforce, mit der ich vor langer Zeit zusammengearbeitet habe [ https://www.perforce.com/perforce/r12.1/manuals/cmdref/client.html] ) haben wir ein "vcs-" erstellt. Holen Sie sich eine Textdatei, in der alle relevanten Repos aufgelistet sind und wo sie in die Entwicklungsumgebung eingecheckt werden sollen, und einen entsprechenden Befehl dazu. ZB eine vcs-fetc-Linie:

svn srv/lib/module-a ^/module-a/trunk

würde entweder verursachen (erstes Mal)

cd /srv/lib && svn co ^/module-a/trunk module-a

oder (danach)

cd /srv/lib/module-a && svn up

und ähnlich für Github-Repos (sowohl unsere eigenen als auch unsere veränderten / unveränderten Vendor-Pakete).

Wir haben den gleichen vcs-fetch-Prozess zum Erstellen der Produktionsumgebung verwendet, stellen jedoch schnell fest, dass wir nicht wissen können, welche Version nach einem vcs-fetch in prod ausgeführt wurde.

Mit dem Mega-Repo konnten wir nur die Revisionsnummer notieren, bevor wir das Produkt aus dem Kofferraum aktualisierten, und das Zurückgehen war ein einfacher svn -r nnn up .Weg. Mit Code in svn und git (und einem Modul in hg) - und ~ 120 Repos ist es nicht offensichtlich, wie das geht.

Ich habe heute http://12factor.net/ gelesen und der erste Faktor ist "Eine Codebasis". Ich frage mich also auch, ob ich hier nicht auf dem richtigen Weg bin.

Eine Idee, die ich hatte, war, ein Bereitstellungsskript zu erstellen, das pip-installierbare "Bereitstellungs" -Räder erstellt und diese in einer requirements.txtDatei "bündelt" . Eine Bereitstellung umfasst dann das Erstellen einer neuen virtuellen Umgebung, das Pip-Installieren der Datei "require.txt", in der die Bereitstellungsräder aufgelistet sind, und das Umschalten der aktiven virtuellen Umgebung. Das Zurücksetzen auf das vorherige würde nur das Zurückschalten der virtuellen Umgebung bedeuten (aber wenn wir die virtuellen Umgebungen nicht für immer behalten wollten, konnten wir zu keinem Zeitpunkt zurückkehren - meiner Erfahrung nach war dies jedoch nie erforderlich).

An diesem Punkt frage ich mich, ob ich in die falsche Richtung gehe oder ob ich einfach nicht weit genug auf dem richtigen Weg gegangen bin. (Alles, was ich lese, spricht immer von "Ihrer App", und ich weiß nicht, wie sich daraus ergibt, dass 14 Websites auf derselben Codebasis ausgeführt werden ...)

thebjorn
quelle
Darf ich davon ausgehen, dass die einzelnen Komponenten jetzt von verschiedenen Teams mit unterschiedlichen Entwicklungszyklen entwickelt werden? In diesem Fall ist es unvermeidlich, das Repository auseinanderzubrechen. Obwohl mit git, würden Sie dann synchronisierte Release-Tags für wichtige, stabile Konfigurationen platzieren. Schauen Sie sich das Repo-Tool von Google an. Der Versuch, Entwicklungsversionen durch integrierte Metadaten abzugleichen, ist ziemlich vergeblich. Das Verknüpfen der Anwendung über pip ist ebenfalls absolut legitim.
Ext3h
Wenn Sie bitte Schätzungen KLOC (1000 Codezeilen) und Bytemessungen des Codes angeben, können wir uns leicht ein Bild von der Größe machen, zum Beispiel "2000 Codezeilen. 50 Kilobyte Quellcode". oder "40 KLOC, 2 GB XML". . Es scheint, was Sie brauchen, um nur nach Git zu migrieren, und Git hat Importfunktionen. Sie können beginnen, indem Sie das Git-Buch lesen .
Niklas
1
@ Programmer400 Die Codebasis lautet: .py 670 kloc, .js: 135kloc, .less: 25kloc, .html: 130kloc. So groß, aber nicht riesig. Nach dem, was ich gelesen habe, mag Git Repos dieser Größe nicht wirklich, also stelle ich mir vor, wir müssen uns in kleinere Repos aufteilen, bevor wir zu Git wechseln.
Thebjorn

Antworten:

2

Es hört sich so an, als ob Ihnen Zweige fehlen (oder eher "Tags" oder "Release" -Zweige).

Anstatt Ihre SVN-Version als Referenz zu verwenden, um zu bestimmen, welche Version Sie installieren, sollten Sie bei dieser veröffentlichten Version eine Verzweigung erstellen. Anschließend stellen Sie diesen Zweigstellennamen bereit.

Dies erleichtert die Verzweigung, auch wenn keine Änderungen vorgenommen wurden, sodass jedes Modul dieselbe Versionsnummer beibehält. Ihre OSS-Pakete möchten jedoch möglicherweise nicht ohne Änderungen verzweigt werden. Daher ist es am besten, ein Skript mit Abhängigkeiten beizubehalten - also Version 5 für Ihr Produkt ist das OSS-Modul X v2 usw. erforderlich.

Sie würden Ihr Skript so ändern, dass es nicht mehr auf Versionen verweist und stattdessen mit den Zweignamen arbeitet (obwohl dies alles sein kann, ist es am besten, sich für eine feste Namenskonvention zu entscheiden, z. B. Release_1_2_3).

Ein weiterer Hinweis besteht darin, mit jedem Modul, das die aktuelle Version beschreibt, eine Datei zu verwalten. Sie können diese bei Bedarf automatisch generieren und möglicherweise auch ein vollständiges Änderungsprotokoll hinzufügen. Dies bedeutet jedoch, dass jeder sehen kann, welche Version bereitgestellt wird, indem er nur nachschaut.

gbjbaanb
quelle
1

Ich denke, Sie haben bereits viele gute Ideen, ich habe die meisten im Laufe der Jahre für verschiedene Projekte verwendet, und Ihr Hauptanliegen scheint die Unfähigkeit zu sein, zu sagen, welche Version aller Module in einem bestimmten Paket enthalten war, wenn Sie sich teilen sie auf.

Ich bin alle dafür, sie auf einer bestimmten Granularitätsebene aufzuteilen, insbesondere wenn Sie mehrere Teams und unterschiedliche Veröffentlichungszyklen haben, wie @ Ext3h erwähnt.

Da ich nicht sicher bin, wie isoliert Ihre Module sind oder wie detailliert Ihre Versionierung sein soll, schlage ich einige Optionen vor.


Verwenden Sie Git-Submodule. Mit Submodulen können Sie jedes Modul in einem separaten Git-Repo speichern, ähnlich wie bei Ihrem SVN-Setup und auch bei Ihren Vorstellungen. Anschließend verknüpfen Sie diese Module mit dem Stammprojekt, das für jedes seiner eigenen Commits einen Verweis auf das relevante Commit jedes Submoduls enthält.

IMO ist dies ein theoretisch schönes Setup und ziemlich einfach. Die Hauptnachteile sind, dass der Workflow für Submodule etwas umständlich ist. Sie scheinen solche Dinge jedoch zuvor mit Skripten gut gelöst zu haben, sodass dies möglicherweise kein wirkliches Problem darstellt.

Die andere Einschränkung ist, dass Commit-Referenzen für Submodule nur ein SHA1 sind, es nie lesbare Details zu Ihrem Zweig gibt und Sie möglicherweise den richtigen Zweig manuell auschecken müssen, wenn Sie direkt im Submodul arbeiten möchten.

Ich habe dieses Muster jedoch nicht ausgiebig verwendet, daher weiß ich nicht, wie problematisch es für ein großes Projekt wie Ihres sein könnte.


Eine andere Alternative ist die Verwendung eines Abhängigkeitsmanagers. Dies erfordert, dass jedes Modul oder jeder Satz von Modulen einzeln versioniert, verpackt und veröffentlicht werden kann und dass Sie über ein System verfügen, das diese Pakete nach Ihren Wünschen zusammenführt.

Sie schlagen pip bereits vor, und was in Ihrem Vorschlag anscheinend fehlt, ist das Speichern der resultierenden Anforderungen.txt zusammen mit dem Build oder im Stammprojekt-Repo, damit Sie die virtuelle Umgebung später neu erstellen können, anstatt sie speichern zu müssen es auf der Festplatte.

Es gibt auch andere Systeme; Ich habe ein ziemlich großes Projekt mit einer leicht angepassten Version von Apache Ivy eingerichtet, um die einzelnen Module zu verpacken und zu veröffentlichen sowie sie für das endgültige Projekt zusammenzuführen. Ivy speichert auch ein Manifest, in dem alle Versionen aller Module aufgelistet sind, auf die Sie verweisen, wenn Sie das Setup später neu erstellen müssen.

axl
quelle