Automatische Wiederherstellung von Commits, bei denen der Build fehlschlägt

43

Ein Kollege von mir sagte mir, dass er daran denkt, unseren CI-Server dazu zu bringen, Commits wiederherzustellen, bei denen der Build fehlgeschlagen ist, so dass das HEADIn masterimmer stabil ist (zumindest, wenn der Build übergeben wird).

Handelt es sich um eine bewährte Methode, oder ist es problematischer, masterwenn das Programm erst dann unterbrochen wird, wenn der Entwickler das Problem behoben hat?

Ich denke, dass das Zurücksetzen des Commits die Aufgabe des Lesens des Commits und des Fixes komplexer machen wird (Entwickler müssen das Zurücksetzen zurücksetzen und dann den Fix zurücksetzen, der auch den Fehler verursacht git log), und wir sollten einfach den Commit verlassen und dann den Commit ausführen Fix. Obwohl ich einige Vorteile darin sehe, masterstabil zu sein, überzeugt mich diese Rückkehr zu fehlgeschlagenen Commits nicht.

edit: Egal ob es sich um mastereinen anderen Entwicklungszweig handelt, aber die Frage bleibt gleich: Sollte das CI-System ein Commit zurücksetzen, das den Build nicht bestanden hat?

noch ein (längen-) edit: ok, wir verwenden es gitauf seltsame weise . Wir sind der Meinung, dass das Konzept von Zweigniederlassungen gegen echte CI verstößt, da Sie durch das Festschreiben an einer Zweigniederlassung von den anderen Entwicklern und deren Änderungen isoliert werden und Sie mehr Zeit benötigen, um Ihre Zweigniederlassung wieder zu integrieren und mögliche Konflikte zu lösen. Wenn sich alle an masterdiesen Konflikten beteiligen, werden diese auf ein Minimum reduziert und jeder Commit besteht alle Tests.

Dies zwingt Sie natürlich dazu, nur stabile Funktionen zu verwenden (oder den Build zu unterbrechen) und sorgfältiger zu programmieren, um die Abwärtskompatibilität nicht zu beeinträchtigen oder Funktionen umzuschalten, wenn Sie neue Funktionen einführen.

Es gibt Kompromisse, wenn CI auf diese oder jene Weise durchgeführt wird, aber dies ist nicht in Frage zu stellen (siehe dazugehörige Frage ). Wenn Sie es vorziehen, kann ich die Frage umformulieren: Ein kleines Entwicklerteam arbeitet in einem Feature-Zweig zusammen. Wenn ein Entwickler etwas festschreibt, das den Build für diesen Zweig unterbricht, sollte das CI-System das Festschreiben rückgängig machen oder nicht?

Carlos Campderrós
quelle
38
Fehlgeschlagene Builds sollten mastervon Anfang an nie erreicht haben . Dafür werden Entwicklungs- und Feature-Zweige verwendet. Diese Änderungen gehen dann in so etwas wie einen Integrationszweig, in dem Sie testen können, ob alle neuen Funktionen mehrerer Entwickler zusammenarbeiten, und nur, wenn dies in getestet wurde, in master übernommen werden können. Zumindest ist das ein möglicher Workflow.
thorsten müller
1
@ thorstenmüller stell dir also gut vor, dass es sich um einen Entwicklungszweig handelt, den alle Entwickler nutzen. Sollte das CI-System Commits wiederherstellen, bei denen der Build fehlschlägt?
Carlos Campderrós
7
Es scheint, dass Sie git auf seltsame Weise verwenden. Im Allgemeinen sollten die Leute in ihren eigenen Filialen an ihren eigenen Repos arbeiten und nur dann auf main klicken, wenn das CI für ihren persönlichen Build bestätigt wurde, dass die Änderungen in Ordnung sind.
Wilbert
4
> "diese Konflikte werden auf ein Minimum reduziert"; Beim Zusammenführen treten weniger Konflikte auf, bei fehlerhaften Zusammenführungen treten jedoch weitaus mehr Probleme auf. Die Lösung besteht darin, als Teil Ihres Prozesses kontinuierlich vom Master zum Zweig zusammenzuführen und nicht zu verzweigen.
Deworde
2
... Warum macht man es nicht so, dass fehlerhafte Builds zunächst nicht in den Master aufgenommen werden?
user253751

Antworten:

55

