Typische Situationen bei kontinuierlicher Integration

Sie haben Git-Befehle gelernt, möchten aber wissen, wie Continuous Integration (CI) in der Praxis aussieht? Oder möchten Sie vielleicht Ihre täglichen Abläufe optimieren? Dieser Kurs vermittelt Ihnen praktische Fähigkeiten zur kontinuierlichen Integration unter Verwendung eines Repositories auf GitHub. Der Kurs ist nicht als Wizard gedacht, den man einfach durchklicken kann; im Gegenteil, Sie werden die gleichen Schritte ausführen, die Menschen in der Praxis tatsächlich bei der Arbeit machen, auf die gleiche Weise, wie sie es tun. Ich werde die Theorie erklären, während Sie die entsprechenden Schritte durchlaufen.

Was werden wir tun?

Im Laufe des Kurses werden wir schrittweise eine Liste typischer CI-Schritte erstellen, was eine hervorragende Möglichkeit ist, sich diese Liste einzuprägen. Mit anderen Worten, wir werden eine Liste von Aktionen erstellen, die Entwickler durchführen, während sie kontinuierliche Integration umsetzen. Außerdem werden wir eine einfache Testsuite verwenden, um unseren CI-Prozess der Realität näherzubringen.

Dieses GIF zeigt schematisch die Commits in Ihrem Repository, während Sie den Kurs durchlaufen. Wie Sie sehen, ist hier nichts kompliziert, nur das Allernotwendigste.

Typische Situationen bei kontinuierlicher Integration

Sie werden an folgenden Standard-CI-Szenarien teilnehmen:

  • Arbeiten an einem Feature;
  • Anwendung von automatisierten Tests zur Gewährleistung der Qualität;
  • Umsetzung einer Prioritätsaufgabe;
  • Lösen von Konflikten bei der Zusammenführung von Branches (Merge-Conflict);
  • Fehler im Produktionsumfeld.

Was werden Sie lernen?

Sie werden in der Lage sein, folgende Fragen zu beantworten:

  • Was ist Continuous Integration (CI)?
  • Welche Arten von automatisierten Tests werden bei CI verwendet und auf welche Aktionen reagieren sie?
  • Was ist ein Pull-Request und wann wird er benötigt?
  • Was ist testgetriebene Entwicklung (TDD) und wie steht sie im Zusammenhang mit CI?
  • Soll man mergen oder Änderungen obenauf anwenden (rebase)?
  • Soll man zurücksetzen oder in der nächsten Version beheben?

Zunächst habe ich überall Ausdrücke wie "pull request" übersetzt, aber letztendlich beschlossen, an einigen Stellen die englischen Begriffe zurückzubringen, um den Wahnsinn im Text zu reduzieren. Manchmal werde ich „Programmierjargon“ wie das wunderbare Verb „committen“ verwenden, wo es im Arbeitsumfeld tatsächlich gebraucht wird.

Was ist Continuous Integration?

Continuous Integration, oder CI, ist eine technische Praxis, bei der jedes Teammitglied seinen Code mindestens einmal täglich in ein gemeinsames Repository integriert, wobei der resultierende Code ohne Fehler kompiliert werden muss.

Es gibt unterschiedliche Auslegungen dieses Begriffs.

Gegenstand der Diskussion ist die Häufigkeit der Integration. Einige behaupten, dass einmal tägliches Zusammenführen nicht ausreicht und in der Tat kontinuierlich integriert werden sollte. Ein Beispiel ist ein Team, in dem alle morgens frischen Code abrufen und abends einmal integrieren. Obwohl dies ein vernünftiger Einwand ist, wird allgemein angenommen, dass die Definition "einmal täglich" ausreichend praktisch, konkret und für Teams unterschiedlicher Größe geeignet ist.

Ein weiteres Argument ist, dass C++ schon lange nicht mehr die einzige Sprache ist, die in der Entwicklung verwendet wird, und die einfache Anforderung, fehlerfrei zu kompilieren, als Validierung zu schwach ist. Ein gewisser Satz an Tests (z. B. lokale Unit-Tests) sollte ebenfalls erfolgreich abgeschlossen werden. Derzeit neigt die Gemeinschaft dazu, diese Anforderung verbindlich zu machen, und in Zukunft wird "Kompilierung + Unit-Tests" anscheinend allgemein akzeptiert werden, wenn das nicht bereits geschehen ist.

Continuous Integration unterscheidet sich von kontinuierlicher Bereitstellung (Continuous Delivery, CD) insofern, als es keinen Release-Kandidaten nach jedem Integrationszyklus erfordert.

Liste von Schritten, die wir im Verlauf des Kurses verwenden werden

  1. Lade den neuesten Code herunter. Erstelle einen Branch von master. Fang an zu arbeiten.
  2. Erstelle Commits auf deinem neuen Branch. Baue und teste lokal. Klappt's? Gehe zum nächsten Schritt. Fehlgeschlagen? Fehler oder Tests beheben und es erneut versuchen.
  3. Push zum Remote-Repository oder Remote-Branch.
  4. Erstelle eine Pull-Anfrage. Diskutiere die Änderungen, füge während der Diskussion weitere Commits hinzu. Sorge dafür, dass die Tests auf dem Feature-Branch erfolgreich sind.
  5. Führe die Commits aus Master zusammen oder rebase sie. Sorge dafür, dass die Tests auf dem Merge-Ergebnis erfolgreich sind.
  6. Deploye vom Feature-Branch in die Produktion.
  7. Wenn alles eine Zeit lang in der Produktion gut läuft, merge die Änderungen in den Master.

