it-swarm.com.de

Wie vermeiden wir CI-gesteuerte Entwicklung ...?

Ich arbeite an einem sehr großen forschungsgeleiteten Open-Source-Projekt mit einer Reihe anderer regelmäßiger Mitarbeiter. Da das Projekt jetzt ziemlich groß ist, ist ein Konsortium (bestehend aus zwei Vollzeitbeschäftigten und wenigen Mitgliedern) für die Aufrechterhaltung des Projekts, die kontinuierliche Integration (CI) usw. verantwortlich. Sie haben einfach keine Zeit für die Integration externer Mitarbeiter Beiträge allerdings.

Das Projekt besteht aus einem "Kern" -Framework, etwa einer halben Million Codezeilen, einer Reihe von "Plugins", die vom Konsortium verwaltet werden, und mehreren externen Plugins, von denen die meisten nicht vorhanden sind. Ich bin mir nicht einmal bewusst.

Derzeit erstellt unser CI den Kern und die gepflegten Plugins.

Eines der großen Probleme, mit denen wir konfrontiert sind, ist, dass die meisten Mitwirkenden (und insbesondere die gelegentlichen) nicht 90% der gepflegten Plugins erstellen. Wenn sie also Änderungen im Kern umgestalten (was heutzutage recht regelmäßig geschieht), Sie überprüften, ob der Code auf ihrem Computer kompiliert wurde, bevor sie eine Pull-Anfrage auf GitHub stellten.

Der Code funktioniert, sie sind glücklich, und dann beendet das CI die Erstellung und die Probleme beginnen: Die Kompilierung ist in einem vom Konsortium verwalteten Plugin fehlgeschlagen, das der Mitwirkende nicht auf seinem Computer erstellt hat.

Dieses Plugin kann Abhängigkeiten von Bibliotheken von Drittanbietern aufweisen, wie z. B. CUDA , und der Benutzer möchte nicht, weiß nicht wie oder kann es einfach Kompilieren Sie das kaputte Plugin nicht aus Hardware-Gründen.

Also dann - entweder bleibt der PR ad aeternam in der Schwebe des nie zu verschmelzenden PRs - oder der Mitwirkende greift nach der umbenannten Variablen in der Quelle des defekten Plugins, ändert den Code und geht weiter Sein Zweig wartet darauf, dass das CI die Kompilierung abgeschlossen hat, erhält normalerweise mehr Fehler und wiederholt den Vorgang, bis CI zufrieden ist. Oder einer der beiden bereits überbuchten bleibenden Karten im Konsortium hilft und versucht, die PR auf ihrem zu reparieren Maschine.

Keine dieser Optionen ist realisierbar, aber wir wissen einfach nicht, wie wir es anders machen sollen. Wurden Sie jemals mit einer ähnlichen Situation Ihrer Projekte konfrontiert? Und wenn ja, wie sind Sie mit diesem Problem umgegangen? Gibt es eine Lösung, die ich hier nicht sehe?

45
lagarkane

CI-gesteuerte Entwicklung ist in Ordnung! Dies ist viel besser, als keine Tests auszuführen und fehlerhaften Code einzuschließen! Es gibt jedoch einige Dinge, die dies für alle Beteiligten einfacher machen:

  • Erwartungen festlegen : Beitragsdokumentation, in der erklärt wird, dass CI häufig zusätzliche Probleme findet und diese vor a behoben werden müssen verschmelzen. Erklären Sie vielleicht, dass kleinere lokale Änderungen mit größerer Wahrscheinlichkeit gut funktionieren. Daher kann es sinnvoll sein, eine große Änderung in mehrere PRs aufzuteilen.

  • Ermutigen Sie lokale Tests: Erleichtern Sie das Einrichten einer Testumgebung für Ihr System. Ein Skript, das überprüft, ob alle Abhängigkeiten installiert wurden? Ein Docker-Container, der bereit ist? Ein Image einer virtuellen Maschine? Verfügt Ihr Testläufer über Mechanismen, mit denen wichtigere Tests priorisiert werden können?

  • Erklären Sie, wie Sie CI für sich selbst verwenden können: Ein Teil der Frustration ist, dass dieses Feedback erst nach dem Einreichen einer PR erfolgt. Wenn die Mitwirkenden CI für ihre eigenen Repositorys einrichten, erhalten sie früheres Feedback - und erstellen weniger CI-Benachrichtigungen für andere Personen.

  • Lösen Sie alle PRs so oder so: Wenn etwas nicht zusammengeführt werden kann, weil es kaputt ist, und wenn es keine Fortschritte bei der Behebung der Probleme gibt, schließen Sie es einfach. Diese verlassenen offenen PRs überladen einfach alles, und jedes Feedback ist besser, als das Problem einfach zu ignorieren. Es ist möglich, dies sehr schön auszudrücken und klar zu machen, dass Sie sich natürlich gerne zusammenschließen würden, wenn die Probleme behoben sind. (siehe auch: Die Kunst des Schließens von Jessie Frazelle , Best Practices für Maintainer: Lernen, nein zu sagen )

    Erwägen Sie auch, diese verlassenen PRs auffindbar zu machen, damit jemand anderes sie abholen kann. Dies kann sogar eine gute Aufgabe für neue Mitarbeiter sein, wenn die verbleibenden Probleme mechanischer sind und keine gründliche Vertrautheit mit dem System erfordern.