Ich würde dies aus folgenden Gründen ablehnen:

  • Jedes Mal, wenn Sie ein automatisiertes Tool zum Ändern von Code in Ihrem Namen einrichten, besteht das Risiko, dass dieser falsch ist oder dass eine Situation auftritt, in der Sie die Änderung beenden müssen (z. B. die neueste Version von Google Mock) hatte einen Fehler, so dass Ihr Code nicht fehlerhaft ist) und Sie müssen Zeit damit verschwenden, ihn neu zu konfigurieren. Außerdem besteht immer ein geringes Risiko, dass der Build aufgrund eines Fehlers im Build-System fehlschlägt, und nicht aufgrund eines Fehlers im Code. Bei CI geht es mir darum, das Vertrauen zu gewinnen, dass mein Code korrekt ist. dies würde es lediglich zu einer weiteren Quelle potenzieller Probleme machen, über die ich mir Sorgen machen müsste.

  • Die Arten von Fehlern, die "den Build" zerstören, sollten alberne Fehler sein, deren Behebung nur sehr wenig Zeit in Anspruch nimmt (wie Sie in einem Kommentar angegeben haben, gilt dies für Sie). Wenn subtilere und kompliziertere Fehler es regelmäßig auf den Master schaffen, besteht die richtige Lösung nicht darin, sie "schneller zu beheben", sondern beim Überprüfen von Feature-Zweigen vor dem Zusammenführen vorsichtiger vorzugehen.

  • Es tut niemandem weh, den Meister für ein paar Minuten unaufbaubar zu lassen, während der Fehler behoben wird. Es ist nicht so, dass der CEO den Master persönlich überprüft und den Code zu jedem beliebigen Zeitpunkt direkt an die Kunden veröffentlicht (zumindest hoffentlich nicht ohne Ihr Zutun). Im höchst unwahrscheinlichen Fall , dass Sie etwas zu lösen, bevor Sie den Fehler beheben können, dann können Sie ganz einfach die Entscheidung treffen , manuell zurückzukehren , die vor der Veröffentlichung.

Ixrec
quelle
1
Außerdem sollten nur erfolgreiche Builds die Erstellung eines "Build Drop" auslösen, der bereitgestellt werden kann. Wenn ein Build fehlschlägt, sollte es keinen bereitstellbaren Build-Drop geben, sodass kein Risiko besteht, dass jemand fehlerhaften Code für Clients veröffentlicht.
Mark Freedman
1
Es gibt definitiv eine andere Option, die verwendet wird und die besser ist als diese, denke ich, und die häufig verwendet wird (wir verwenden sie bei Twitter). Setzen Sie keine fehlgeschlagenen Builds auf Master UND alberne Fehler, die auch noch leicht zu beheben sind. Siehe meine vollständige Antwort unten.
Dean Hiller
26

Lassen Sie uns zunächst die Bedingungen vereinbaren.

Ich persönlich verwende die Begriffe Continuous Build und Continuous Integration, um zwei verschiedene Szenarien zu unterscheiden:

  • Continuous Build: Ein Tool, das regelmäßig überprüft, ob sich das Repository seit dem letzten Build geändert hat, und ob dies der Fall ist.
  • Kontinuierliche Integration: Ein Tool, das Pull-Requests aufnimmt und anhand des neuesten Heads überprüft, bevor sie sichtbar gemacht werden.

Letzteres, Continuous Integration, bedeutet, dass das Repository, das es schützt, immer grün ist 1 : Es ist strikt besser.

Ihre Frage ist nur für Continuous Build wirklich sinnvoll, daher werde ich antworten, wenn dies Ihr Setup ist.

1 : Umwelteinflüsse können auch einen Build vermasseln, zum Beispiel kann ein Test mit einem fest programmierten Jahr (2015) im Januar 2016 scheitern, eine Festplatte kann voll werden, ... und natürlich gibt es die Plage der Instabilität Tests. Ich ignoriere diese Themen hier hochmütig. sonst kommen wir nie weiter.