Typische Situationen bei kontinuierlicher Integration

️ Vorbereitung

Stelle sicher, dass die benötigte Software vorhanden ist.

Um diesen Kurs zu absolvieren, benötigst du Node.js und einen Git-Client..

Du kannst jeden Git-Client verwenden, aber ich werde die Befehle nur für die Befehlszeile angeben.

Stelle sicher, dass du einen Git-Client hast, der die Befehlszeile unterstützt.

Wenn du noch keinen Git-Client hast, der die Befehlszeile unterstützt, kannst du Installationsanleitungen finden. hier.

Bereite das Repository vor.

Du musst eine persönliche Kopie (Fork) erstellen des Vorlage-Repositories mit dem Code für den Kurs auf GitHub. Lass uns vereinbaren, diese persönliche Kopie als Kursrepository zu bezeichnen..

Haben Sie es gemacht? Wenn Sie die Standardeinstellungen nicht geändert haben, heißt Ihr Kurs-Repository wahrscheinlich continuous-integration-team-scenarios-students, es befindet sich in Ihrem GitHub-Konto, und die URL sieht so aus

https://github.com//continuous-integration-team-scenarios-students

Ich werde diese Adresse einfach nennen <URL репозитория>.

Die spitzen Klammern wie <тут> bedeutet, dass Sie einen solchen Ausdruck durch den entsprechenden Wert ersetzen sollten.

Stellen Sie sicher, dass GitHub-Aktionen für dieses Kurs-Repository aktiviert sind. Wenn sie nicht aktiviert sind, aktivieren Sie sie bitte, indem Sie auf die große Schaltfläche in der Mitte der Seite klicken, die Sie erreichen können, indem Sie auf "Aktionen" in der GitHub-Oberfläche klicken.

Sie können den Kurs nicht erfolgreich absolvieren, solange die GitHub-Aktionen nicht aktiviert sind.

Typische Situationen bei kontinuierlicher Integration

Sie können immer die Funktion von GitHub nutzen, um Markdown anzuzeigen, um den aktuellen Zustand der Liste zu sehen, die wir hier erstellen

https://github.com//continuous-integration-team-scenarios-students/blob/master/ci.md

Zu den Antworten

Obwohl der beste Weg, diesen Kurs abzuschließen, darin besteht, alles selbst zu tun, könnten Sie auf Schwierigkeiten stoßen.

Wenn Sie das Gefühl haben, nicht zu verstehen, was zu tun ist, und nicht weitermachen können, können Sie in den Branch solution, der in Ihrem Start-Repository vorhanden ist, schauen.
Bitte führen Sie während des Kurses kein Merging durch. Sie können diesen Branch verwenden, um herauszufinden, was zu tun ist, oder um Ihren Code mit dem Autor-Code zu vergleichen, und alle Möglichkeiten nutzen, die uns Git bietet. Wenn Sie vollkommen verloren sind, können Sie Ihren Branch solution in master auf den Branch master ersetzen und dann Ihr Arbeitsverzeichnis auf den Kursabschnitt zurücksetzen, den Sie benötigen. solution Verwenden Sie dies nur, wenn Sie es wirklich brauchen

Committen Sie Ihren Code

git add . git commit -m "Sichere meine Arbeit"

Diese Befehle

benennen um

  • master-backup master in wechseln (checkout) zu einem neuen Branch;
  • master-backup solution in master;
  • und überschreiben den Inhalt des Arbeitsverzeichnisses; master erstellt einen Branch "solution" aus "master" (der vorher "solution" war), für den Fall, dass Sie in Zukunft einen Branch "solution" benötigen.
  • git branch -m master master-backup git branch -m solution master git checkout master -f git branch solution

Nach diesen Schritten können Sie verwenden

git log master um herauszufinden, welcher Commit Sie benötigen. Sie können Ihr Arbeitsverzeichnis auf diesen Commit zurücksetzen mit:
git reset --hard

git reset --hard

Wenn Sie mit dem Ergebnis zufrieden sind, müssen Sie irgendwann Ihre Repository-Versionen in ein entferntes Repository publik machen. Vergessen Sie nicht, den entfernten Branch beim Ausführen dieser Aktion eindeutig anzugeben.

git push --force origin master

Bitte beachten Sie, dass wir git push --forcevermutlich nicht oft so verfahren möchten, aber wir haben hier ein äußerst spezifisches Szenario mit einem Benutzer des Repositories, der außerdem versteht, was er tut.

Arbeiten beginnen

Typische Situationen bei kontinuierlicher Integration

Lassen Sie uns mit der Erstellung unserer CI-Schritte beginnen. Normalerweise beginnen Sie diesen Schritt mit dem Abrufen der neuesten Codeversion aus dem entfernten Repository, aber wir haben noch kein lokales Repository, also klonen wir es stattdessen aus dem Entfernten.

