Typische Situationen bei kontinuierlicher Integration

Sie haben Git-Befehle gelernt, möchten sich aber vorstellen, wie Continuous Integration (CI) in der Realität funktioniert? Oder möchten Sie Ihre täglichen Aktivitäten optimieren? Dieser Kurs vermittelt Ihnen praktische Kenntnisse in der kontinuierlichen Integration mithilfe eines GitHub-Repositorys. Dieser Kurs soll kein Assistent sein, den Sie einfach durchklicken können; im Gegenteil, Sie werden die gleichen Aktionen ausführen, die Menschen tatsächlich bei der Arbeit ausführen, und zwar auf die gleiche Weise, wie sie es tun. Ich werde die Theorie erklären, während Sie die einzelnen Schritte durchgehen.

Was werden wir tun?

Im weiteren Verlauf werden wir nach und nach eine Liste typischer CI-Schritte erstellen, was eine gute Möglichkeit ist, sich diese Liste zu merken. Mit anderen Worten: Wir erstellen eine Liste der Aktionen, die Entwickler bei der kontinuierlichen Integration durchführen. Wir werden auch eine einfache Reihe von Tests verwenden, um unseren CI-Prozess dem tatsächlichen Prozess anzunähern.

Dieses GIF zeigt schematisch die Commits in Ihrem Repository im Verlauf des Kurses. Wie Sie sehen, gibt es hier nichts Kompliziertes und nur das Nötigste.

Typische Situationen bei kontinuierlicher Integration

Sie durchlaufen die folgenden Standard-CI-Szenarien:

  • An einer Funktion arbeiten;
  • Anwendung automatisierter Tests zur Qualitätssicherung;
  • Umsetzung der vorrangigen Aufgabe;
  • Konfliktlösung beim Zusammenführen von Zweigen (Merge-Konflikt);
  • In einer Produktionsumgebung tritt ein Fehler auf.

Was wirst du lernen?

Folgende Fragen können Sie beantworten:

  • Was ist kontinuierliche Integration (CI)?
  • Welche Arten von automatisierten Tests werden in CI verwendet und als Reaktion auf welche Aktionen werden sie ausgelöst?
  • Was sind Pull Requests und wann werden sie benötigt?
  • Was ist Test Driven Development (TDD) und in welcher Beziehung steht es zu CI?
  • Soll ich die Änderungen zusammenführen oder umbasieren?
  • Zurücksetzen oder in der nächsten Version beheben?

Anfangs habe ich Dinge wie „Pull Requests“ überall übersetzt, mich dann aber entschieden, an manchen Stellen Phrasen auf Englisch zurückzugeben, um den Grad des Wahnsinns im Text zu reduzieren. Manchmal verwende ich „programmer surzhik“ wie das wunderbare Verb „commit“, wo es tatsächlich bei der Arbeit verwendet wird.

Was ist kontinuierliche Integration?

Kontinuierliche Integration, oder CI, ist eine technische Praxis, bei der jedes Teammitglied seinen Code mindestens einmal am Tag in ein gemeinsames Repository integriert und der resultierende Code mindestens fehlerfrei erstellt werden muss.

Über diesen Begriff gibt es Meinungsverschiedenheiten

Der Streitpunkt ist die Häufigkeit der Integration. Einige argumentieren, dass das Zusammenführen von Code nur einmal am Tag nicht ausreicht, um tatsächlich kontinuierlich zu integrieren. Ein Beispiel ist ein Team, in dem jeder morgens frischen Code nimmt und ihn abends einmal integriert. Obwohl dies ein berechtigter Einwand ist, wird allgemein angenommen, dass die Definition „einmal am Tag“ einigermaßen praktisch, spezifisch und für Teams unterschiedlicher Größe geeignet ist.

Ein weiterer Einwand besteht darin, dass C++ nicht mehr die einzige Sprache ist, die in der Entwicklung verwendet wird, und dass es schwach ist, lediglich eine fehlerfreie Assemblierung als Validierungsmethode zu fordern. Einige Tests (z. B. lokal ausgeführte Komponententests) müssen ebenfalls erfolgreich abgeschlossen werden. Im Moment ist die Community dabei, dies zu einer Anforderung zu machen, und in Zukunft werden „Build + Unit-Tests“ wahrscheinlich gängige Praxis werden, sofern dies nicht bereits geschehen ist.

Kontinuierliche Integration unterscheidet sich von Kontinuierliche Lieferung (Continuous Delivery, CD), da nach jedem Integrationszyklus kein Release Candidate erforderlich ist.

