Typické situace při kontinuální integraci

Naučili jste se příkazy Git, ale chtěli byste vědět, jak probíhá kontinuální integrace (Continuous Integration, CI) ve skutečnosti? Nebo chcete optimalizovat své každodenní úkoly? Tento kurz vám poskytne praktické dovednosti v oblasti kontinuální integrace pomocí repozitáře na GitHubu. Kurz není navržen jako jakýsi wizard, kterým můžete jen proklikávat, naopak, budete provádět stejné úkony, které lidé skutečně dělají v práci, stejným způsobem, jakým je dělají. Budu vysvětlovat teorii, jak budete postupovat jednotlivými kroky, které s ní souvisejí.

Co budeme dělat?

Během postupu budeme postupně vytvářet seznam typických kroků CI, což je skvělý způsob, jak si tento seznam zapamatovat. Jinými slovy, vytvoříme seznam činností, které vývojáři vykonávají při realizaci kontinuální integrace. Také budeme používat jednoduchou sadu testů, abychom přiblížili náš proces CI k realitě.

Tento GIF schematicky zobrazuje commity ve vašem repozitáři, jak kurz postupuje. Jak vidíte, není na tom nic složitého a pouze to nejnutnější.

Typické situace při kontinuální integraci

Projdete standardními scénáři CI:

  • Práce na funkci;
  • Použití automatizovaných testů pro zajištění kvality;
  • Realizace prioritního úkolu;
  • Vyřešení konfliktu při sloučení větví (merge conflict);
  • Vznik chyby v produkčním prostředí.

Co se naučíte?

Budete schopni odpovědět na následující otázky:

  • Co je to kontinuální integrace (CI)?
  • Jaké typy automatizovaných testů se používají při CI a na základě jakých činností se spouští?
  • Co je to pull request a kdy jsou potřeba?
  • Co je to testem řízený vývoj (Test Driven Development, TDD) a jak souvisí s CI?
  • Proč provádět sloučení (merge) nebo aplikovat změny (rebase)?
  • Vrátit zpět nebo opravit v další verzi?

Na začátku jsem všude překládal výrazy jako "pull request", ale nakonec jsem se rozhodl vrátit některé fráze do angličtiny, abych snížil míru šílenství v textu. Občas budu používat "programátorskou hatmatilku" jako kouzelný sloveso "zakommitit", tam kde ho lidé skutečně používají v práci.

Co je to kontinuální integrace?

Kontinuální integrace, nebo CI, je technická praxe, která spočívá v tom, že každý člen týmu integruje svůj kód do společného repozitáře alespoň jednou denně, přičemž výsledný kód by měl být schopen kompilace bez chyb.

Existují rozporuplné názory na tento termín.

Předmětem sporu je frekvence integrace. Někteří tvrdí, že integrovat kód pouze jednou denně není dostatečné a ve skutečnosti bychom se měli integrací zabývat kontinuálně. Jako příklad je uváděn tým, kde si všichni ráno vezmou čerstvý kód a integrují se jen jednou večer. I když je to rozumná námitka, stále se obecně považuje, že definice 'jednou denně' je dost praktická, konkrétní a vhodná pro týmy různých velikostí.

Další námitka spočívá v tom, že C++ dávno není jediným jazykem používaným při vývoji a jednoduché požadavek na kompilaci bez chyb jako způsob validace je slabý. Nějaký soubor testů (např. modulových, prováděných lokálně) by také měl úspěšně projít. V současné době se komunita kloní k tomu, aby takový požadavek byl povinný a v budoucnu se 'kompilace + modulové testy' patrně stane běžnou praxí, pokud se to už nestalo.

Kontinuální integrace se liší od nepřetržité dodávky (Continuous Delivery, CD) tím, že nevyžaduje releasový kandidát po každém integračním cyklu.