️ Aufgabe: Aktualisieren Sie das lokale Repository, erstellen Sie einen Branch aus master, beginnen Sie zu arbeiten

  1. Klonen Sie das Kurs-Repository aus <URL репозитория>.
  2. Führen Sie npm install im Verzeichnis des Kurs-Repositories aus; es wird benötigt, um Jest zu installieren, das wir zum Ausführen von Tests verwenden.
  3. Erstellen Sie einen Branch und benennen Sie ihn Feature. Wechseln Sie zu diesem Branch.
  4. Fügen Sie Testcode in ci.test.js zwischen den Kommentaren ein, die Sie dazu auffordern.

    it('1. Die neueste Codeversion abrufen', () => {
      expect(/.*pull.*/ig.test(fileContents)).toBe(true);
    });
    
    it('2. Commits hinzufügen', () => {
      expect(/.*commit.*/ig.test(fileContents)).toBe(true);
    });
    
    it('3. In den entfernten Branch mit demselben Namen pushen', () => {
      expect(/.*push.*/ig.test(fileContents)).toBe(true);
    });
    
    it('4. Eine Pull-Anfrage erstellen und weiterarbeiten', () => {
      expect(/.*pulls+request.*/ig.test(fileContents)).toBe(true);
    });

  5. Fügen Sie Text mit den ersten 4 Schritten in die Datei ci.md.
    1. Ziehen Sie den neuesten Code. Erstellen Sie einen Branch von `master`. Beginnen Sie mit der Arbeit.    
    2. Erstellen Sie Commits in Ihrem neuen Branch. Bauen und testen Sie lokal.  
    Erfolgreich? Gehen Sie zum nächsten Schritt. Fehler? Beheben Sie die Fehler oder Tests und versuchen Sie es erneut.  
    3. Pushen Sie in Ihr entferntes Repository oder in den entfernten Branch.  
    4. Erstellen Sie eine Pull-Anfrage. Diskutieren Sie die Änderungen, fügen Sie weitere Commits hinzu, während die Diskussion fortsetzt. Lassen Sie die Tests im Feature-Branch bestehen.  

    Befehle

# Клонируйте репозиторий курса
git clone <repository URL>
cd <repository name>

# Выполните npm install в каталоге репозитория курса; он установит Jest, который мы используем для запуска тестов.
npm install

# Создайте ветку и назовите ее feature. Переключитесь на эту в ветку.
git checkout -b feature

# Отредактируйте ci.test.js как описано выше.
# Отредактируйте ci.md как описано выше

Erstellen Sie Commits im neuen Branch, führen Sie Builds und Tests lokal durch.

Wir werden Tests einrichten, die vor dem Commit ausgeführt werden, und dann den Code committen.

Typische Szenarien, wenn Tests automatisch ausgeführt werden

  • Lokal:
    • Dauerhaft oder als Reaktion auf relevante Codeänderungen;
    • Beim Speichern (für interpretierte oder JIT-kompilierte Sprachen);
    • Beim Build (wenn eine Kompilierung erforderlich ist);
    • Beim Commit;
    • Beim Veröffentlichen in ein gemeinsames Repository.

  • Auf dem Build-Server oder in der Build-Umgebung:
    • Wenn Code in einen persönlichen Branch / ein Repository veröffentlicht wird.
    • Der Code wird in diesem Branch getestet.
    • Das potenzielle Zusammenführungsergebnis wird getestet (normalerweise mit master).
    • Als Teil der kontinuierlichen Integrations-/Lieferpipeline

In der Regel können Sie Tests umso häufiger ausführen, je schneller sie abgeschlossen sind. Eine typische Verteilung der Phasen kann so aussehen.

  • Schnelle Modultests – beim Bauen, in der CI-Pipeline
  • Langsame Modultests, schnelle Komponententests und Integrationstests – beim Commit, in der CI-Pipeline
  • Langsame Komponententests und Integrationstests – in der CI-Pipeline
  • Sicherheitstests, Lasttests und andere langwierige oder kostenintensive Tests – in CI/CD-Pipelines, jedoch nur in bestimmten Modi/Phasen/Pipelines, beispielsweise bei der Vorbereitung eines Release-Kandidaten oder bei manuellem Start.

️ Aufgabe

Ich schlage vor, die Tests zuerst manuell mit dem Befehl zu starten npm test. Danach fügen wir einen Git-Hook hinzu, um unsere Tests beim Commit auszuführen. Es gibt einen Haken: Git-Hooks sind nicht Teil des Repositories und können daher nicht von GitHub zusammen mit dem restlichen Kursmaterial geklont werden. Um den Hook einzurichten, müssen Sie install_hook.sh ausführen oder die Datei repo/hooks/pre-commit in das lokale Verzeichnis .git/hooks/.
bewegen. Beim Commit sehen Sie, dass die Tests ausgeführt werden und sie prüfen, ob bestimmte Schlüsselwörter in der Liste vorhanden sind.

  1. Führen Sie die Tests manuell aus, indem Sie den Befehl npm test im Verzeichnis des Kursrepositories eingeben. Stellen Sie sicher, dass die Tests abgeschlossen sind.
  2. Richten Sie den Commit-Hook (pre-commit hook) ein, indem Sie install_hook.sh.
  3. Änderungen in das lokale Repository committen.
  4. Stellen Sie sicher, dass die Tests vor dem Commit ausgeführt werden.

Ihr Repository sollte nach der Durchführung dieser Schritte so aussehen.
Typische Situationen bei kontinuierlicher Integration

Befehle

# Установите pre-commit hook выполнив install_hook.sh.  

# Закоммитьте изменения в локальный репозиторий. Используйте "Add first CI steps" в качестве сообщения при коммите.
git add ci.md ci.test.js
git commit -m "Add first CI steps"

# Убедитесь, что тесты запускаются перед коммитом.  