Wenn Sie ein Setup für die fortlaufende Erstellung haben, können Sie die Umkehrung von Festschreibungen, die die Erstellung möglicherweise unterbrochen haben, zwar automatisieren, es gibt jedoch mehrere Feinheiten.

  • Sie können die Commits nicht wirklich entfernen: Andere Mitarbeiter haben sie möglicherweise bereits ausgecheckt und werden sie beim nächsten Versuch, sie zu übernehmen, zurückschieben. Stattdessen sollte eine Umkehrung ein umgekehrtes Diff begehen . Oh, und Mitarbeiter werden Sie dafür hassen, dass Sie ihre Arbeit zurückgesetzt haben, als es richtig war, da sie einen Weg finden müssen, sie wieder zurückzudrängen ...
  • Sie können nicht nur das letzte Commit entfernen (es ist eine Zusammenführung), sondern müssen alle Commits entfernen ... bis zu einem bestimmten Punkt. Zum Beispiel das letzte als funktionierend bekannte Commit (Vorsicht beim Booten des Systems).
  • Sie müssen über externe Ursachen nachdenken (Umweltprobleme) und ein Setup vermeiden, bei dem alles auf Tag 0 zurückgesetzt wird. Glücklicherweise können Sie dieses Problem umgehen, indem Sie zum letzten bekannten Good Commit zurückkehren.
  • Sie müssen bedenken, dass der letzte bekannte funktionierende Build möglicherweise nicht mehr erstellt wird (Umgebungsprobleme). In diesem Fall werden wahrscheinlich alle weiteren Commits rückgängig gemacht. Im Idealfall sollten Sie im Falle eines Fehlers vor dem Zurücksetzen den letzten als funktionierend bekannten Build auschecken und erneut testen. Wenn es erfolgreich ist, kehren Sie zurück, andernfalls lösen Sie eine Warnung aus.

Beachten Sie, dass mit diesem System im Falle eines instabilen Tests oder eines Mitarbeiters, der häufig Mist begeht, viele gute Commits rückgängig gemacht werden. Ihre Mitarbeiter werden Sie dann hassen.


Hoffentlich hat meine Horrorgeschichte die Probleme aufgedeckt, ein defektes Repository zuzulassen, und Sie werden jetzt eine ordnungsgemäße Continuous Integration-Pipeline implementieren, bei der PR nie direkt in das Repository verschoben, sondern zum Zusammenführen in eine Arbeitswarteschlange eingereiht und einzeln integriert werden ( oder durch Roll-ups):

  • Abrufen des Head of Repository lokal
  • Pull Request (s) anwenden
  • bauen und testen
  • Im Erfolgsfall in das Repository verschieben, andernfalls als fehlgeschlagen markieren
  • weiter zu den nächsten Anfragen

Beides probiert zu haben, ist strikt besser.

Matthieu M.
quelle
2
Dies ist in der Tat die richtige Antwort - die richtige Lösung besteht darin, zu verhindern, dass böse Änderungen jemals den Master-Zweig erreichen, ihn nicht landen zu lassen und ihn dann zurückzurollen.
Daniel Pryden
Ich denke, das Problem hierbei ist, dass der Fragesteller der Meinung ist, dass die angegebenen Kosten für die "Isolierung von Ihnen von den anderen Entwicklern und deren Änderungen" die Vorteile überwiegen. Die angegebenen Kosten sind die erhöhte Gefahr nicht-trivialer Zusammenschlüsse, je länger zwei Personen auseinander gehen. IMO ist der Vorteil der Isolierung von defektem Code offensichtlich. Der Fragesteller möchte eine "optimistische" Strategie verfolgen, bei der defekter Code kurz verfügbar ist, um abgerufen masterzu werden, und diese Situation dann beheben, wenn die Tests fehlschlagen. Alle anderen verfolgen eine "pessimistische" Strategie und stellen nur Code zum Abrufen zur Verfügung.
Steve Jessop
( masterWobei mit "Verfügbar zum Abrufen" "Abrufen von " gemeint ist, was Entwickler im Idealfall problemlos tun können. Um dies zu erreichen, müssen Sie jedoch das Eintreffen von Commits verzögern, masterbevor sie getestet und bestanden werden. Wenn ein Entwickler dies möchte Wählen Sie ungetesteten oder getesteten und fehlgeschlagenen Code aus, der auch in Ordnung ist, und der Code ist in diesem Sinne "verfügbar". Es ist nur nicht das, worauf ich mich beziehe.)
Steve Jessop
Die richtige Lösung besteht darin, zu verhindern, dass böse Änderungen jemals eine beliebige Filiale erreichen. Fehlgeschlagene Commits sollten niemals veröffentlicht werden.
Miles Rout
5