Seznam kroků, které budeme používat během kurzu.

  1. Pull in the latest code. Create a branch from master. Začněte pracovat.
  2. Vytvořte commity na své nové větvi. Sestavte a testujte lokálně. Prošlo? Přejděte na další krok. Neprošlo? Opravit chyby nebo testy a zkuste to znovu.
  3. Push do svého vzdáleného repozitáře nebo vzdálené větve.
  4. Vytvořte pull request. Diskutujte o změnách, přidejte další commity během diskuse. Ujistěte se, že testy prošly na funkční větvi.
  5. Merge/rebase commity z masteru. Ujistěte se, že testy prošly na výsledku sloučení.
  6. Deploy ze funkční větve do produkce.
  7. Pokud je vše v produkci po nějakou dobu v pořádku, sloučte změny do masteru.

Typické situace při kontinuální integraci

️ Příprava

Ujistěte se, že máte potřebný software.

Abyste absolvovali tento kurz, budete potřebovat Node.js a Git klienta..

Můžete použít jakýkoli Git klient, ale já budu uvádět příkazy pouze pro příkazovou řádku.

Ujistěte se, že máte nainstalovaný Git klient, který podporuje příkazovou řádku.

Pokud ještě nemáte nainstalovaný Git klient, který podporuje příkazovou řádku, můžete najít pokyny k instalaci. zde.

Připravte repozitář.

Budete muset vytvořit osobní kopii (fork) repozitáře šablony s kódem pro kurz na GitHubu. Domluvme se, že tuto osobní kopii budeme nazývat repozitářem kurzu..

Hotovo? Pokud jste nezměnili výchozí nastavení, váš kurzový repozitář se pravděpodobně nazývá continuous-integration-team-scenarios-students, je umístěn ve vašem účtu na GitHubu a URL vypadá takto

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

Toto místo budu označovat jednoduše jako <URL репозитория>.

Úhlové závorky jako <тут> znamenají, že musíte nahradit takový výraz odpovídající hodnotou.

Ujistěte se, že GitHub actions jsou povolené pro tento kurzový repozitář. Pokud nebudou povolené, prosím, povolte je kliknutím na velké tlačítko uprostřed stránky, na které se dostanete kliknutím na Actions v uživatelském rozhraní GitHubu.

Nebudete schopni projít kurzem podle mých pokynů, pokud nebudou GitHub Actions povolené.

Typické situace při kontinuální integraci

Vždy můžete využít schopnost GitHubu zobrazovat Markdown a vidět aktuální stav seznamu, který zde vytváříme

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

O odpovědích

Ačkoli nejlepší způsob, jak dokončit tento kurz, je dělat vše vlastníma rukama, mohou nastat i potíže.

Pokud máte pocit, že nerozumíte, co dělat, a nemůžete pokračovat, můžete se podívat na větev solution, která se nachází ve vašem startovním repozitáři.
Prosím, neprovádějte sloučení solution v master během kurzu. Můžete použít tuto větev k tomu, abyste pochopili, co dělat, nebo k porovnání svého kódu s autorským, využívajíc všechny možnosti, které nám Git dává. Pokud jste úplně ztraceni, můžete svou větev master nahradit větví solution a poté resetovat svůj pracovní adresář na krok kurzu, který potřebujete.

Používejte to pouze pokud je to opravdu nutné

Zcommitujte svůj kód

git add .
git commit -m "Zálohování mé práce"

Tyto příkazy

  • přejmenovávají master v master-backup;
  • přejmenovávají solution v master;
  • přepínají(st checkout) na novou větev master a přepisují obsah pracovního adresáře;
  • vytvářejí větev "solution" z "master" (která byla dříve "solution") pro případ, že byste v budoucnu potřebovali větev "solution".

git branch -m master master-backup
git branch -m solution master
git checkout master -f
git branch solution

Po těchto akcích můžete použít git log master abyste zjistili, který commit potřebujete.
Můžete resetovat svůj pracovní adresář na tento commit takto:

git reset --hard