Auf lange Sicht scheinen Änderungen, die nicht verwandte Funktionen so oft zu beeinträchtigen scheinen, dass Ihr aktuelles Design etwas problematisch ist. Kapseln die Plugin-Schnittstellen beispielsweise die Interna Ihres Kerns ordnungsgemäß ein? C++ erleichtert das versehentliche Durchsickern von Implementierungsdetails, ermöglicht jedoch auch das Erstellen starker Abstraktionen, die nur sehr schwer missbraucht werden können. Sie können dies nicht über Nacht ändern, aber Sie können die langfristige Entwicklung der Software hin zu einer weniger fragilen Architektur vorantreiben.

68
amon

Um ein nachhaltiges Plugin-Modell zu erstellen, muss Ihr Kernframework eine stabile Schnittstelle bereitstellen, auf die sich Plugins verlassen können. Die goldene Regel lautet, dass Sie im Laufe der Zeit neue Schnittstellen einführen können, eine bereits veröffentlichte Schnittstelle jedoch niemals ändern können. Wenn Sie dieser Regel folgen, können Sie das Implementierung des Kernframeworks nach Ihren Wünschen umgestalten, ohne befürchten zu müssen, dass Plugins versehentlich beschädigt werden, unabhängig davon, ob es sich um ein vom Konsortium verwaltetes oder ein externes Plugin handelt.

Nach dem, was Sie beschrieben haben, klingt es so, als hätten Sie keine genau definierte Oberfläche, und das macht es schwierig zu sagen, ob eine Änderung Plugins beschädigen wird. Arbeiten Sie daran, diese Schnittstelle zu definieren und in Ihrer Codebasis explizit zu machen, damit die Mitwirkenden wissen, was sie nicht ändern sollten.

34
casablanca

Um ehrlich zu sein, glaube ich nicht, dass Sie damit besser umgehen können - wenn Änderungen dazu führen, dass beschädigte Teile Ihres Projekts beschädigt werden das CI fehlschlagen sollte.

Hat Ihr Projekt ein contributing.md oder ähnliches, um neuen und gelegentlichen Mitwirkenden bei der Vorbereitung ihrer Beiträge zu helfen? Haben Sie eine klare Liste, welche Plugins Teil des Kerns sind und kompatibel bleiben müssen?

Wenn es aufgrund von Abhängigkeiten usw. schwierig ist, alles auf einem Computer zu erstellen, können Sie gebrauchsfertige Docker-Images als Build-Umgebungen für Ihre Mitwirkenden erstellen.

8
mhr

als sie vorschlugen, Änderungen im Kern umzugestalten (was heutzutage ziemlich regelmäßig geschieht), überprüften sie, ob der Code auf ihrem Computer kompiliert wurde, bevor sie eine Pull-Anfrage für Github stellten.

Ich denke, hier kann der lockere Stil von Open Source-Projekten ins Wanken geraten. Die meisten zentral organisierten Projekte sind vorsichtig beim Core Refactoring, insbesondere wenn es eine API-Grenze überschreitet. Wenn sie eine API-Grenze umgestalten, ist dies normalerweise ein "Urknall", bei dem alle Änderungen auf einmal mit einem Inkrement zur API-Hauptversion geplant werden. nd Die alte API wird beibehalten.

Ich würde eine Regel vorschlagen "Alle API-Änderungen müssen im Voraus geplant werden": Wenn eine PR eingeht, die eine rückwärts inkompatible Änderung an der API vornimmt, von jemandem, der nicht mit den Betreuern in Kontakt war, um ihren Ansatz im Voraus zu vereinbaren, ist dies der Fall wird einfach geschlossen und der Einsender zeigt auf die Regel.

Sie benötigen außerdem eine explizite Versionierung der Plugin-API. Auf diese Weise können Sie v2 entwickeln, während alle v1-Plugins weiterhin erstellt werden und funktionieren.

Ich würde auch ein bisschen mehr fragen warum so viele Kern-Refactoring- und API-Änderungen werden vorgenommen. Sind sie wirklich notwendig oder nur Menschen, die dem Projekt ihren persönlichen Geschmack aufzwingen?

8
pjc50

Klingt so, als müsste der CI-Prozess straffer, umfassender und für die Mitwirkenden sichtbarer sein, bevor sie eine PR erheben. BitBucket verfügt beispielsweise über eine Pipelines-Funktion, die dies ermöglicht. Sie geben ihm eine Datei, die den CI-Erstellungsprozess im Code definiert. Wenn dies fehlschlägt, wird verhindert, dass der Zweig zusammengeführt wird.

Unabhängig von der Technologie erhalten Sie durch die Bereitstellung automatischer Builds, wenn ein Mitarbeiter in eine Zweigstelle wechselt, viel schneller eine Rückmeldung darüber, auf welche Fallstricke bei Änderungen zu achten ist, und führen zu PRs, die nachträglich nicht repariert werden müssen.