Veröffentlichen Sie den Code im Remote-Repository oder in einem Remote-Branch

Nachdem sie lokal gearbeitet haben, machen Entwickler ihren Code in der Regel öffentlich, damit er schließlich in das gemeinsame integriert werden kann. Mit GitHub wird dies in der Regel erreicht, indem die Arbeit entweder in einer persönlichen Fork des Repositories oder in einem persönlichen Branch veröffentlicht wird.

  • Bei der Verwendung von Forks klont der Entwickler ein entferntes gemeinsames Repository und erstellt eine persönliche Remote-Kopie, die als Fork bekannt ist. Danach klont er dieses persönliche Repository, um lokal daran zu arbeiten. Wenn die Arbeit abgeschlossen ist und Commits erstellt wurden, stellt er sie in seinen Fork ein, wo sie für andere zugänglich sind und in das gemeinsame Repository integriert werden können. Dieser Ansatz wird normalerweise in Open-Source-Projekten auf GitHub verwendet. Er wird auch in meinem erweiterten Kurs [Team Work and CI with Git] verwendet.http://devops.redpill.solutions/).
  • Ein anderer Ansatz besteht darin, nur ein entferntes Repository zu verwenden und nur den Branch des master gemeinsam genutzten Repositories als „geschützt“ zu betrachten. In diesem Szenario veröffentlichen einzelne Entwickler ihren Code in Branches des entfernten Repositories, damit andere diesen Code ansehen können, und wenn alles in Ordnung ist, ihn mit master dem gemeinsamen Repository zusammenzuführen.

In diesem speziellen Kurs werden wir einen Workflow verwenden, der Branches nutzt.

Lass uns unseren Code veröffentlichen.

️ Aufgabe

  • Veröffentliche Änderungen in einen Remote-Branch mit dem gleichen Namen wie dein Arbeitsbranch

Befehle

git push --set-upstream origin feature

Erstelle einen Pull Request

Erstelle einen Pull Request mit dem Titel Schritte überprüfen. Setze Feature als „Head-Branch“ und master als „Base-Branch“.

Stelle sicher, dass du master in seinem den Fork des Repositories als „Base-Branch“ eingestellt hast, ich werde keine Änderungsanfragen für das Repository mit den Kursmaterialien beantworten.

Im GitHub-Jargon ist der „Base-Branch“ der Branch, auf dem du deine Arbeit aufbaust, während der „Head-Branch“ der Branch ist, der die vorgeschlagenen Änderungen enthält.

Diskutiere die Änderungen, füge neue Commits hinzu, während die Diskussion fortschreitet.

Ein Pull Request (PR)

Ein Pull Request (PR) ist eine Möglichkeit, über den Code zu diskutieren und ihn zu dokumentieren sowie eine Codeüberprüfung (Code Review) durchzuführen. Pull Requests sind nach der allgemeinen Methode benannt, einzelne Änderungen in den gemeinsamen Code zu integrieren. Normalerweise klont eine Person das entfernte offizielle Repository des Projekts und arbeitet lokal am Code. Danach stellt sie den Code in ihr persönliches entferntes Repository ein und bittet die Verantwortlichen des offiziellen Repositories, ihren Code in ihre lokalen Repositories zu übernehmen, wo dieser überprüft und möglicherweise integriert wird.pull), also Merge-Vorgänge.Dieses Konzept ist auch unter anderen Namen bekannt, zum Beispiel, Merge-Request..

Tatsächlich müssen Sie die Pull-Request-Funktion von GitHub oder ähnlichen Plattformen nicht zwangsläufig verwenden. Entwicklerteams können andere Kommunikationsmethoden nutzen, einschließlich persönlicher Gespräche, Telefonate oder E-Mails, aber es gibt dennoch mehrere Gründe, solche Pull-Requests im Forum-Stil zu nutzen. Hier sind einige davon:

  • organisierte Diskussionen zu spezifischen Änderungen im Code;
  • als Ort zur Überprüfung von Rückmeldungen zu noch nicht abgeschlossenen Arbeiten, sowohl von automatisierten Tests als auch von Kollegen;
  • Vereinheitlichung der Code-Überprüfungen;
  • um später die Gründe und Überlegungen hinter bestimmten Code-Abschnitten nachvollziehen zu können.

Normalerweise erstellen Sie einen Pull Request, wenn Sie etwas diskutieren oder Feedback erhalten möchten. Wenn Sie beispielsweise an einer Funktion arbeiten, die auf verschiedene Arten implementiert werden kann, können Sie einen Änderungsantrag bereits vor dem Schreiben der ersten Code-Zeile erstellen, um Ihre Ideen zu teilen und Ihre Pläne mit Mitautoren zu besprechen. Wenn die Arbeit einfacher ist, wird der Pull Request eröffnet, wenn etwas bereits abgeschlossen, festgehalten und diskutiert werden kann. In einigen Szenarien können Sie einen PR auch nur aus Qualitätskontrollgründen öffnen: um automatische Tests auszuführen oder eine Code-Überprüfung einzuleiten. Was auch immer Sie entscheiden, vergessen Sie nicht, @Personen zu erwähnen, deren Zustimmung für Ihren Pull Request erforderlich ist.