Pokud jste s výsledkem spokojeni, v určitém okamžiku budete potřebovat publikovat vaši verzi repozitáře na vzdálený repozitář. Nezapomeňte jasně uvést vzdálenou větev, když to budete dělat.

git push --force origin master

Věnujte prosím pozornost tomu, že používáme git push --force. Pravděpodobně nebudete chtít často takto postupovat, ale máme tu krajně specifický scénář s jedním uživatelem repozitáře, který navíc ví, co dělá.

Začneme pracovat

Typické situace při kontinuální integraci

Začněme sestavovat náš seznam kroků CI. Obvykle začínáte tento krok tím, že vytáhnete poslední verzi kódu z vzdáleného repozitáře, ale ještě nemáme lokální repozitář, takže místo toho ho klonujeme z vzdáleného.

️ Úkol: aktualizujte lokální repozitář, vytvořte větev z master, začněte pracovat

  1. Klonujte repozitář kurzu z <URL репозитория>.
  2. Spusťte npm install v adresáři repozitáře kurzu; je to pro nás potřeba k instalaci Jest, který používáme k provádění testů.
  3. Vytvořte větev a pojmenujte ji feature. Přepněte se na tuto větev.
  4. Přidejte testovací kód do ci.test.js mezi komentáři žádajícími o to.

    it('1. stáhnout nejnovější kód', () => {
      expect(/.*pull.*?/ig.test(fileContents)).toBe(true);
    });
    
    it('2. přidat commity', () => {
      expect(/.*commit.*?/ig.test(fileContents)).toBe(true);
    });
    
    it('3. push na vzdálenou větev se stejným názvem', () => {
      expect(/.*push.*?/ig.test(fileContents)).toBe(true);
    });
    
    it('4. vytvořit pull request a pokračovat v práci', () => {
      expect(/.*pulls+request.*?/ig.test(fileContents)).toBe(true);
    });

  5. Přidejte text s prvními 4 kroky do souboru ci.md.
    1. Stáhněte nejnovější kód. Vytvořte větev z `master`. Začněte pracovat.  
    2. Vytvořte commity na své nové větvi. Sestavte a otestujte lokálně.  
    Prošlo? Pokračujte na další krok. Selhalo? Opravit chyby nebo testy a zkuste to znovu.  
    3. Push na svůj vzdálený repozitář nebo vzdálenou větev.  
    4. Vytvořte pull request. Diskutujte o změnách, přidejte další commity  
    během pokračující diskuse. Nechte testy projít na vývojové větvi.  

    Příkazy

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

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

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

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

Vytvářejte commity na nové větvi, provádějte sestavování a testování lokálně

Chystáme se nastavit testy, aby se spouštěly před commitem, a poté zakomitovat kód.

Typické scénáře, kdy se testy spouštějí automaticky

  • Lokálně:
    • Nepřetržitě nebo v reakci na příslušné změny kódu;
    • Při ukládání (pro interpretované nebo JIT-kompilované jazyky);
    • Při sestavování (když je potřeba kompilace);
    • Při commitu;
    • Při publikaci do společného repozitáře.

  • Na sestavovacím serveru nebo v sestavovací prostředí:
    • Když je kód publikován do osobní větve / repozitáře.
    • Kód je testován v této větvi.
    • Je testován potenciální výsledek sloučení (obvykle s master).
    • Jako etapa kontinuální integrace / kontinuální dodávky

Obecně platí, že čím rychleji se sada testů vykonává, tím častěji si můžete dovolit ji spouštět. Typické rozdělení etap může vypadat takto.

  • Rychlé modulární testy — při sestavení, v CI konvaji
  • Pomalé modulární testy, rychlé komponentní a integrační testy — při commitu, v CI konvaji
  • Pomalé komponentní a integrační testy — v CI konvaji
  • Testování bezpečnosti, zátěžové a jiné dlouhé nebo nákladné testy — v CI/CD konvah, ale pouze v určitých režimech / etapách / konvaji sestavení, například při přípravě kandidáta na verzi nebo při manuálním spuštění.