Designprobleme lassen sich gut beheben, sind jedoch orthogonal zu diesem Problem.

2
Nathan Adams

Der Code funktioniert, sie sind glücklich, und dann beendet das CI die Erstellung und die Probleme beginnen: Die Kompilierung ist in einem vom Konsortium verwalteten Plugin fehlgeschlagen, das der Mitwirkende nicht auf seinem Computer erstellt hat.

Dieses Plugin kann Abhängigkeiten von Bibliotheken von Drittanbietern aufweisen, wie z. B. CUDA, und der Benutzer möchte, weiß nicht, wie er dieses defekte Plugin kompilieren kann oder kann es aus Hardwaregründen einfach nicht.

Ihre Lösung ist einfach: Senkung der Beitragsbarriere.

Der einfachste Weg, um (1) den Edit-Compile-Test-Zyklus zu beschleunigen und (2) Umgebungsunterschiede auszugleichen, besteht darin, Build-Server bereitzustellen:

  • Nehmen Sie leistungsstarke Maschinen auf: 24, 48 oder 96 Kerne, 2 GB RAM/Core, SSD, um die Kompilierung zu beschleunigen.
  • Stellen Sie sicher, dass sie über die richtige Hardware verfügen: FPGA, Grafikkarte, was auch immer benötigt wird.
  • Erstellen Sie ein Docker-Image mit allen erforderlichen vorinstallierten Softwarebibliotheken.

Öffnen Sie dann diese Build-Server für Mitwirkende. Sie sollten in der Lage sein, sich remote in einem neuen Docker-Image anzumelden und den Kompilierungstest auf diesem Computer remote zu bearbeiten.

Dann:

  • Sie haben keine Entschuldigung dafür, die gepflegten Plugins nicht zu erstellen/zu testen: Sie haben alles zur Verfügung.
  • Sie müssen nicht auf langwierige Rückmeldungen mit CI-gesteuerten PRs warten: Sie verfügen über eine inkrementelle Kompilierung und die Möglichkeit zum Debuggen (anstatt zu raten).

Im Allgemeinen können Build-Server von mehreren Mitwirkenden gemeinsam genutzt werden. Wenn jedoch spezielle Hardware-Peripheriegeräte beteiligt sind, kann es erforderlich sein, dass ein Mitwirkender dieses Peripheriegerät selbst verwendet.


Quelle: Wenn Sie an Software mit FPGAs arbeiten, finden Sie angesichts des Preises der Bestien und der Vielzahl der benötigten Modelle nicht jedes FPGA-Modell auf jedem Entwicklercomputer installiert.

2
Matthieu M.

Wenn ein Beitrag zum Kern ohne Vertragsänderung die abhängige Software beschädigen kann, schlägt dies Folgendes vor:

  • Die Verträge Ihrer Schnittstellen können mehrdeutig sein. Vielleicht hilft das Hinzufügen von Attributen zu Ihren Funktionen und Funktionsparametern dabei, dem Clientcode zusätzliche Einschränkungen aufzuerlegen, um die Verträge klarer zu gestalten. Wenn Sie vertragswidrige Änderungen vornehmen, kann die Einführung einer semantischen Versionierung hilfreich sein.
  • Die Unit-Tests decken nicht genügend mögliche Anrufszenarien ab.

Beide Probleme sollten leicht zu lösen sein, aber Sie erwähnen, dass das Kernteam möglicherweise nicht in der Lage ist, dies zu tun. Eine Möglichkeit wäre, die Community um Hilfe bei der Lösung des Problems zu bitten.

1
jcayzac

Niemand sonst scheint dies als mögliche Lösung angesprochen zu haben.

  • listen Sie alle Plugins auf, auf die Sie zugreifen können.
  • führen Sie alle Tests aus, die diese Plugins definieren
  • zeichnen Sie alle Anfragen/Antworten/Interaktionen zwischen dem Core und allen Plugins auf
  • speichern Sie diese Aufzeichnungen, dies sind jetzt grobe Kompatibilitätstests.

Ermutigen Sie Entwickler bei der Entwicklung des Kerns, diese Kompatibilitätstests durchzuführen. Wenn sie fehlschlagen, checken Sie nicht ein.

Dies wird die Kompatibilität nicht zu 100% gewährleisten, aber es werden viel mehr Probleme frühzeitig erkannt.

Ein sekundärer Vorteil besteht darin, dass diese Aufzeichnungen hervorheben können, welche Schnittstellen aktiv verwendet werden und welche Funktionen aktiv verwendet werden.

1
Kain0_0

Ich habe Probleme, die Situation so zu verstehen, wie sie zu sein scheint: Das CI baut nur einen Zweig?

Gibt es einen Grund, warum Sie mit dem CI nicht mehr als einen Zweig erstellen können?

Die einfachste Lösung für dieses Problem wäre es jedem Mitwirkenden ermöglichen, den CI-Build auf seinem Feature-Zweig auszuführen.

Dann benötigen Sie einfach einen erfolgreichen CI-Build für den Feature-Zweig, damit die Pull-Anforderung dieses Zweigs akzeptiert wird.

0
Kyralessa