Liste der Schritte, die wir im gesamten Kurs verwenden werden

  1. Ziehen Sie den neuesten Code ein. Erstellen Sie einen Zweig aus master. Beginne zu arbeiten.
  2. Erstellen Sie Commits für Ihren neuen Zweig. Lokal erstellen und testen. Passieren? Fahren Sie mit dem nächsten Schritt fort. Scheitern? Beheben Sie Fehler oder Tests und versuchen Sie es erneut.
  3. Pushen Sie in Ihr Remote-Repository oder Ihren Remote-Zweig.
  4. Erstellen Sie eine Pull-Anfrage. Besprechen Sie die Änderungen und fügen Sie im weiteren Verlauf der Diskussion weitere Commits hinzu. Sorgen Sie dafür, dass Tests im Feature-Zweig bestehen.
  5. Commits vom Master zusammenführen/rebasieren. Lassen Sie Tests das Zusammenführungsergebnis weitergeben.
  6. Bereitstellung vom Feature-Branch bis zur Produktion.
  7. Wenn in der Produktion über einen gewissen Zeitraum hinweg alles in Ordnung ist, führen Sie die Änderungen im Master zusammen.

Typische Situationen bei kontinuierlicher Integration

️ Vorbereitung

Stellen Sie sicher, dass Sie über die richtige Software verfügen

Um an diesem Kurs teilnehmen zu können, benötigen Sie Node.js и Git-Client.

Sie können jeden Git-Client verwenden, ich werde jedoch nur Befehle für die Befehlszeile bereitstellen.

Stellen Sie sicher, dass Sie einen Git-Client installiert haben, der die Befehlszeile unterstützt

Wenn Sie noch keinen Git-Client haben, der die Befehlszeile unterstützt, finden Sie hier Installationsanweisungen hier.

Bereiten Sie das Repository vor

Sie müssen eine persönliche Kopie (Fork) erstellen. Vorlagen-Repository mit Code für den Kurs auf GitHub. Lassen Sie uns vereinbaren, diese persönliche Kopie zu nennen Kurs-Repository.

Erledigt? Wenn Sie die Standardeinstellungen nicht geändert haben, wird höchstwahrscheinlich Ihr Kurs-Repository aufgerufen continuous-integration-team-scenarios-students, es befindet sich in Ihrem GitHub-Konto und die URL sieht so aus

https://github.com/<ваше имя ползователя на GitHub>/continuous-integration-team-scenarios-students

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

Spitze Klammern wie <тут> bedeutet, dass Sie einen solchen Ausdruck durch den entsprechenden Wert ersetzen müssen.

Stelle sicher das GitHub-Aktionen für dieses Kurs-Repository enthalten. Wenn sie nicht aktiviert sind, aktivieren Sie sie bitte, indem Sie auf die große Schaltfläche in der Mitte der Seite klicken. Sie können darauf zugreifen, indem Sie in der GitHub-Oberfläche auf „Aktionen“ klicken.

Sie können den Kurs gemäß meinen Anweisungen nicht abschließen, wenn GitHub-Aktionen nicht aktiviert sind.

Typische Situationen bei kontinuierlicher Integration

Sie können jederzeit die Fähigkeit von GitHub zum Rendern von Markdown nutzen, um den aktuellen Status der Liste anzuzeigen, die wir hier erstellen

https://github.com/<your GitHub user name>/continuous-integration-team-scenarios-students/blob/master/ci.md

Über die Antworten

Obwohl es am besten ist, diesen Kurs selbst zu absolvieren, kann es sein, dass Sie auf einige Schwierigkeiten stoßen.

Wenn Sie das Gefühl haben, dass Sie nicht verstehen, was Sie tun sollen, und nicht weitermachen können, können Sie sich den Thread ansehen solution, das sich in Ihrem Start-Repository befindet.
Bitte nicht zusammenführen solution в master während des Kurses. Sie können diesen Zweig verwenden, um herauszufinden, was zu tun ist, oder um Ihren Code mit dem des Autors zu vergleichen und dabei alle Möglichkeiten zu nutzen, die Git uns bietet. Wenn Sie völlig verloren gehen, können Sie Ihre Filiale komplett ersetzen master auf einem Ast solution und setzen Sie dann Ihr Arbeitsverzeichnis auf den benötigten Kursschritt zurück.

Benutzen Sie dies nur, wenn Sie es wirklich brauchen

Übernehmen Sie Ihren Code

git add .
git commit -m "Backing up my work"

Diese Befehle

  • umbenennen master в master-backup;
  • umbenennen solution в master;
  • Auschecken in eine neue Filiale master und den Inhalt des Arbeitsverzeichnisses neu schreiben;
  • Erstellen Sie einen „solution“-Zweig aus „master“ (früher „solution“) für den Fall, dass Sie in Zukunft einen „solution“-Zweig 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 es verwenden git log master um herauszufinden, welches Commit Sie benötigen.
Sie können Ihr Arbeitsverzeichnis wie folgt auf dieses Commit zurücksetzen:

git reset --hard <the SHA you need>