️ Úkol

Navrhuji nejprve spustit testy ručně pomocí příkazu npm test. Poté přidejme git hook k spuštění našich testů při commitu. Je tu malý háček: Git hooky nejsou považovány za součást repozitáře a nemohou být proto klonovány z GitHubu spolu s ostatními materiály kurzu. K nastavení hooku musíte spustit install_hook.sh nebo zkopírovat soubor repo/hooks/pre-commit do místního adresáře .git/hooks/.
Při commitu uvidíte, že se testy vykonávají a kontrolují, zda jsou v seznamu určitá klíčová slova.

  1. Spusťte testy ručně, vykonáním příkazu npm test ve složce repozitáře vašeho kurzu. Ujistěte se, že testy byly provedeny.
  2. Nastavte hook pro commit (pre-commit hook) spuštěním install_hook.sh.
  3. Uložte změny do místního repozitáře.
  4. Ujistěte se, že testy probíhají před commitem.

Váš repozitář by měl vypadat takto po provedení těchto kroků.
Typické situace při kontinuální integraci

Příkazy

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

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

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

Publikujte kód do vzdáleného repozitáře nebo vzdálené větve

Po dokončení práce lokálně vývojáři obvykle zpřístupní svůj kód, aby ho bylo možné nakonec integrovat se společným. S pomocí GitHubu se toho obvykle dosahuje publikováním práce buď v osobní kopii repozitáře (personal fork), nebo v osobní větvi.

  • Při použití forků vývojář klonuje vzdálené sdílené úložiště a vytváří jeho osobní vzdálenou kopii, známou jako fork. Poté klonuje toto osobní úložiště, aby s ním mohl pracovat lokálně. Jakmile je práce dokončena a jsou vytvořeny commity, umisťuje je do svého forku, kde jsou dostupné ostatním a mohou být integrovány do společného úložiště. Tento přístup se obvykle používá v projektech s otevřeným zdrojovým kódem na GitHubu. Používá se také v mém pokročilém kurzu [Team Work and CI with Git]http://devops.redpill.solutions/).
  • Jiný přístup spočívá v používání pouze jednoho vzdáleného úložiště a považování pouze větve master sdíleného úložiště za "chráněnou". V tomto scénáři jednotliví vývojáři publikují svůj kód do větví vzdáleného úložiště, aby si ostatní mohli tento kód prohlédnout, a pokud je vše v pořádku, sloučit ho s master společného úložiště.

V tomto konkrétním kurzu budeme používat pracovní postup, který využívá větve.

Pojďme publikovat náš kód.

️ Úkol

  • Publikujte změny do vzdálené větve se stejným názvem jako vaše pracovní větev

Příkazy

git push --set-upstream origin feature

Vytvořte pull request

Vytvořte pull request s názvem Kroky k revizi. Nastavte feature jako "hlavní větev" a master jako "základní větev".

Ujistěte se, že jste nastavili master ve svém fork úložiště jako "základní větev", nebudu reagovat na žádosti o změny v úložišti s materiály kurzu.

Ve slangu GitHubu je "základní větev" větev, na které zakládáte svou práci, a "hlavní větev" je větev obsahující navrhované změny.

Diskutujte o změnách, přidejte nové commity, jak pokračuje diskuse

Pull request (PR)

Pull request (PR) je způsob, jak diskutovat a dokumentovat kód, a také provést kontrolu kódu (code review). Pull requesty jsou nazvány podle běžného způsobu integrace jednotlivých změn do společného kódu. Obvykle osoba klonuje vzdálené oficiální úložiště projektu a pracuje na kódu lokálně. Poté umístí kód do svého osobního vzdáleného úložiště a požádá osoby odpovědné za oficiální úložiště, aby vzalypull) jej do svých lokálních úložišť, kde jej prohlížejí a případně integrujísloučit) jej. Tento koncept je známý také jinými názvy, například merge request.