Ist dies eine bewährte Methode oder ist es problematischer, den Master nur so lange kaputt zu lassen, bis der Entwickler das Problem behoben hat?

Das ist problematisch. Eine Person, die entscheidet, "der Master-HEAD ist kaputt; ich werde die oberste Änderung rückgängig machen", ist völlig anders als das CI-System, das dasselbe tut.

Hier einige Nachteile:

  • Fehler im automatisierten Stornierungsprozess werden das Repository durcheinander bringen.

  • Dies setzt voraus, dass ein einzelner Änderungssatz (der oberste) den Build vermasselt hat (was unrealistisch ist).

  • Die Betreuer haben mehr zu tun, um das Problem zu beheben, als nur Nachforschungen anzustellen und sich zu verpflichten (sie müssen sich auch die umgekehrte Historie ansehen).

Wir sind der Meinung, dass das Konzept von Zweigniederlassungen gegen echte CI verstößt, da Sie durch das Festschreiben an einer Zweigniederlassung von den anderen Entwicklern und deren Änderungen isoliert werden und mehr Zeit für die Reintegration Ihrer Zweigniederlassung und die Bewältigung möglicher Konflikte benötigt wird.

Diese Überzeugung (Branches vs. CI) ist falsch. Ziehen Sie in Betracht, einen stabilen Zweig beizubehalten , in dem Sie nur Unit-getestete Changesets festschreiben. Der Rest (Feature-Zweige und lokale Zweige) sollte in der Verantwortung jedes Entwicklers liegen und in keiner Weise Teil Ihrer CI-Richtlinie sein.

In Feature-Zweigen möchten Sie von anderen Entwicklern isoliert sein. Auf diese Weise können Sie:

  • Erkundungscodierung durchführen

  • experimentieren Sie mit der Codebasis

  • Führen Sie teilweise Festschreibungen durch (schreiben Sie effektiv nicht funktionierenden Code fest), um Sicherungspunkte einzurichten (falls Sie Fehler machen), einen aussagekräftigeren Änderungsverlauf zu erstellen (durch Festschreibungsmeldungen) und Ihre Arbeit zu sichern und vollständig auf etwas anderes umzuschalten (in die Zeit, die Sie brauchen, um "git commit && git checkout" zu schreiben)

  • Aufgaben mit niedriger Priorität ausführen, die viel Zeit in Anspruch nehmen (z. B. möchten Sie ein Refactoring durchführen, das alle 80 Klassen der Datenschicht ändert: Sie ändern zwei pro Tag, bis Sie alle ändern und der Code kompiliert wird (dies ist jedoch möglich) ohne jemanden zu beeinflussen, bis Sie ein einzelnes Commit durchführen können).

Wenn ein Entwickler etwas festschreibt, das den Build für diesen Zweig unterbricht, sollte das CI-System das Festschreiben rückgängig machen oder nicht?

Das sollte es nicht. Das Festschreiben von stabilem Code in Ihrer CI-Filiale liegt in der Verantwortung des Committers und nicht in der Verantwortung eines automatisierten Systems.

utnapistim
quelle
2

Ich würde vorschlagen, eine Gerrit + Jenkins-Umgebung zu verwenden, um Ihre Hauptniederlassung immer in einem guten Zustand zu halten. Die Leute schicken ihren neuen Code an Gerrit, was einen Jenkins-Job zum Abrufen dieses Patches, Builds, Tests usw. auslöst. Wenn andere Entwickler wie Ihr Patch und Jenkins ihre Arbeit erfolgreich abschließen, führt Gerrit diesen Code in Ihrem Master-Zweig zusammen.

Es ist eine ähnliche Umgebung, die von @ brian-vandenberg beschrieben wird

Neben einem guten Zustand Ihrer Niederlassung fügen Sie einen Codeüberprüfungsschritt hinzu, der die Codequalität und den Wissensaustausch über Ihre Software verbessert.

[1] Jenkins https://jenkins-ci.org/

[2] Gerrit https://www.gerritcodereview.com/

Gustavo Coelho
quelle
1

Das CI sollte niemals den Commit-Verlauf des Repos ändern.

Die richtige Lösung ist hier, dass dem Hauptzweig keine Commits hinzugefügt werden, wenn sie nicht getestet und verifiziert wurden.