Wenn Sie mit dem Ergebnis zufrieden sind, müssen Sie irgendwann Ihre Version des Repositorys in einem Remote-Repository veröffentlichen. Vergessen Sie nicht, dabei den Remote-Zweig explizit anzugeben.

git push --force origin master

Bitte beachten Sie, dass wir verwenden git push --force. Es ist unwahrscheinlich, dass Sie dies sehr oft tun möchten, aber wir haben hier ein sehr spezifisches Szenario mit einem Repository-Benutzer, der darüber hinaus versteht, was er tut.

Beginnt mit der Arbeit

Typische Situationen bei kontinuierlicher Integration

Beginnen wir mit der Zusammenstellung unserer Liste der CI-Schritte. Normalerweise würden Sie diesen Schritt damit beginnen, die neueste Version des Codes aus dem Remote-Repository auszuchecken. Da wir jedoch noch kein lokales Repository haben, klonen wir ihn stattdessen aus dem Remote-Repository.

️ Aufgabe: Aktualisieren Sie das lokale Repository und erstellen Sie einen Zweig daraus master, beginne zu arbeiten

  1. Klonen Sie das Kurs-Repository von <URL репозитория>.
  2. Rennen npm install im Kurs-Repository-Verzeichnis; Wir benötigen es, um Jest zu installieren, mit dem wir Tests durchführen.
  3. Erstellen Sie einen Zweig und benennen Sie ihn feature. Wechseln Sie zu diesem Thread.
  4. Testcode hinzufügen ci.test.js zwischen den Kommentaren, die mich dazu auffordern.

    it('1. pull latest code', () => {
      expect(/.*pull.*/ig.test(fileContents)).toBe(true);
    });
    
    it('2. add commits', () => {
      expect(/.*commit.*/ig.test(fileContents)).toBe(true);
    });
    
    it('3. push to the remote branch with the same name', () => {
      expect(/.*push.*/ig.test(fileContents)).toBe(true);
    });
    
    it('4. create a pull request and continue working', () => {
      expect(/.*pulls+request.*/ig.test(fileContents)).toBe(true);
    });

  5. Fügen Sie der Datei Text mit den ersten 4 Schritten hinzu ci.md.
    1. Pull in the latest code. Create a branch from `master`. Start working.    
    2. Create commits on your new branch. Build and test locally.  
    Pass? Go to the next step. Fail? Fix errors or tests and try again.  
    3. Push to your remote repository or remote branch.  
    4. Create a pull request. Discuss the changes, add more commits  
    as discussion continues. Make tests pass on the feature branch.  

    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 für einen neuen Zweig, erstellen und testen Sie sie lokal

Wir werden die Tests so einrichten, dass sie vor dem Festschreiben ausgeführt werden, und dann den Code festschreiben.

Typische Szenarien, wenn Tests automatisch ausgeführt werden

  • Örtlich:
    • Kontinuierlich oder als Reaktion auf entsprechende Codeänderungen;
    • Beim Speichern (für interpretierte oder JIT-kompilierte Sprachen);
    • Während der Montage (wenn eine Kompilierung erforderlich ist);
    • Beim Commit;
    • Beim Veröffentlichen in einem freigegebenen Repository.

  • Auf dem Build-Server oder der Build-Umgebung:
    • Wenn Code in einem persönlichen Zweig/Repository veröffentlicht wird.
    • Der Code in diesem Thread wird getestet.
    • Das potenzielle Ergebnis der Fusion wird getestet (normalerweise mit master).
    • Als kontinuierliche Integrationsstufe/kontinuierliche Lieferpipeline

Je schneller eine Testsuite ausgeführt wird, desto häufiger können Sie es sich normalerweise leisten, sie auszuführen. Eine typische Bühnenverteilung könnte so aussehen.

  • Schnelle Unit-Tests – während des Builds, in der CI-Pipeline
  • Langsame Unit-Tests, schnelle Komponenten- und Integrationstests – beim Commit, in der CI-Pipeline
  • Langsame Komponenten- und Integrationstests – in der CI-Pipeline
  • Sicherheitstests, Lasttests und andere zeitaufwändige oder teure Tests – in CI/CD-Pipelines, aber nur in bestimmten Modi/Stufen/Pipelines des Builds, zum Beispiel bei der Vorbereitung eines Release Candidate oder bei manueller Ausführung.

️Aufgabe