Normalerweise machen Sie folgendes, wenn Sie einen PR erstellen.

  • Sie geben an, was Sie ändern möchten und wo.
  • Sie schreiben eine Beschreibung, die den Zweck der Änderungen erklärt. Möglicherweise möchten Sie:
    • etwas Wichtiges hinzufügen, das aus dem Code nicht offensichtlich ist, oder etwas Nützliches zum Verständnis des Kontexts, wie relevante #Bugs und Commit-Nummern;
    • @alle erwähnen, mit denen Sie zusammenarbeiten möchten, oder Sie können sie später in Kommentaren @erwähnen;
    • Kollegen um Hilfe bei etwas bitten oder spezifischere Überprüfungen anfordern.

Nachdem Sie den PR eröffnet haben, werden die für solche Fälle konfigurierten Tests ausgeführt. In unserem Fall handelt es sich um denselben Testsatz, den wir lokal ausgeführt haben, aber in einem echten Projekt können zusätzliche Tests und Überprüfungen vorhanden sein.

Bitte warten Sie, während die Tests abgeschlossen werden. Sie können den Status der Tests im unteren Bereich der PR-Diskussion in der GitHub-Oberfläche einsehen. Fahren Sie fort, wenn die Tests abgeschlossen sind.

️ Fügen Sie einen Hinweis zur Willkür der CI-Schritteliste hinzu

Die in diesem Kurs verwendete Liste ist willkürlich und subjektiv; wir sollten einen Hinweis dazu hinzufügen.