Arbeiten Sie an Feature-Zweigen, lassen Sie das CI automatisch auf diesen Zweigen ausführen, und führen Sie sie nicht mit dem Master zusammen, wenn die Builds fehlschlagen.

Sie können einen zusätzlichen Build erstellen, bei dem Tests zusammengeführt werden, wenn dies ein Problem darstellt, indem Sie auf dem Feature-Zweig und während des Zusammenführens von Master / Integration / was auch immer in den lokalen Zweig Tests ausführen.

Daenyth
quelle
1
Dies beantwortet die Frage in keiner Weise. Wenn der Build in einem Feature-Zweig fehlschlägt, sollte das CI das Commit zurücksetzen?
Carlos Campderrós
Was passiert, wenn die Erstellung in der Feature-Verzweigung erfolgreich ist, aber nach dem Zusammenführen fehlschlägt ?
Matthieu M.
@MatthieuM. Zusammenführen ist ein Commit. Soll der CI-Schritt, der zusammengeführt wird, den Build zurücksetzen?
Carlos Campderrós
@ CarlosCampderrós: ​​Ich persönlich hätte niemals ein Setup, das versucht, Commits zurückzusetzen. viel zu kompliziert.
Matthieu M.
Ich habe die Kommentare angesprochen.
Daenyth
1

Wir verwenden Jenkins für unseren Build-Server und verwenden das Gatekeeper-Modell für Push-Commits. Dabei ist der Gatekeeper eine Kombination aus Jenkins und Commit-Triggern (die sicherstellen, dass Peer-Reviewer ihre Arbeit erledigt haben).

Commits werden indirekt über einen Curl an Jenkins weitergeleitet, wo das Master-Repo geklont wird. Anschließend werden die zu verschmelzenden Commits abgerufen und alle erforderlichen Builds ausgeführt (für Linux / Solaris). Wenn alle Builds abgeschlossen sind, wird das Commit weitergeleitet.

Dies vermeidet viele, wenn nicht alle der bisher diskutierten Probleme:

  • Änderung der Geschichte
  • Die Geschichte richtig schreiben, wenn Sie der Entwickler sind, der den Bruch reparieren muss
  • Instabilität (in Form von kaputten Builds) wird niemals eingeführt

Es ermöglicht uns auch, andere Anforderungen direkt durchzusetzen, z. B. die erfolgreiche Durchführung von Komponententests.

Brian Vandenberg
quelle
re: the downvote, würde es dir etwas ausmachen, zu kommentieren, was dir an meiner Antwort nicht gefallen hat?
Brian Vandenberg
0

Wie oft haben Sie diese automatisierte E-Mail erhalten, die besagt, dass Ihr letzter Commit den Build gebrochen hat? Wie oft ist es falsch? Aber jetzt musst du nachsehen, ob es wirklich du oder jemand anderes war, der etwa zur gleichen Zeit ein anderes Commit ausgeführt hat. Oder vielleicht war es etwas Umweltfreundliches.

Wenn das System es nicht genau weiß, möchte ich es auf keinen Fall automatisieren.

Mohair
quelle
0

Die gestellte Frage ist fehlerhaft. Ich respektiere diese Aussage jedoch

"Wir glauben, dass das Konzept von Filialen gegen echte CI verstößt, da Sie durch das Festlegen einer Filiale von den anderen Entwicklern und deren Änderungen isoliert werden."

Was Sie jedoch tun sollten, sind diese Schritte

  • Arbeite den Master ab, wenn du magst (das ist in Ordnung und ziehe weiterhin Änderungen von allen), ABER verpflichte dich NICHT, den Master vor Ort zu machen
  • Erstellen Sie mit submit_XXXXXX eine Verzweigung, bevor Sie Ihre Änderungen an master übergeben
  • Lassen Sie Ihren automatischen Build alle Submit_XXX-Zweige abholen
  • Option 1: Pausen erstellen oder Pausen zusammenführen ... Änderung abgelehnt und landet nie auf dem Master
  • Option 2: Build funktioniert, Jenkins schiebt Master und aktualisiert es

DANN setzen wir einen GIT-Commit-Haken, um zu verhindern, dass sich JEDER tatsächlich zum Master verpflichtet. Es funktioniert großartig ... KEINE kaputten Builds und KEINE rückgängig gemachten Commits vom Master.

später Dean

Dean Hiller
quelle