Ich empfehle, die Tests zuerst manuell mit dem Befehl auszuführen npm test. Danach fügen wir einen Git-Hook hinzu, um unsere Tests beim Commit auszuführen. Es gibt einen Haken: Git-Hooks gelten nicht als Teil des Repositorys und können daher nicht zusammen mit den restlichen Kursmaterialien von GitHub geklont werden. Um Hook zu installieren, müssen Sie ausführen install_hook.sh oder kopieren Sie die Datei repo/hooks/pre-commit in das lokale Verzeichnis .git/hooks/.
Wenn Sie einen Commit durchführen, werden Sie sehen, dass Tests ausgeführt werden und überprüft wird, ob bestimmte Schlüsselwörter in der Liste vorhanden sind.

  1. Führen Sie die Tests manuell aus, indem Sie den Befehl ausführen npm test in Ihrem Kurs-Repository-Ordner. Stellen Sie sicher, dass die Tests abgeschlossen wurden.
  2. Setzen Sie durch Ausführen einen Commit-Hook (Pre-Commit-Hook). install_hook.sh.
  3. Übertragen Sie Ihre Änderungen in Ihr lokales Repository.
  4. Stellen Sie sicher, dass vor dem Festschreiben Tests ausgeführt werden.

Nachdem Sie diese Schritte ausgeführt haben, sollte Ihr Repository 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 Code in einem Remote-Repository oder Remote-Zweig