Ve skutečnosti není nutné používat funkci pull request na GitHubu nebo podobných platformách. Vývojářské týmy mohou používat jiné způsoby komunikace, včetně osobního setkání, telefonických hovorů nebo e-mailu, ale i tak existuje řada důvodů, proč používat pull requesty ve stylu diskuse na fóru. Zde je několik z nich:

  • organizované diskuse související s konkrétními změnami v kódu;
  • jako místo pro recenzi nedokončené práce jak od automatických testů, tak od kolegů;
  • formalizace kontrol kódu;
  • aby bylo možné později zjistit důvody a úvahy, které stojí za určitým fragmentem kódu.

Obvykle vytváříte pull request, když potřebujete něco prodiskutovat nebo získat zpětnou vazbu. Například pokud pracujete na funkci, která může být realizována několika způsoby, můžete vytvořit žádost o změnu ještě před napsáním prvního řádku kódu, abyste sdíleli své nápady a prodiskutovali své plány se spoluautory. Pokud je práce jednodušší, pull request se otevírá, když je něco již hotovo, zajištěno a může být projednáno. V některých scénářích můžete otevřít PR pouze z důvodů kontroly kvality: abyste spustili automatické testy nebo zahájili kontrolu kódu. Ať už se rozhodnete jakkoli, nezapomeňte @zmínit lidi, jejichž schválení je ve vašem pull requestu potřebné.

Obvykle při vytváření PR děláte následující.

  • Uvedete, co navrhujete změnit a kde.
  • Napíšete popis, který vysvětluje cíle změn. Můžete chtít:
    • přidat něco důležitého, co není z kódu zřejmé, nebo něco užitečného pro porozumění kontextu, například odpovídající #chyby a čísla commitů;
    • @zmínit všechny, s nimiž chcete začít spolupracovat, nebo je můžete @zmínit v komentářích později;
    • požádat kolegy o pomoc s něčím nebo zkontrolovat něco konkrétního.

Po otevření PR se spustí testy, které jsou nastaveny na spuštění v takových případech. V našem případě to bude stejný soubor testů, který jsme spouštěli lokálně, ale v reálném projektu mohou být další testy a kontroly.

Prosím, počkejte, až testy skončí. Stav testů můžete vidět na spodní části diskuze PR v rozhraní GitHub. Pokračujte, když budou testy dokončeny.

️ Přidejte upozornění o libovolnosti seznamu kroků CI

Seznam použitý v tomto kurzu je libovolný a subjektivní, měli bychom přidat poznámku o tom.