️ Aufgabe: Erstellen eines Pull Requests für diese Anmerkung

  1. Wechseln Sie zu dem Branch master.
  2. Erstellen Sie einen Branch mit dem Namen bugfix.
  3. Fügen Sie den Anmerkungstext ans Ende der Datei hinzu. ci.md.
    > **GitHub-Flow** wird manchmal als Spitzname verwendet, um eine Variante der trunkbasierten Entwicklung zu bezeichnen, 
    bei der Code direkt von Feature-Branches bereitgestellt wird. Diese Liste ist nur eine Interpretation, 
    die ich in meinen [DevOps-Kursen](http://redpill.solutions) verwende. 
    Das offizielle Tutorial finden Sie [hier](https://guides.github.com/introduction/flow/).
  4. Speichern Sie die Änderungen.
  5. Veröffentlichen Sie den Branch bugfix im entfernten Repository.
  6. Erstellen Sie einen Pull Request mit dem Namen Eine Anmerkung hinzufügen zu dem Haupt-Branch bugfix und dem Basis-Branchmaster.

Stelle sicher, dass du master in seinem den Fork des Repositories als „Base-Branch“ eingestellt hast, ich werde keine Änderungsanfragen für das Repository mit den Kursmaterialien beantworten.

So sollte Ihr Repository aussehen.
Typische Situationen bei kontinuierlicher Integration

Befehle

# Переключитесь на ветку master. Создайте ветку bugfix.
git checkout master

# Создайте ветку bugfix-remark.
git checkout -b bugfix

# Добавьте текст примечания внизу ci.md.

# Закоммитьте изменения
git add ci.md
git commit -m "Add a remark about the list being opinionated"

# Опубликуйте ветку bugfix в удалённый репозиторий.
git push --set-upstream origin bugfix

# Создайте pull request при помощи интерфейса GitHub как описано выше

Bestätigen Sie den Pull Request "Eine Anmerkung hinzufügen".

️ Aufgabe

  1. Erstellen Sie einen Pull Request.
  2. Klicken Sie auf "Pull Request zusammenführen".
  3. Klicken Sie auf "Zusammenführung bestätigen".
  4. Klicken Sie auf "Branch löschen"; wir benötigen ihn nicht mehr.

Das ist das Diagramm der Commits nach der Zusammenführung.
Typische Situationen bei kontinuierlicher Integration

️ Arbeiten Sie weiter und fügen Sie Tests hinzu.

Die Zusammenarbeit an einem Pull Request führt oft zu zusätzlicher Arbeit. Dies ist normalerweise das Ergebnis von Code-Überprüfungen oder Diskussionen, aber in unserem Kurs werden wir dies simulieren, indem wir neue Elemente zu unserer CI-Schritteliste hinzufügen.

Bei der kontinuierlichen Integration wird normalerweise eine Art von Testabdeckung verwendet. Die Anforderungen an die Testabdeckung variieren und befinden sich üblicherweise in einem Dokument mit einem Titel wie "Richtlinien für Autoren" (contribution guidelines). Wir werden es einfach halten und einen Test für jede Zeile in unserer Checkliste hinzufügen.

Wenn Sie Aufgaben ausführen, versuchen Sie zuerst, die Tests zu committen. Wenn Sie den pre-commit Hook korrekt eingerichtet haben, wird der neu hinzugefügte Test ausgeführt, schlägt fehl und es wird nichts committed. Beachten Sie: So erfahren wir, dass unsere Tests tatsächlich etwas überprüfen. Interessanterweise könnte eine erfolgreiche Ausführung der Tests bedeuten, dass der Code wie erwartet funktioniert, oder dass die Tests tatsächlich nichts überprüfen, wenn wir mit diesem Code ohne Tests beginnen würden. Außerdem könnten wir, wenn wir die Tests nicht ursprünglich geschrieben hätten, sie ganz vergessen, da uns nichts daran erinnern würde.

Testgetriebene Entwicklung (TDD)

TDD empfiehlt, Tests vor dem Code zu schreiben. Der übliche Arbeitsprozess unter Verwendung von TDD sieht so aus.

  1. Fügen Sie einen Test hinzu.
  2. Führen Sie alle Tests aus und stellen Sie sicher, dass der neue Test nicht erfolgreich ist.
  3. Schreiben Sie den Code.
  4. Führen Sie die Tests aus, stellen Sie sicher, dass alle Tests erfolgreich sind.
  5. Führen Sie ein Refactoring des Codes durch.
  6. Wiederholen Sie.

Da die Ergebnisse der Tests, die nicht erfolgreich waren, normalerweise in Rot angezeigt werden, während die erfolgreich durchgeführten in Grün angezeigt werden, wird der Zyklus auch "rot-grün-refactor" (red-green-refactor) genannt.

️ Aufgabe

Versuchen Sie zuerst, die Tests zu committen und ihnen zu erlauben, nicht erfolgreich zu sein, und fügen Sie dann den Text der CI-Schritte hinzu und committen Sie ihn. Sie werden sehen, dass die Tests erfolgreich sind ("grün").
Veröffentlichen Sie dann den neuen Code im entfernten Repository und beobachten Sie, wie die Tests im GitHub-Interface am Ende der Pull-Request-Diskussion ausgeführt werden und der PR-Status aktualisiert wird.

  1. Wechseln Sie zu dem Branch Feature.
  2. Fügen Sie diese Tests zu ci.test.js nach dem letzten Aufruf it (...);.

    it('5. Merge/Rebase Commits von master. Stellen Sie sicher, dass Tests mit dem Merge-Ergebnis bestehen.', () => {
      expect(/.*merge.*commits.*tests+pass.*/ig.test(fileContents)).toBe(true);
    });
    
    it('6. Bereitstellung vom Feature-Branch in die Produktion.', () => {
      expect(/.*Deploy.*to+production.*/ig.test(fileContents)).toBe(true);
    });
    
    it('7. Wenn alles für einige Zeit in der Produktion gut ist, ändern Sie alles in master.', () => {
      expect(/.*merge.*to+master.*/ig.test(fileContents)).toBe(true);
    });

  3. Versuchen Sie, die Tests zu committen. Wenn pre-commit der Hook aktiv ist, schlägt der Commit fehl.
  4. Fügen Sie danach diesen Text hinzu ci.md.
    5. Merge/Rebase Commits von master. Stellen Sie sicher, dass Tests mit dem Merge-Ergebnis bestehen.  
    6. Bereitstellung vom Feature-Branch mit einem schleichenden Fehler in die Produktion.
    7. Wenn alles für einige Zeit in der Produktion gut ist, ändern Sie alles in master. 
  5. Nehmen Sie die Änderungen lokal vor und committen Sie sie.
  6. Veröffentlichen Sie die Änderungen in den Branch Feature.

Jetzt sollte es etwa so aussehen
Typische Situationen bei kontinuierlicher Integration

Befehle


# Переключительна ветку feature
git checkout feature

# Добавить тесты в ci.test.js как описано выше

# Добавьте в индекс ci.test.js чтобы позже закоммитить
git add ci.test.js

# Попытайтесь закоммитить тесты. Если pre-commit hook установлены, коммит не произойдёт.
git commit

# Теперь добавьте текст в ci.md как описано выше

# Внесите изменения и закоммитьте их
git add ci.md
git commit -m "Add the remaining CI steps"

# Опубликуйте изменения в ветку feature
git push

Merge-Konflikt

Gehen Sie zur Pull-Request-Anfrage Schritte überprüfen.

Obwohl wir nichts falsch gemacht haben und die Tests für unseren Code erfolgreich waren, können wir den Branch immer noch nicht zusammenführen. Feature und master. Das liegt daran, dass ein anderer Branch bugfix mit master zusammengeführt wurde, während wir an diesem PR gearbeitet haben.
Dies führt zu einer Situation, in der der entfernte Branch master eine neuere Version hat als die, auf der wir unseren Branch basieren. Feature. Daher können wir HEAD nicht einfach zurücksetzen master bis zum Ende des Branches Feature. In dieser Situation müssen wir entweder einen Merge durchführen oder die Commits Feature darüber anwenden (rebase). masterGitHub kann tatsächlich automatisches Merging durchführen, wenn es keine Konflikte gibt. Leider gibt es in unserer Situation in beiden Branches konkurrierende Änderungen in der Datei. ci.mdDiese Situation ist bekannt als Merge-Konflikt, und wir müssen ihn manuell lösen.

Merge oder Rebase

Merge

  • Erstellt ein zusätzliches Merge-Commit und bewahrt die Historie.
    • Behält die ursprünglichen Commits der Branches mit den ursprünglichen Zeitstempeln und Autoren bei.
    • Bewahrt die SHA der Commits und Verweise darauf in den Diskussionen über Pull-Requests.
  • Erfordert eine einmalige Konfliktbehebung.
  • Macht die Historie nichtlinear.
    • Die Historie kann aufgrund der vielen Branches schwer zu lesen sein (wie das Kabel eines IDE).
    • Kompliziert die automatische Fehlersuche, zum Beispiel macht es git bisect weniger nützlich – es findet nur das Merge-Commit.

Rebase

  • Spielt die Commits aus dem aktuellen Branch nacheinander über die Basis wieder ein.
    • Es werden neue Commits mit neuen SHA gebildet, sodass die Commits in GitHub mit den ursprünglichen Pull-Requests, jedoch nicht mit den entsprechenden Kommentaren, übereinstimmen.
    • Commits können während des Prozesses rekombiniert und verändert oder sogar zu einem einzigen kombiniert werden.
  • Es kann notwendig sein, mehrere Konflikte zu lösen.
  • Ermöglicht das Beibehalten einer linearen Historie.
    • Die Historie könnte leichter lesbar sein, es sei denn, sie ist zu lang ohne vernünftigen Grund.
    • Die automatische Fehlersuche und das Beheben von Problemen ist etwas einfacher: es macht möglich, git bisectkann automatische Rollbacks klarer und vorhersehbarer machen.
  • Erfordert das Veröffentlichen des Branches mit den verschobenen Commits mit dem Flag --force bei der Verwendung mit Pull-Requests.

Normalerweise vereinbaren Teams, immer dieselbe Strategie zu verwenden, wenn sie Änderungen zusammenführen müssen. Dies kann ein "sauberes" Merging oder ein "sauberes" Einspielen von Commits über oder etwas dazwischen sein, wie das Einspielen von Commits im interaktiven Modus (git rebase -i) lokal für Branches, die nicht im gemeinsamen Repository veröffentlicht sind, aber Merging für "öffentliche" Branches.

Hier werden wir Merging verwenden.

️ Aufgabe

  1. Stellen Sie sicher, dass der Code im lokalen Branch master aus dem entfernten Repository aktualisiert ist.
  2. Wechseln Sie zu dem Branch Feature.
  3. Initiieren Sie das Merging mit dem Branch master. Es wird auf einen Merge-Konflikt hingewiesen, der mit konkurrierenden Änderungen in Verbindung steht. ci.md.
  4. Lösen Sie den Konflikt so, dass unsere Liste der CI-Schritte und der Hinweis darauf im Text erhalten bleibt.
  5. Veröffentlichen Sie den Merge-Commit in den Remote-Branch Feature.
  6. Überprüfen Sie den Status des Pull-Requests in der Benutzeroberfläche von GitHub und warten Sie, bis die Zusammenführung genehmigt wurde.

Befehle

# Убедитесь, что код в локальное ветке `master` обновлён из удалённого репозитория.
git checkout master
git pull

# Переключитесь на ветку feature
git checkout feature

# Инициируйте слияние с веткой master 
git merge master

# A merge conflict related to concurrent changes to ci.md will be reported
# => Auto-merging ci.md
#    CONFLICT (content): Merge conflict in ci.md
#    Automatic merge failed; fix conflicts and then commit the result.

# Разрешите конфликт так, чтобы и наш список шагов CI, и замечание о нем остались в тексте.
# отредактируйте ci.md чтоб он не содержал маркеров конфликта слияния
git add ci.md
git merge --continue
# при коммите можете оставить сообщение по умолчанию

# Опубликуйте коммит слияния в удаленную ветку feature.
git push

# Проверьте статус запроса на изменения в пользовательском интерфейсе GitHub, дождитесь пока слияние не будет разрешено.

Tolle Arbeit!

Sie haben an der Liste gearbeitet und müssen nun den Pull-Request in master.

️ Aufgabe: Genehmigen Sie den Pull-Request "Steps review"

  1. Öffnen Sie den Pull-Request.
  2. Klicken Sie auf "Pull Request zusammenführen".
  3. Klicken Sie auf "Zusammenführung bestätigen".
  4. Klicken Sie auf "Branch löschen", da wir ihn nicht mehr benötigen.

Dies ist momentan Ihr Repository
Typische Situationen bei kontinuierlicher Integration

Fehler in der Produktion

Es wird gesagt, dass „Tests verwendet werden können, um Fehler nachzuweisen, aber niemals, um deren Abwesenheit zu beweisen“. Obwohl wir Tests hatten, die uns keine Fehler gezeigt haben, hat sich ein heimtückischer Fehler in die Produktion eingeschlichen.

In einem solchen Szenario müssen wir uns um folgende Punkte kümmern:

  • was in der Produktion bereitgestellt ist;
  • den Code im Branch master mit dem Fehler, von dem die Entwickler neue Arbeiten aufnehmen können.

Rollback oder Fix in der nächsten Version?

"Rollback" (Rückgängigmachen) ist das Bereitstellen einer vorher bekannten fehlerfreien Version in der Produktionsumgebung und das Rückgängig machen (revert) von Commits, die den Fehler enthalten. "Fix in der nächsten Version" (Vorwärtsbehebung) bedeutet, eine Korrektur hinzuzufügen und master so schnell wie möglich eine neue Version bereitzustellen. Da APIs und Datenbankschemata sich beim Bereitstellen von Code in der Produktionsumgebung ändern, ist das Rollback in der Regel viel komplexer und riskanter als die Behebung in der nächsten Version, wenn kontinuierliche Bereitstellung und gute Testabdeckung vorhanden sind.

Da das Rollback in unserem Fall kein Risiko birgt, werden wir diesen Weg gehen, da es uns ermöglicht,

  • den Fehler in der Produktion so schnell wie möglich zu beheben;
  • den Code in master sofort für neue Arbeiten bereit zu machen.

️ Aufgabe

  1. Wechseln Sie zu dem Branch master lokal.
  2. Aktualisieren Sie das lokale Repository aus dem Remote-Repository.
  3. Rollback des Merge-Commits des PR Schritte überprüfen in master.
  4. Änderungen in das Remote-Repository veröffentlichen.

Dies ist die Repository-Historie mit dem zurückgenommenen Merge-Commit
Typische Situationen bei kontinuierlicher Integration

Befehle

# Переключитесь на ветку master.
git checkout master

# Обновите локальный репозиторий из удалённого репозитория.
git pull

# Отмените коммит слияния PR Steps review в master.
# Мы отменяем коммит слияния, поэтому нам нужно выбрать ветку истории, которую мы захотим оставить
git show HEAD

# предположим, что коммит, который был последним в ветке master до слияния, был отображён предыдущей командой первым
git revert HEAD -m 1
# можете не менять сообщения коммитов

# Опубликуйте изменения в удалённый репозиторий
git push

️ Selbstüberprüfung

Stellen Sie sicher, dass ci.md nach dem Rückgängigmachen des Merge-Commits keinen Text "sneaky bug" mehr enthält.

Korrigieren Sie die CI-Schritte und übernehmen Sie sie in master

Wir haben den Merge-Commit des Branches vollständig zurückgenommen Feature. Die gute Nachricht ist, dass wir jetzt keinen Fehler mehr haben. master. Die schlechte Nachricht ist, dass unsere wertvolle Liste der Schritte zur kontinuierlichen Integration verschwunden ist. Daher müssen wir idealerweise die Korrektur auf die Commits anwenden, die Feature und sie zurückgeben nach master zusammen mit der Korrektur.

Wir können die Aufgabe auf verschiedene Weise angehen:

  • einen Commit zurücksetzen, der das Merge rückgängig macht Feature c master;
  • Commits von dem ehemaligen Feature.

Verschiedene Entwicklerteams verwenden in diesem Fall unterschiedliche Ansätze. Wir werden nützliche Commits in einen separaten Branch übertragen und einen separaten Pull-Request für diesen neuen Branch erstellen.

️ Aufgabe

  1. Erstellen Sie einen Branch mit dem Namen feature-fix und wechseln Sie zu diesem.
  2. Übertragen Sie alle Commits vom ehemaligen Branch Feature in den neuen Branch. Lösen Sie die Merge-Konflikte, die beim Übertragen aufgetreten sind.

    Typische Situationen bei kontinuierlicher Integration

  3. Fügen Sie einen Regressionstest in ci.test.js:

    it('does not contain the sneaky bug', () => {
    expect( /.*sneakys+bug.* /gi.test(fileContents)).toBe(false);
    });

  4. Führen Sie die Tests lokal aus, um sicherzustellen, dass sie nicht erfolgreich abgeschlossen werden.
  5. Entfernen Sie den Text " with a sneaky bug" in ci.md.
  6. Fügen Sie die Änderungen an den Tests und die Änderungen in der Schritt-Liste zum Index hinzu und committen Sie sie.
  7. Veröffentlichen Sie den Branch im Remote-Repository.

Sie sollten am Ende etwas Ähnliches haben
Typische Situationen bei kontinuierlicher Integration

Befehle

# Создайте ветку под названием feature-fix и переключитесь на нее.
git checkout -b feature-fix

# Перенесите все коммиты из бывшей ветки feature в новую ветку. Разрешите конфликты слияния, которые возникли при переносе.
# используйте историю чтобы узнать хэши коммитов:
# - предшествующего коммиту с первой частью списка: C0
# - добавляющего последние элементы списка: C2
git log --oneline --graph
git cherry-pick C0..C2
# разрешите конфликты слияния
# - отредактируйте ci.md и/или ci.test.js
# - добавьте файлы в индекс
# - выполните "git cherry-pick --continue", можете не менять сообщение коммита

# Добавьте регрессионный тест в ci.test.js
# Запустите тесты локально, чтобы убедиться, что они не завершаются успешно.

# Удалите текст " with a sneaky bug" в ci.md.

# Добавьте в индекс изменения тестов и в списке шагов и закоммитьте их.
git add ci.md ci.test.js
git commit -m "Fix the bug in steps list"

# Опубликуйте ветку в удалённый репозиторий.
git push --set-upstream origin feature-fix

Erstellen Sie einen Pull Request.

Erstelle einen Pull Request mit dem Titel Fixing the feature. Setze feature-fix als "head branch", und master als „Base-Branch“.
Bitte warten Sie, bis die Tests abgeschlossen sind. Sie können den Teststatus am Ende der PR-Diskussion sehen.

Stelle sicher, dass du master in seinem den Fork des Repositories als „Base-Branch“ eingestellt hast, ich werde keine Änderungsanfragen für das Repository mit den Kursmaterialien beantworten.

Genehmigen Sie den Pull-Request "Fixing the feature"

Vielen Dank für die Korrektur! Bitte genehmigen Sie die Änderungen in master aus dem Pull-Request.

️ Aufgabe

  1. Klicken Sie auf "Pull Request zusammenführen".
  2. Klicken Sie auf "Zusammenführung bestätigen".
  3. Klicken Sie auf "Branch löschen", da wir ihn nicht mehr benötigen.

Das sollten Sie momentan haben
Typische Situationen bei kontinuierlicher Integration

Herzlichen Glückwunsch!

Sie haben alle Schritte unternommen, die Menschen normalerweise im Prozess der kontinuierlichen Integration durchführen.

Wenn Sie Probleme mit dem Kurs bemerken oder wissen, wie er verbessert werden kann, erstellen Sie ein Issue im Repository mit den Kursmaterialien. Dieser Kurs hat auch eine interaktive Version , die das GitHub Learning Lab als Plattform nutzt.

Quelle: habr.com

60GB SSD 8Gb DDR4