Sobald sie mit der lokalen Arbeit fertig sind, stellen Entwickler ihren Code normalerweise öffentlich zur Verfügung, damit er schließlich in die Öffentlichkeit integriert werden kann. Bei GitHub wird dies normalerweise durch die Veröffentlichung der Arbeit entweder in einer persönlichen Kopie des Repositorys (persönlicher Zweig) oder in einem persönlichen Zweig erreicht.

  • Bei Forks klont ein Entwickler ein gemeinsam genutztes Remote-Repository und erstellt eine persönliche Remote-Kopie davon, auch Fork genannt. Anschließend wird dieses persönliche Repository geklont, um lokal damit zu arbeiten. Wenn die Arbeit abgeschlossen ist und die Commits vorgenommen wurden, schiebt er sie in seinen Fork, wo sie für andere verfügbar sind und in das gemeinsame Repository integriert werden können. Dieser Ansatz wird häufig in Open-Source-Projekten auf GitHub verwendet. Es wird auch in meinem Aufbaukurs [Teamarbeit und CI mit Git] verwendet (http://devops.redpill.solutions/).
  • Ein anderer Ansatz besteht darin, nur ein Remote-Repository zu verwenden und nur den Zweig zu zählen master Gemeinsames Repository „geschützt“. In diesem Szenario veröffentlichen einzelne Entwickler ihren Code in Zweigen eines Remote-Repositorys, damit andere diesen Code ansehen und, wenn alles in Ordnung ist, mit ihm zusammenführen können master gemeinsames Repository.

In diesem speziellen Kurs verwenden wir einen Workflow, der Zweige verwendet.

Lassen Sie uns unseren Code veröffentlichen.

️Aufgabe

  • Veröffentlichen Sie Änderungen in einem Remote-Zweig mit demselben Namen wie Ihr Arbeitszweig

Befehle

git push --set-upstream origin feature

Erstellen Sie eine Pull-Anfrage

Erstellen Sie eine Pull-Anfrage mit einem Titel Überprüfung der Schritte... Installieren feature wie „Hauptzweig“ und master wie „Basiszweig“.

Stellen Sie sicher, dass Sie installiert haben master vor Forken Sie das Repository Als „Basiszweig“ reagiere ich nicht auf Änderungswünsche am Kursmaterial-Repository.

Im GitHub-Jargon ist der „Basiszweig“ der Zweig, auf dem Ihre Arbeit basiert, und der „Kopfzweig“ ist der Zweig, der die vorgeschlagenen Änderungen enthält.

Besprechen Sie die Änderungen und fügen Sie im weiteren Verlauf der Diskussion neue Commits hinzu

Pull-Anfrage (PR)

Pull-Anfrage (PR) ist eine Möglichkeit, Code zu diskutieren und zu dokumentieren sowie eine Codeüberprüfung durchzuführen. Pull Requests sind nach der allgemeinen Art und Weise benannt, einzelne Änderungen in den Gesamtcode zu integrieren. Normalerweise klont eine Person das offizielle Remote-Repository des Projekts und arbeitet lokal am Code. Danach legt er den Code in seinem persönlichen Remote-Repository ab und bittet die Verantwortlichen des offiziellen Repositorys, ihn abzuholen(ziehen) seinen Code in ihre lokalen Repositories, wo sie ihn überprüfen und möglicherweise integrieren(fusionieren) sein. Dieses Konzept ist auch unter anderen Namen bekannt, zum Beispiel Anfrage zusammenführen.

Sie müssen nicht unbedingt die Pull-Request-Funktion von GitHub oder ähnlichen Plattformen verwenden. Entwicklungsteams verwenden möglicherweise andere Kommunikationsmethoden, einschließlich persönlicher Kommunikation, Sprachanrufe oder E-Mail. Es gibt jedoch immer noch eine Reihe von Gründen für die Verwendung von Pull-Requests im Forum-Stil. Hier sind einige davon:

  • organisierte Diskussionen im Zusammenhang mit spezifischen Codeänderungen;
  • als Ort, um Feedback zu laufenden Arbeiten von Autotestern und Kollegen einzusehen;
  • Formalisierung von Codeüberprüfungen;
  • damit Sie später die Gründe und Überlegungen hinter diesem oder jenem Codeabschnitt herausfinden können.

Normalerweise erstellen Sie eine Pull-Anfrage, wenn Sie etwas besprechen oder Feedback einholen möchten. Wenn Sie beispielsweise an einer Funktion arbeiten, die auf mehr als eine Weise implementiert werden könnte, können Sie vor dem Schreiben der ersten Codezeile eine Pull-Anfrage erstellen, um Ihre Ideen zu teilen und Ihre Pläne mit Ihren Mitarbeitern zu besprechen. Wenn die Arbeit einfacher ist, wird ein Pull-Request geöffnet, wenn etwas bereits erledigt und festgeschrieben wurde und besprochen werden kann. In einigen Szenarien möchten Sie möglicherweise eine PR nur aus Gründen der Qualitätskontrolle öffnen: um automatisierte Tests durchzuführen oder Codeüberprüfungen zu initiieren. Wie auch immer Sie sich entscheiden, vergessen Sie nicht, in Ihrem Pull-Request die Personen zu @erwähnen, deren Zustimmung Sie wünschen.

Normalerweise gehen Sie beim Erstellen einer PR wie folgt vor.

  • Geben Sie an, was Sie wo ändern möchten.
  • Schreiben Sie eine Beschreibung, in der Sie den Zweck der Änderungen erläutern. Du möchtest vielleicht:
    • Fügen Sie alles Wichtige hinzu, das aus dem Code nicht ersichtlich ist, oder etwas, das zum Verständnis des Kontexts nützlich ist, wie etwa relevante #bugs und Commit-Nummern;
    • @erwähnen Sie jeden, mit dem Sie zusammenarbeiten möchten, oder Sie können ihn später in den Kommentaren @erwähnen;
    • Bitten Sie Kollegen, bei etwas zu helfen oder etwas Bestimmtes zu überprüfen.

Sobald Sie den PR öffnen, werden die für die Ausführung in solchen Fällen konfigurierten Tests ausgeführt. In unserem Fall handelt es sich dabei um die gleichen Tests, die wir lokal durchgeführt haben, aber in einem realen Projekt kann es zusätzliche Tests und Prüfungen geben.

Bitte warten Sie, bis die Tests abgeschlossen sind. Den Status der Tests können Sie unten in der PR-Diskussion in der GitHub-Oberfläche einsehen. Fahren Sie fort, wenn die Tests abgeschlossen sind.

️ Fügen Sie einen Hinweis zur Zufälligkeit der Liste der CI-Schritte hinzu

Die in diesem Kurs verwendete Liste ist willkürlich und subjektiv, wir sollten hierzu eine Anmerkung hinzufügen.

️ Aufgabe: Erstellen Sie eine Pull-Anfrage für diesen Kommentar

  1. Wechseln Sie zur Filiale master.
  2. Erstellen Sie einen Zweig mit dem Namen bugfix.
  3. Fügen Sie am Ende der Datei Notiztext hinzu ci.md.
    > **GitHub flow** is sometimes used as a nickname to refer to a flavor of trunk-based development  
    when code is deployed straight from feature branches. This list is just an interpretation  
    that I use in my [DevOps courses](http://redpill.solutions).  
    The official tutorial is [here](https://guides.github.com/introduction/flow/).
  4. Übernehmen Sie die Änderungen.
  5. Veröffentliche den Thread bugfix in ein Remote-Repository.
  6. Erstellen Sie eine Pull-Anfrage mit dem Namen Eine Bemerkung hinzufügen mit Kopfast bugfix und der Basiszweigmaster.

Stellen Sie sicher, dass Sie installiert haben master vor Forken Sie das Repository Als „Basiszweig“ reagiere ich nicht auf Änderungswünsche am Kursmaterial-Repository.

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 как описано выше

Pull-Anfrage „Hinzufügen einer Bemerkung“ genehmigen

️Aufgabe

  1. Erstellen Sie eine Pull-Anfrage.
  2. Klicken Sie auf „Pull-Anfrage zusammenführen“.
  3. Klicken Sie auf „Zusammenführung bestätigen“.
  4. Klicken Sie auf „Zweig löschen“, wir benötigen ihn nicht mehr.

Dies ist ein Diagramm der Commits nach einer Zusammenführung.
Typische Situationen bei kontinuierlicher Integration

️ Arbeiten Sie weiter und fügen Sie Tests hinzu

Die Zusammenarbeit an einem Pull-Request führt häufig zu zusätzlichem Aufwand. Dies ist normalerweise das Ergebnis einer Codeüberprüfung oder -diskussion, aber in unserem Kurs werden wir dies modellieren, indem wir unserer Liste der CI-Schritte neue Elemente hinzufügen.

Kontinuierliche Integration beinhaltet typischerweise eine gewisse Testabdeckung. Die Anforderungen an die Testabdeckung variieren und sind normalerweise in einem Dokument enthalten, das so etwas wie „Beitragsrichtlinien“ genannt wird. Wir halten es einfach und fügen unserer Checkliste für jede Zeile einen Test hinzu.

Versuchen Sie beim Ausführen von Aufgaben zunächst, die Tests festzuschreiben. Wenn Sie richtig installiert haben pre-commit Wenn Sie den Hook früher ausführen, wird der neu hinzugefügte Test ausgeführt, schlägt fehl und es wird nichts festgeschrieben. Beachten Sie, dass wir dadurch wissen, dass unsere Tests tatsächlich etwas testen. Wenn wir vor den Tests mit dem Code beginnen würden, könnte das Bestehen der Tests interessanterweise entweder bedeuten, dass der Code wie erwartet funktionierte, oder dass die Tests tatsächlich nichts testeten. Und wenn wir die Tests nicht von Anfang an geschrieben hätten, hätten wir sie vielleicht ganz vergessen, da uns nichts daran erinnert hätte.

Testgetriebene Entwicklung (TDD)

TDD empfiehlt, Tests vor dem Code zu schreiben. Ein typischer Workflow mit TDD sieht folgendermaßen aus.

  1. Fügen Sie einen Test hinzu.
  2. Führen Sie alle Tests aus und stellen Sie sicher, dass der neue Test fehlschlägt.
  3. Schreiben Sie den Code.
  4. Führen Sie die Tests durch und stellen Sie sicher, dass alle Tests erfolgreich sind.
  5. Refaktorieren Sie Ihren Code.
  6. Wiederholen.

Da die Ergebnisse von Tests, die nicht bestanden wurden, normalerweise in Rot und diejenigen, die bestanden wurden, normalerweise in Grün angezeigt werden, wird der Zyklus auch als Rot-Grün-Refaktor bezeichnet.

️Aufgabe

Versuchen Sie zunächst, die Tests festzuschreiben und sie fehlschlagen zu lassen, und fügen Sie dann den Text der CI-Schrittliste selbst hinzu und festschreiben Sie ihn. Sie werden sehen, dass die Tests bestanden werden („grün“).
Veröffentlichen Sie dann den neuen Code im Remote-Repository und beobachten Sie die Ausführung der Tests in der GitHub-Schnittstelle am Ende der Pull-Request-Diskussion und der PR-Statusaktualisierung.

  1. Wechseln Sie zur Filiale feature.
  2. Fügen Sie diese Tests hinzu ci.test.js nach dem letzten Anruf it (...);.

    it('5. Merge/rebase commits from master. Make tests pass on the merge result.', () => {
      expect(/.*merge.*commits.*testss+pass.*/ig.test(fileContents)).toBe(true);
    });
    
    it('6. Deploy from the feature branch to production.', () => {
      expect(/.*Deploy.*tos+production.*/ig.test(fileContents)).toBe(true);
    });
    
    it('7. If everything is good in production for some period of time, merge changes to master.', () => {
      expect(/.*merge.*tos+master.*/ig.test(fileContents)).toBe(true);
    });

  3. Versuchen Sie, die Tests durchzuführen. Wenn pre-commit Wenn der Hook installiert ist, schlägt der Commit-Versuch fehl.
  4. Dann fügen Sie diesen Text hinzu ci.md.
    5. Merge/rebase commits from master. Make tests pass on the merge result.  
    6. Deploy from the feature branch with a sneaky bug to production.
    7. If everything is good in production for some period of time, merge changes to master. 
  5. Nehmen Sie Änderungen lokal vor und übernehmen Sie sie.
  6. Veröffentlichen Sie Änderungen in der Filiale feature.

Sie sollten jetzt so etwas haben
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

Konflikt zusammenführen

Gehen Sie zu Änderungsantrag Überprüfung der Schritte.

Obwohl wir nichts falsch gemacht haben und die Tests für unseren Code bestanden haben, können wir den Zweig immer noch nicht zusammenführen feature и master. Es liegt am anderen Thread bugfix wurde mit verschmolzen master während wir an dieser PR arbeiteten.
Dadurch entsteht eine Situation, in der die Remote-Verzweigung erfolgt master hat eine neuere Version als die, auf der der Zweig basiert feature. Aus diesem Grund können wir HEAD nicht einfach zurückspulen master bis zum Ende des Threads feature. In dieser Situation müssen wir Commits entweder zusammenführen oder anwenden feature umbasieren master. GitHub kann tatsächlich automatische Zusammenführungen durchführen, wenn keine Konflikte vorliegen. Leider haben in unserer Situation beide Zweige konkurrierende Änderungen in der Datei ci.md. Diese Situation wird als Zusammenführungskonflikt bezeichnet und muss manuell gelöst werden.

Zusammenführen oder umbasieren

Merge

  • Erstellt einen zusätzlichen Merge-Commit und speichert den Arbeitsverlauf.
    • Behält die ursprünglichen Commits der Zweige mit ihren ursprünglichen Zeitstempeln und Autoren bei.
    • Speichert den SHA von Commits und verlinkt sie in Diskussionen über Änderungsanfragen.
  • Erfordert eine einmalige Konfliktlösung.
  • Macht die Geschichte nichtlinear.
    • Aufgrund der großen Anzahl an Zweigen (erinnert an ein IDE-Kabel) kann die Geschichte schwer zu lesen sein.
    • Erschwert das automatische Debuggen, z. B. git bisect weniger nützlich – es wird nur das Merge-Commit gefunden.

rebasieren

  • Wiederholt Commits aus dem aktuellen Zweig nacheinander über dem Basiszweig.
    • Es werden neue Commits mit neuen SHAs generiert, wodurch die Commits in GitHub mit den ursprünglichen Pull-Requests übereinstimmen, nicht jedoch mit den entsprechenden Kommentaren.
    • Commits können dabei neu kombiniert und geändert oder sogar zu einem zusammengeführt werden.
  • Möglicherweise müssen mehrere Konflikte gelöst werden.
  • Ermöglicht Ihnen, eine lineare Geschichte beizubehalten.
    • Die Geschichte ist möglicherweise einfacher zu lesen, solange sie nicht ohne triftigen Grund zu lang wird.
    • Automatisches Debuggen und Fehlerbehebung ist etwas einfacher: macht es möglich git bisect, kann automatische Rollbacks klarer und vorhersehbarer machen.
  • Erfordert die Veröffentlichung eines Zweigs mit migrierten Commits mit einem Flag --force bei Verwendung mit Pull-Requests.

Normalerweise vereinbaren Teams, immer die gleiche Strategie zu verwenden, wenn sie Änderungen zusammenführen müssen. Dies könnte eine „reine“ Zusammenführung oder ein „reiner“ Commit oben drauf oder etwas dazwischen sein, wie zum Beispiel die interaktive Durchführung eines Commits oben drauf(git rebase -i) lokal für Zweige, die nicht im öffentlichen Repository veröffentlicht sind, aber für „öffentliche“ Zweige zusammenführen.

Hier verwenden wir Merge.

️Aufgabe

  1. Stellen Sie sicher, dass sich der Code in einer lokalen Filiale befindet master von einem Remote-Repository aktualisiert.
  2. Wechseln Sie zur Filiale feature.
  3. Initiieren Sie eine Zusammenführung mit einem Zweig master. Ein Zusammenführungskonflikt aufgrund konkurrierender Änderungen an der ci.md.
  4. Lösen Sie den Konflikt, sodass sowohl unsere Liste der CI-Schritte als auch ein Hinweis dazu im Text verbleiben.
  5. Veröffentlichen Sie einen Merge-Commit in einem Remote-Zweig feature.
  6. Überprüfen Sie den Status der Pull-Anfrage in der GitHub-Benutzeroberfläche und warten Sie, bis die Zusammenführung gelöst ist.

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, дождитесь пока слияние не будет разрешено.

Ausgezeichnete Arbeit!

Sie sind mit der Liste fertig und müssen nun die Pull-Anfrage genehmigen master.

️ Aufgabe: Pull-Anfrage „Schritte überprüfen“ genehmigen

  1. Öffnen Sie eine Pull-Anfrage.
  2. Klicken Sie auf „Pull-Anfrage zusammenführen“.
  3. Klicken Sie auf „Zusammenführung bestätigen“.
  4. Klicken Sie auf „Zweig löschen“, da wir ihn nicht mehr benötigen.

Dies ist derzeit Ihr Repository
Typische Situationen bei kontinuierlicher Integration

Produktfehler

Es heißt, dass „Tests dazu dienen können, das Vorhandensein von Fehlern nachzuweisen, aber niemals, um deren Abwesenheit nachzuweisen.“ Obwohl wir Tests hatten und diese keine Fehler zeigten, schlich sich ein heimtückischer Fehler in die Produktion ein.

In einem Szenario wie diesem müssen wir uns um Folgendes kümmern:

  • was in der Produktion eingesetzt wird;
  • Code im Thread master mit einem Fehler, von dem aus Entwickler neue Arbeit beginnen können.

Sollte ich ein Rollback durchführen oder es in der nächsten Version beheben?

Beim Rollback handelt es sich um den Prozess, bei dem eine bekanntermaßen funktionierende frühere Version in der Produktion bereitgestellt und Commits, die den Fehler enthalten, zurückgesetzt werden. „Fixing Forward“ ist das Hinzufügen eines Fixes zum master und die neue Version so schnell wie möglich bereitzustellen. Da sich APIs und Datenbankschemata ändern, wenn Code in der Produktion bereitgestellt wird, ist bei kontinuierlicher Bereitstellung und guter Testabdeckung ein Rollback in der Regel viel schwieriger und riskanter als die Behebung in der nächsten Version.

Da das Zurücksetzen in unserem Fall kein Risiko birgt, werden wir diesen Weg gehen, weil er es uns ermöglicht

  • Beheben Sie den Fehler am Produkt so schnell wie möglich.
  • Code einbauen master sofort für den Einstieg in einen neuen Job geeignet.

️Aufgabe

  1. Wechseln Sie zur Filiale master örtlich
  2. Aktualisieren Sie das lokale Repository vom Remote-Repository.
  3. Setzen Sie den PR-Merge-Commit zurück Überprüfung der Schritte в master.
  4. Veröffentlichen Sie Änderungen in einem Remote-Repository.

Dies ist der Verlauf eines Repositorys mit einem zurückgesetzten 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

️ Selbsttest

Stelle sicher das ci.md Enthält nach dem Zurücksetzen eines Merge-Commits nicht mehr den Text „Sneaky Bug“.

Korrigieren Sie die Liste der CI-Schritte und geben Sie sie an den Master zurück

Wir haben den Merge-Commit des Zweigs vollständig zurückgesetzt. feature. Die gute Nachricht ist, dass wir jetzt keinen Fehler mehr haben master. Die schlechte Nachricht ist, dass auch unsere wertvolle Liste kontinuierlicher Integrationsschritte verschwunden ist. Im Idealfall müssen wir den Fix also auf die Commits von anwenden feature und gib sie zurück master zusammen mit dem Fix.

Wir können das Problem auf unterschiedliche Weise angehen:

  • einen Commit zurücksetzen, der eine Zusammenführung rückgängig macht feature с master;
  • Verschieben Sie Commits von ersterem feature.

Verschiedene Entwicklungsteams verwenden in diesem Fall unterschiedliche Ansätze, aber wir werden nützliche Commits in einen separaten Zweig verschieben und einen separaten Pull-Request für diesen neuen Zweig erstellen.

️Aufgabe

  1. Erstellen Sie einen Thread namens feature-fix und darauf umschalten.
  2. Migrieren Sie alle Commits aus dem vorherigen Zweig feature zu einem neuen Thread. Lösen Sie Zusammenführungskonflikte, die während der Migration aufgetreten sind.

    Typische Situationen bei kontinuierlicher Integration

  3. Fügen Sie einen Regressionstest hinzu 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 fehlschlagen.
  5. Entfernen Sie den Text „mit einem hinterhältigen Käfer“ in ci.md.
  6. Fügen Sie Teständerungen und Schrittlistenänderungen zum Index hinzu und übernehmen Sie sie.
  7. Veröffentlichen Sie den Zweig in einem Remote-Repository.

Am Ende sollten Sie etwas Ähnliches erhalten:
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 eine Pull-Anfrage.

Erstellen Sie eine Pull-Anfrage mit einem Titel Behebung der Funktion... Installieren feature-fix wie „Hauptzweig“ und master wie „Basiszweig“.
Bitte warten Sie, während die Tests abgeschlossen sind. Den Status der Tests können Sie am Ende der PR-Diskussion einsehen.

Stellen Sie sicher, dass Sie installiert haben master vor Forken Sie das Repository Als „Basiszweig“ reagiere ich nicht auf Änderungswünsche am Kursmaterial-Repository.

Pull-Anfrage „Reparatur der Funktion“ genehmigen

Danke für die Korrektur! Bitte genehmigen Sie die Änderungen an master aus Pull-Anfrage.

️Aufgabe

  1. Klicken Sie auf „Pull-Anfrage zusammenführen“.
  2. Klicken Sie auf „Zusammenführung bestätigen“.
  3. Klicken Sie auf „Zweig löschen“, da wir ihn nicht mehr benötigen.

Das sollten Sie im Moment haben.
Typische Situationen bei kontinuierlicher Integration

Herzlichen Glückwunsch!

Sie haben alle Schritte abgeschlossen, die normalerweise bei der kontinuierlichen Integration ausgeführt werden.

Wenn Sie Probleme mit dem Kurs bemerken oder wissen, wie Sie ihn verbessern können, erstellen Sie bitte ein Problem in Repositorien mit Kursmaterialien. Dieser Kurs hat auch interaktive Version Nutzung von GitHub Learning Lab als Plattform.

Source: habr.com

Kommentar hinzufügen