️ Úkol: vytvoření pull requestu pro tuto poznámku

  1. Přepněte se na větev master.
  2. Vytvořte větev s názvem bugfix.
  3. Přidejte text poznámky na konec souboru ci.md.
    > **GitHub flow** se někdy používá jako přezdívka pro variantu vývoje založeného na trunku,  
    když je kód nasazován přímo z feature větví. Tento seznam je pouze interpretací,  
     kterou používám ve svých [DevOps kurzech](http://redpill.solutions).  
    Oficiální tutoriál je [zde](https://guides.github.com/introduction/flow/).
  4. Zaveďte změny.
  5. Publikujte větev bugfix do vzdáleného repozitáře.
  6. Vytvořte pull request s názvem Přidání poznámky s hlavní větví bugfix a základní větvímaster.

Ujistěte se, že jste nastavili master ve svém fork úložiště jako "základní větev", nebudu reagovat na žádosti o změny v úložišti s materiály kurzu.

Takto by měl vypadat váš repozitář.
Typické situace při kontinuální integraci

Příkazy

# Переключитесь на ветку 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 как описано выше

Schvalte pull request "Přidání poznámky"

️ Úkol

  1. Vytvořte pull request.
  2. Klikněte na "Merge pull request".
  3. Klikněte na "Potvrdit sloučení".
  4. Klikněte na "Smazat větev", již ji nepotřebujeme.

Tohle je diagram commitů po sloučení.
Typické situace při kontinuální integraci

️ Pokračujte v práci a přidejte testy.

Spolupráce na pull requestu často vede k potřebě další práce. Obvykle je to důsledkem kontroly kódu nebo diskuze, ale v našem kurzu budeme simulovat to, že přidáme nové položky do našeho seznamu kroků CI.

Při kontinuální integraci se obvykle používá nějaké pokrytí testy. Požadavky na pokrytí testy se liší a obvykle se nacházejí v dokumentu s názvem jako "průvodce pro autory" (contribution guidelines). My to zjednodušíme a přidáme jeden test pro každý řádek v našem kontrolním seznamu.

Při plnění úkolů se nejprve pokuste zcommittovat testy. Pokud jste správně nastavili pre-commit hook dříve, právě přidaný test se spustí, nebude úspěšný a nic nebude zcommittováno. Všimněte si: tím se dozvíme, že naše testy skutečně něco kontrolují. Zajímavé je, že pokud bychom začali kódem před testy, úspěch testů by mohl znamenat jak to, že kód funguje, jak bylo očekáváno, tak to, že testy vlastně nic nekontrolují. Kromě toho, pokud bychom testy vůbec nenapsali, mohli bychom na ně zapomenout, protože by nám nic nepřipomínalo.

Vývoj prostřednictvím testování (TDD)

TDD doporučuje psát testy před kódem. Běžný pracovní proces pomocí TDD vypadá takto.

  1. Přidejte test.
  2. Spusťte všechny testy a ujistěte se, že nový test neprochází úspěšně.
  3. Napište kód.
  4. Spusťte testy, ujistěte se, že všechny testy procházejí úspěšně.
  5. Proveďte refaktoring kódu.
  6. Opakujte.

Protože výsledky testů, které nebyly úspěšně splněny, se obvykle zobrazují červeně, zatímco úspěšné — zeleně, cyklus je také známý jako "červená-zelená-refaktoring".

️ Úkol

Nejprve zkuste commitnout testy a nechat je skončit neúspěšně, poté přidejte a commitněte samotný text seznamu kroků CI. Uvidíte, že testy prochází ("zelené").
Poté publikujte nový kód do vzdáleného repozitáře a sledujte, jak se testy vykonávají v rozhraní GitHub v dolní části diskuse o pull requestu, a aktualizuje se stav PR.

  1. Přepněte se na větev feature.
  2. Přidejte tyto testy do ci.test.js po posledním volání it (...);.

    it('5. Merge/rebase commits from master. Make tests pass on the merge result.', () => {
      expect(/.*merge.*commits.*tests+pass.*/ig.test(fileContents)).toBe(true);
    });
    
    it('6. Deploy from the feature branch to production.', () => {
      expect(/.*Deploy.*to+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.*to+master.*/ig.test(fileContents)).toBe(true);
    });

  3. Zkuste commitnout testy. Pokud pre-commit hook je nastaven, pokus o commit skončí chybou.
  4. Po přidejte tento text do 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. Změny proveďte a commitněte lokálně.
  6. Publikujte změny do větve feature.

Nyní byste měli mít něco jako toto
Typické situace při kontinuální integraci

Příkazy


# Переключительна ветку 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 sloučení

Přejděte k pull requestu Kroky k revizi.

I když jsme neudělali nic špatného a testy našeho kódu prošly úspěšně, stále nemůžeme provést sloučení větve feature a master. Je to proto, že jiná větev bugfix byla sloučena s master zatímco jsme pracovali na tomto PR.
To vytváří situaci, kdy má vzdálená větev master novější verzi než ta, na které jsme založili naši větev feature. Kvůli tomu nemůžeme prostě přetáčet HEAD master na konec větve feature. V této situaci potřebujeme buď provést sloučení, nebo aplikovat commity feature na povrchu. masterGitHub skutečně může provádět automatické sloučení, pokud nejsou žádné konflikty. Bohužel, v naší situaci mají obě větve konkurenční změny v souboru. ci.mdTato situace je známá jako konflikt při sloučení (merge conflict) a musíme ji vyřešit ručně.

Merge nebo rebase

Merge

  • Vytváří další sloučený commit (merge commit) a uchovává historii práce.
    • Uchovává původní commity větví s původními časovými razítky a autory.
    • Uchovává SHA commitů a odkazy na ně v diskusích o pull requestech.
  • Vyžaduje jednorázové vyřešení konfliktů.
  • Dělá historii nelineární.
    • Historii může být obtížné číst kvůli velkému množství větví (připomíná kabel IDE).
    • Ztěžuje automatické ladění, například dělá git bisect méně užitečným – pouze najde sloučený commit.

Rebase

  • Reprodukuje commity z aktuální větve na základně jeden po druhém.
    • Vytvářejí se nové commity s novými SHA, v důsledku čehož jsou commity v GitHubu spojeny s původními pull requesty, ale ne s příslušnými komentáři.
    • Commity mohou být rekombinovány a změněny v průběhu nebo dokonce sloučeny do jednoho.
  • Může být nutné vyřešit několik konfliktů.
  • Umožňuje udržovat lineární historii.
    • Historii může být snadnější číst, pokud není příliš dlouhá bez rozumných důvodů.
    • Automatické ladění a odstraňování problémů je poněkud jednodušší: umožňuje git bisect, může udělat automatické vracení jasnější a předvídatelnější.
  • Vyžaduje publikování větve s přesunutými commity s příznakem --force při použití s požadavky na změny.

Obvykle se týmy dohodnou, že vždy použijí stejnou strategii, když je třeba sloučit změny. Může to být "čisté" sloučení nebo "čisté" použití commitů jako nadstavby, nebo něco mezi tím, například provést použití commitů v interaktivním režimu (git rebase -i) lokálně pro větve, které nejsou publikovány v společném repozitáři, ale sloučení (merge) pro "veřejné" větve.

Zde budeme používat sloučení.

️ Úkol

  1. Ujistěte se, že kód v místní větvi master je aktuální z vzdáleného repozitáře.
  2. Přepněte se na větev feature.
  3. Iniciujte sloučení s větví master. Bude oznámen konflikt sloučení související s konkurenčními změnami. ci.md.
  4. Umožněte konflikt tak, aby text obsahoval jak náš seznam kroků CI, tak poznámku k tomu.
  5. Publikujte sloučený commit do vzdálené větve feature.
  6. Zkontrolujte stav pull requestu v uživatelském rozhraní GitHubu a počkejte, až bude sloučení vyřešeno.

Příkazy

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

Skvělá práce!

Dokončili jste práci se seznamem a teď je třeba schválit pull request v master.

️ Úkol: Schválit pull request "Revize kroků"

  1. Otevřete pull request.
  2. Klikněte na "Merge pull request".
  3. Klikněte na "Potvrdit sloučení".
  4. Klikněte na "Smazat větev", protože ji už nepotřebujeme.

To je váš repozitář v tuto chvíli.
Typické situace při kontinuální integraci

Chyba na produkci

Říká se, že „testování může být použito k prokázání existence chyb, ale nikdy k prokázání jejich absence“. I když jsme měli testy, které nám žádné chyby neukázaly, proklouzla nám do produkce záludná chyba.

V takovém scénáři musíme věnovat pozornost:

  • tomu, co je nasazeno na produkci;
  • kódu ve větvi master s chybou, ze které mohou vývojáři začít novou práci.

Vrátit zpět nebo opravit v další verzi?

"Vrátit zpět" (rolling back) je nasazení známé opravené starší verze do produkčního prostředí a zrušení (revert) commitů obsahujících chybu. "Opravit v další verzi" (fixing forward) je přidání opravy do master a nasazení nové verze co nejdříve. Protože se API a databázové schémata mění při nasazování kódu do produkčního prostředí, při kontinuální dodávce a pokud máme dobré pokrytí testy, vracení zpět je obvykle mnohem složitější a rizikovější než oprava v další verzi.

Protože vracení zpět v našem případě nenese žádné riziko, půjdeme touto cestou, protože nám to umožňuje

  • opravit chybu na produkci co nejdříve;
  • udělat kód v master ihned použitelný pro začátek nové práce.

️ Úkol

  1. Přepněte se na větev master lokálně.
  2. Aktualizujte místní repozitář z dálkového repozitáře.
  3. Zrušte commit sloučení PR Kroky k revizi v master.
  4. Publikovat změny do vzdáleného repozitáře.

Toto je historie repozitáře se zrušeným commitem sloučení
Typické situace při kontinuální integraci

Příkazy

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

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

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

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

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

️ Sebeověřování

Ujistěte se, že ci.md už neobsahuje text "sneaky bug" po zrušení commitu sloučení.

Opravit seznam kroků CI a vrátit ho do master

Úplně jsme zrušili commit sloučení větve feature. Dobrou zprávou je, že nyní nemáme žádnou chybu v master. Špatná zpráva je, že zmizel i náš cenný seznam kroků kontinuální integrace. Takže ideálně bychom měli aplikovat opravu na commity z feature a vrátit je zpět do master spolu s opravou.

K úkolu se můžeme přistupovat různými způsoby:

  • vrátit (revert) commit, který vrací mergování feature s master;
  • přesunout commity z bývalé feature.

Různé týmy vývojářů v tomto případě používají různé přístupy, my však přesuneme užitečné commity do nové větve a vytvoříme samostatný pull request pro tuto novou větev.

️ Úkol

  1. Vytvořte větev s názvem feature-fix a přepněte se na ni.
  2. Přesuňte všechny commity z bývalé větve feature do nové větve. Vyřešte konflikty sloučení, které vznikly při přesunu.

    Typické situace při kontinuální integraci

  3. Přidejte regresní test do ci.test.js:

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

  4. Spusťte testy lokálně, abyste se ujistili, že nevytvářejí žádné úspěšné výsledky.
  5. Odstraňte text " with a sneaky bug" v ci.md.
  6. Přidejte do indexu změny testů a změny v seznamu kroků a commitujte je.
  7. Publikujte větev do vzdáleného repozitáře.

Měli byste mít něco podobného
Typické situace při kontinuální integraci

Příkazy

# Создайте ветку под названием 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

Vytvořte pull request.

Vytvořte pull request s názvem Fixing the feature. Nastavte feature-fix jako "head branch", a master jako "základní větev".
Prosím, počkejte, dokud se testy nedokončí. Stav testů můžete vidět ve spodní části diskuze PR.

Ujistěte se, že jste nastavili master ve svém fork úložiště jako "základní větev", nebudu reagovat na žádosti o změny v úložišti s materiály kurzu.

Schvalte pull request "Fixing the feature"

Děkujeme za opravu! Prosím, schvalte změny v master z pull request.

️ Úkol

  1. Klikněte na "Merge pull request".
  2. Klikněte na "Potvrdit sloučení".
  3. Klikněte na "Smazat větev", protože ji už nepotřebujeme.

To je to, co byste měli mít v tuto chvíli
Typické situace při kontinuální integraci

Gratulujeme!

Provedli jste všechny kroky, které lidé obvykle provádějí v procesu kontinuální integrace.

Pokud jste si všimli nějakých problémů s kurzem nebo víte, jak jej vylepšit, vytvořte issue v repozitáři s materiály kurzu. Tento kurz má také interaktivní verzi využívající GitHub Learning Lab jako platformu.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster