Umgang mit mehreren Zweigen in kontinuierlicher Integration

85

Ich habe mich in meinem Unternehmen mit dem Problem der Skalierung von CI befasst und gleichzeitig versucht, herauszufinden, welchen Ansatz ich bei CI und mehreren Niederlassungen wählen soll. Es gibt eine ähnliche Frage bei Stackoverflow, Zweigen mehrerer Features und kontinuierlicher Integration . Ich habe eine neue gestartet, weil ich mehr Diskussion und Analyse in der Frage haben möchte.

Bisher habe ich festgestellt, dass es zwei Hauptansätze gibt, die ich verfolgen kann (oder vielleicht einige andere ???).

Wenn ich Entwicklern CI für ihre eigenen benutzerdefinierten Zweige zur Verfügung stellen möchte, benötige ich anscheinend spezielle Tools für Jenkins (API oder Shellscripts oder so?) Und die Skalierung. Oder ich kann ihnen sagen, dass sie häufiger mit DEV fusionieren und ohne CI in benutzerdefinierten Zweigen leben sollen. Welches würdest du nehmen oder gibt es andere Möglichkeiten?

toomasr
quelle

Antworten:

69

Wenn Sie über die Skalierung von CI sprechen, sprechen Sie wirklich über die Skalierung der Verwendung Ihres CI-Servers, um alle Ihre Feature-Zweige zusammen mit Ihrer Hauptlinie zu verwalten. Dies scheint zunächst ein guter Ansatz zu sein, da die Entwickler in einer Branche alle Vorteile der automatisierten Tests nutzen, die die CI-Jobs beinhalten. Sie haben jedoch Probleme beim Verwalten der CI-Server-Jobs (wie Sie festgestellt haben), und was noch wichtiger ist, Sie führen CI nicht wirklich aus. Ja, Sie verwenden einen CI-Server, integrieren jedoch nicht kontinuierlich den Code aller Ihrer Entwickler.

Wenn Sie ein echtes CI ausführen, verpflichten sich alle Ihre Entwickler regelmäßig zur Hauptleitung. Einfach zu sagen, aber der schwierige Teil ist es, ohne Ihre Anwendung zu brechen. Ich empfehle Ihnen dringend, sich Continuous Delivery anzusehen , insbesondere den Abschnitt Keeping Your Application Releasable in Kapitel 13: Verwalten von Komponenten und Abhängigkeiten . Die Hauptpunkte sind:

  • Verstecken Sie neue Funktionen, bis sie fertig sind (AKA Feature Toggles ).
  • Nehmen Sie alle Änderungen schrittweise als eine Reihe kleiner Änderungen vor, von denen jede freigegeben werden kann.
  • Verwenden Sie Branch by Abstraction, um umfangreiche Änderungen an der Codebasis vorzunehmen.
  • Verwenden Sie Komponenten, um Teile Ihrer Anwendung zu entkoppeln, die sich unterschiedlich schnell ändern.

Sie sind ziemlich selbsterklärend, außer durch Abstraktion zu verzweigen. Dies ist nur ein ausgefallener Begriff für:

  1. Erstellen Sie eine Abstraktion über den Teil des Systems, den Sie ändern müssen.
  2. Refactorieren Sie den Rest des Systems, um die Abstraktionsschicht zu verwenden.
  3. Erstellen Sie eine neue Implementierung, die erst nach Abschluss Teil des Produktionscodepfads ist.
  4. Aktualisieren Sie Ihre Abstraktionsschicht, um sie an Ihre neue Implementierung zu delegieren.
  5. Entfernen Sie die alte Implementierung.
  6. Entfernen Sie die Abstraktionsschicht, wenn sie nicht mehr geeignet ist.

Der folgende Abschnitt aus dem Abschnitt Zweige, Streams und kontinuierliche Integration in Kapitel 14: Erweiterte Versionskontrolle fasst die Auswirkungen zusammen.

Der inkrementelle Ansatz erfordert sicherlich mehr Disziplin und Sorgfalt - und in der Tat mehr Kreativität - als die Schaffung eines Zweigs und das Eintauchen in die Neugestaltung und Entwicklung neuer Funktionen. Dies verringert jedoch das Risiko, dass Ihre Änderungen die Anwendung beschädigen, erheblich und spart Ihnen und Ihrem Team viel Zeit beim Zusammenführen, Beheben von Fehlern und Versetzen Ihrer Anwendung in einen bereitstellbaren Zustand.

Es ist ein ziemlicher Umdenken, Feature-Zweige aufzugeben, und Sie werden immer Widerstand bekommen. Nach meiner Erfahrung basiert dieser Widerstand darauf, dass Entwickler sich nicht sicher fühlen, Code als Hauptzeile zu verwenden, und dies ist ein vernünftiges Anliegen. Dies ist in der Regel auf mangelndes Wissen, Vertrauen oder Erfahrung mit den oben aufgeführten Techniken und möglicherweise auf mangelndes Vertrauen in Ihre automatisierten Tests zurückzuführen. Ersteres kann durch Schulung und Entwicklerunterstützung gelöst werden. Letzteres ist ein weitaus schwierigeres Problem. Die Verzweigung bietet jedoch keine zusätzliche echte Sicherheit. Sie verschiebt das Problem nur, bis sich die Entwickler mit ihrem Code sicher genug fühlen.

Tom Howard
quelle
4
Tom, das funktioniert nur, wenn 1) sowohl die Veröffentlichung als auch das Update vergleichsweise einfach sind 2) die meisten Ihrer Änderungen gut isoliert sind. Dies gilt für Webentwickler. Wenn Sie jedoch Produktversionen im Karton ausführen, müssen stabile Versionen um jeden Preis stabil bleiben, da Hotfixes in einer großen Unternehmensumgebung sehr teuer oder sogar unmöglich sind.
Jevgeni Kabanov
13
Bei echtem CI geht es nicht nur um Integration, sondern auch um Feedback
Anton Arhipov,
3
Ich habe dies als Antwort gewählt (zumindest das Kopfgeld gegeben, bitte lassen Sie mich wissen, wenn ich es irgendwie noch richtig markieren muss), aber ich denke, dies ist keine Lösung für mein Problem. Ich habe ein Follow-up unter zeroturnaround.com/blog/…
toomasr geschrieben
1
@Jevgeni Kabanov und @toomasr Sie scheinen beide davon auszugehen, dass echtes CI bedeutet, auf Qualität zu verzichten, und es funktioniert nur für Webentwickler, weil es so einfach ist, Korrekturen zu veröffentlichen. Ich vermute, dass Sie sich kurz vor einer Veröffentlichung Sorgen um ein zwielichtiges Commit machen. Ja, dies kann zu einer fehlerhaften Version führen, deren Behebung teuer sein kann. Ein zweifelhaftes Commit für einen Feature-Zweig kurz vor seiner Veröffentlichung ist jedoch genauso schlecht. Wenn Sie der Meinung sind, dass es einen Unterschied gibt, teilen Sie uns bitte Ihre Argumentation mit. Eine Möglichkeit, dem entgegenzuwirken (wenn sich das Commit auf der Hauptlinie oder einem Feature-Zweig befand), ist die Verwendung des Continuous Delivery-Ansatzes.
Tom Howard
1
Übrigens, in den letzten 4 Jahren war meine Hauptentwicklungserfahrung bei Finanzinstituten. Die Notwendigkeit, stabile Releases zu haben, und die Kosten für Fehler (ganz zu schweigen von dem Änderungskontrollprozess, den Sie durchlaufen müssen, um einen Hotfix herauszubringen) werden nicht viel höher. Ein verpacktes Produkt wäre für mich eine entspannende Abwechslung.
Tom Howard
4

Ich würde für jede Niederlassung separate Jobs einrichten. Ich habe das schon einmal gemacht und es ist nicht schwer zu verwalten und einzurichten, wenn Sie Hudson / Jenkins richtig eingerichtet haben. Eine schnelle Möglichkeit, mehrere Jobs zu erstellen, besteht darin, von einem vorhandenen Job mit ähnlichen Anforderungen zu kopieren und diese nach Bedarf zu ändern. Ich bin mir nicht sicher, ob Sie jedem Entwickler erlauben möchten, seine eigenen Jobs für seine eigenen Niederlassungen einzurichten, aber es ist nicht viel Arbeit für eine Person (dh einen Build-Manager), diese zu verwalten. Sobald die benutzerdefinierten Zweige zu stabilen Zweigen zusammengeführt wurden, können entsprechende Jobs entfernt werden, wenn sie nicht mehr benötigt werden.

Wenn Sie sich Sorgen über die Auslastung des CI-Servers machen, können Sie separate Instanzen des CI oder sogar separate Slaves einrichten, um die Auslastung auf mehrere Server zu verteilen. Stellen Sie sicher, dass der Server, auf dem Sie Hudson / Jenkins ausführen, ausreichend ist. Ich habe Apache Tomcat verwendet und musste nur sicherstellen, dass es über genügend Speicher und Rechenleistung verfügt, um die Build-Warteschlange zu verarbeiten.

Es ist wichtig, klar zu machen, was Sie mit CI erreichen möchten, und dann einen Weg zu finden, um es ohne großen manuellen Aufwand oder Doppelarbeit zu implementieren. Es ist nichts Falsches daran, andere externe Tools oder Skripte zu verwenden, die von Ihrem CI-Server ausgeführt werden, um Ihren gesamten Build-Management-Prozess zu vereinfachen.

Bernard
quelle
Ich denke, dieser Mangel an Werkzeugen bedeutet, dass in dieser Abteilung Platz für einige Plugins / Produkte ist. Würde nicht meine eigenen schreiben wollen.
Toomasr
1
Es gibt ein Dienstprogramm für Jenkins, das automatisch eine Build-Konfiguration für jeden Zweig erstellt: entagen.github.com/jenkins-build-per-branch
kolen
3

Ich würde dev + stabile Zweige wählen. Und wenn Sie immer noch benutzerdefinierte Zweige möchten und Angst vor der Last haben, verschieben Sie diese benutzerdefinierten in die Cloud und lassen Sie sie von Entwicklern selbst verwalten, z. B. http://cloudbees.com/dev.cb Dies ist das Unternehmen, in dem Kohsuke jetzt tätig ist . Es gibt auch ein Eclipse-Tool. Wenn Sie also Eclipse verwenden, wird es direkt in dev env integriert.

Anton Safonov
quelle
Werde ich den Mangel an Tools für die Verwaltung mehrerer Filialen gegen das gleiche Problem, aber in der Cloud, eintauschen? Ich meine, ich werde jetzt in der Lage sein, die Last zu verwalten, aber immer noch nicht die Zweige?
Toomasr
Ich wollte die Tools vergessen und das Management unter den Entwicklern verteilen - "Wenn Sie einen benutzerdefinierten persönlichen Build wünschen, ist hier Ihr CB-Konto". Ohne die Build-Leistung des Hauptservers zu beeinträchtigen. Obwohl ihre API ziemlich einfach ist, würde das Erstellen von Verwaltungs-Utils wahrscheinlich eine Frage von ein bis zwei Wochen sein, und dann tun Sie dort, was Sie wollen. Wie es im Leben üblich ist, ist es besser, wenn Sie etwas Besonderes wollen, es selbst zu tun. Gleichzeitig wachsen sie schnell und hören der Community zu. Füllen Sie also eine Feature-Anfrage aus und es kann sein, dass sie bald erscheint.
Anton Safonov
Oh, verstanden. Sagen Sie dem Filialbesitzer, dass die Kirsche die Jobs auswählt, an denen er interessiert ist, und richten Sie sie nach Belieben für seine benutzerdefinierte Filiale ein. Ich mag diese Idee.
Toomasr
1

Was wirklich problematisch ist, ist die Build-Isolation mit Feature-Zweigen. In unserem Unternehmen haben wir eine Reihe von separaten Maven-Projekten, die alle Teil einer größeren Distribution sind. Diese Projekte werden von verschiedenen Teams verwaltet, aber für jede Distribution müssen alle Projekte freigegeben werden. Eine Feature-Branche kann sich jetzt von einem Projekt zum anderen überschneiden, und das ist der Fall, wenn die Build-Isolation schmerzhaft wird. Wir haben verschiedene Lösungen ausprobiert:

  • Erstellen Sie für jeden Feature-Zweig separate Snapshot-Repositorys im Nexus
  • Teilen Sie lokale Repositorys auf dedizierten Slaves
  • Verwenden Sie das Repository-Server-Plugin mit Upstream-Repositorys
  • Erstellen Sie alles innerhalb eines Jobs mit einem privaten Repository

Tatsächlich ist die letzte Lösung die vielversprechendste. Alle anderen Lösungen fehlen auf die eine oder andere Weise. Zusammen mit dem job-dsl-Plugin ist es einfach, einen neuen Feature-Zweig einzurichten. Kopieren Sie einfach das groovige Skript und fügen Sie es ein, passen Sie Zweige an und lassen Sie den Seed-Job die neuen Jobs erstellen. Stellen Sie sicher, dass der Seed-Job nicht verwaltete Jobs entfernt. Dann können Sie problemlos mit Feature-Zweigen über verschiedene Maven-Projekte skalieren.

Aber wie Tom oben bereits sagte, wäre es besser, die Notwendigkeit von Feature-Zweigen zu überwinden und Entwicklern die saubere Integration beizubringen. Dies ist jedoch ein längerer Prozess, und das Ergebnis ist bei vielen älteren Systemteilen, die Sie nicht mehr berühren, nicht klar.

meine 2 Cent

Prosailor
quelle