ProHoster > Blog > podávání > Průvodce CI/CD v GitLabu pro (téměř) absolutního začátečníka
Průvodce CI/CD v GitLabu pro (téměř) absolutního začátečníka
Aneb jak získat krásné odznaky pro svůj projekt za jeden večer snadného kódování
Pravděpodobně každý vývojář, který má alespoň jeden pet projekt, má někdy svědění z krásných odznaků se statusy, pokrytím kódu, verzemi balíčků v nugetu ... A toto svědění mě přivedlo k napsání tohoto článku. V rámci přípravy na psaní jsem v jednom ze svých projektů získal tuto krásu:
Tento článek vás provede základním nastavením průběžné integrace a doručování pro projekt knihovny tříd .Net Core v GitLab, publikováním dokumentace na GitLab Pages a odesíláním sestavených balíčků do soukromého kanálu v Azure DevOps.
Jako vývojové prostředí s rozšířením byl použit VS Code Pracovní postup GitLab (pro ověření souboru nastavení přímo z vývojového prostředí).
Stručný úvod
CD - je to, když jste právě zatlačili a vše už padlo na klienta?
Co je CI / CD a proč to potřebujete - můžete si to snadno vygooglit. Najděte kompletní dokumentaci o konfiguraci kanálů v GitLab také snadné. Zde stručně a pokud možno bez chyb popíšu proces systému z ptačí perspektivy:
vývojář odešle potvrzení do úložiště, vytvoří žádost o sloučení prostřednictvím webu, nebo nějakým jiným způsobem explicitně nebo implicitně spustí potrubí,
všechny úlohy jsou vybírány z konfigurace, jejíž podmínky umožňují jejich spuštění v daném kontextu,
úkoly jsou uspořádány podle jejich fází,
etapy se provádějí postupně - tzn. paralelní všechny úkoly této fáze jsou dokončeny,
pokud fáze selže (tj. alespoň jedna z úloh fáze selže), potrubí se zastaví (Skoro pořád),
pokud jsou všechny fáze úspěšně dokončeny, potrubí je považováno za úspěšné.
Máme tedy:
pipeline – sada úloh uspořádaných do fází, ve kterých můžete sestavit, testovat, zabalit kód, nasadit hotové sestavení do cloudové služby atd.,
etapa (fáze) — organizační jednotka potrubí, obsahuje 1+ úkol,
úkol (práce) je jednotka práce v potrubí. Skládá se ze skriptu (povinné), podmínek spouštění, nastavení pro publikování/ukládání artefaktů do mezipaměti a mnoho dalšího.
Úkol při nastavování CI / CD tedy spočívá ve vytvoření sady úkolů, které implementují všechny potřebné akce pro vytváření, testování a publikování kódu a artefaktů.
Než začnete: proč?
Proč Gitlab?
Protože když bylo nutné vytvořit soukromá úložiště pro pet projekty, byly placeny na GitHubu a já byl nenasytný. Úložiště se stala zdarma, ale zatím to není dostatečný důvod, abych přešel na GitHub.
Proč ne Azure DevOps Pipelines?
Protože tam je nastavení elementární - znalost příkazového řádku ani není potřeba. Integrace s externími poskytovateli git – na několik kliknutí, import SSH klíčů pro odeslání commitů do úložiště – také potrubí lze snadno konfigurovat, i když ne ze šablony.
Výchozí pozice: co máte a co chcete
Máme:
úložiště v GitLabu.
Chceme:
automatické sestavení a testování pro každý požadavek na sloučení,
sestavení balíčků pro každý požadavek na sloučení a odeslání do hlavního serveru za předpokladu, že ve zprávě odevzdání je určitý řádek,
odesílání sestavených balíčků do soukromého kanálu v Azure DevOps,
sestavení dokumentace a publikace v GitLab Pages,
odznaky!11
Popsané požadavky organicky spadají do následujícího modelu potrubí:
Fáze 1 - montáž
Shromažďujeme kód, publikujeme výstupní soubory jako artefakty
Fáze 2 - testování
Získáváme artefakty z fáze sestavení, spouštíme testy, shromažďujeme data o pokrytí kódu
Fáze 3 – Odeslat
Úkol 1 – sestavte balíček nuget a odešlete jej do Azure DevOps
Úkol 2 – shromáždíme web z xmldoc ve zdrojovém kódu a zveřejníme ho na stránkách GitLab
Po kliknutí na tlačítko Vytvořit se projekt vytvoří a budete přesměrováni na jeho stránku. Na této stránce můžete zakázat nepotřebné funkce tak, že přejdete do nastavení projektu (spodní odkaz v seznamu vlevo -> Přehled -> Blok Azure DevOps Services)
Přejděte na Atrifacts a klikněte na Vytvořit zdroj
Zadejte název zdroje
Vyberte viditelnost
Zrušte zaškrtnutí Zahrňte balíčky z běžných veřejných zdrojů, aby se zdroj nezměnil v klon dump nuget
Kliknutím na Connect to feed, vyberte Visual Studio, zkopírujte Source z bloku Machine Setup
Přejděte do nastavení účtu, vyberte Osobní přístupový token
Vytvořte nový přístupový token
Jméno - libovolné
Organizace – aktuální
Platnost maximálně 1 rok
Rozsah – Balení/čtení a zápis
Zkopírujte vytvořený token - po zavření modálního okna bude hodnota nedostupná
Přejděte do nastavení úložiště v GitLab, vyberte nastavení CI / CD
Rozbalte blok Proměnné, přidejte nový
Název - libovolný bez mezer (bude k dispozici v příkazovém shellu)
Hodnota - přístupový token z odstavce 9
Vyberte proměnnou masky
Tím je předkonfigurace dokončena.
Příprava konfiguračního rámce
Ve výchozím nastavení používá konfigurace CI/CD v GitLab soubor .gitlab-ci.yml z kořenového adresáře úložiště. V nastavení úložiště můžete nastavit libovolnou cestu k tomuto souboru, ale v tomto případě to není nutné.
Jak můžete vidět z rozšíření, soubor obsahuje konfiguraci ve formátu YAML. Dokumentace podrobně popisuje, které klíče mohou být obsaženy na nejvyšší úrovni konfigurace a na každé z vnořených úrovní.
Nejprve do konfiguračního souboru přidáme odkaz na obrázek dockeru, ve kterém se budou úkoly provádět. K tomu najdeme Stránka obrázků .Net Core na Docker Hub. V GitHub existuje podrobný návod, který obrázek vybrat pro různé úkoly. Obrázek s .Net Core 3.1 je pro nás vhodný k sestavení, takže neváhejte přidat první řádek do konfigurace
image: mcr.microsoft.com/dotnet/core/sdk:3.1
Nyní, když je kanál spuštěn z úložiště bitových kopií společnosti Microsoft, bude stažen zadaný obraz, ve kterém budou provedeny všechny úlohy z konfigurace.
Dalším krokem je přidání fáze's. Ve výchozím nastavení GitLab definuje 5 fází:
.pre - provedeny až do všech fází,
.post - provádí se po všech fázích,
build - první po .pre etapa,
test - druhá fáze,
deploy - třetí etapa.
Nic vám však nebrání je výslovně deklarovat. Pořadí, ve kterém jsou kroky uvedeny, ovlivňuje pořadí, ve kterém jsou prováděny. Pro úplnost dodejme ke konfiguraci:
stages:
- build
- test
- deploy
Pro ladění má smysl získat informace o prostředí, ve kterém jsou úkoly prováděny. Přidejme globální sadu příkazů, které budou provedeny před každou úlohou s before_script:
before_script:
- $PSVersionTable.PSVersion
- dotnet --version
- nuget help | select-string Version
Zbývá přidat alespoň jeden úkol, aby se po odeslání commitů spustil pipeline. Pro tuto chvíli přidáme prázdný úkol pro demonstraci:
dummy job:
script:
- echo ok
Spustíme ověřování, dostaneme zprávu, že je vše v pořádku, potvrdíme, zatlačíme, podíváme se na výsledky na webu ... A dostaneme chybu skriptu - bash: .PSVersion: command not found. WTF?
Vše je logické – ve výchozím nastavení používají běžci (odpovědní za provádění skriptů úloh a poskytovaných GitLab) bash provádět příkazy. Můžete to opravit tak, že v popisu úlohy explicitně určíte, jaké značky by měl mít spouštěcí kanál:
dummy job on windows:
script:
- echo ok
tags:
- windows
Skvělý! Potrubí nyní běží.
Pozorný čtenář si po zopakování uvedených kroků všimne, že úkol byl ve fázi dokončen test, i když jsme fázi neupřesnili. Jak asi tušíte test je výchozí krok.
Pokračujme ve vytváření kostry konfigurace přidáním všech výše popsaných úloh:
build job:
script:
- echo "building..."
tags:
- windows
stage: build
test and cover job:
script:
- echo "running tests and coverage analysis..."
tags:
- windows
stage: test
pack and deploy job:
script:
- echo "packing and pushing to nuget..."
tags:
- windows
stage: deploy
pages:
script:
- echo "creating docs..."
tags:
- windows
stage: deploy
Získali jsme sice nepříliš funkční, ale přesto správné potrubí.
Nastavení spouštěčů
Vzhledem k tomu, že pro žádnou z úloh nejsou specifikovány žádné spouštěcí filtry, potrubí bude plně být proveden pokaždé, když je potvrzení odesláno do úložiště. Protože toto obecně není žádoucí chování, nastavíme spouštěcí filtry pro úkoly.
Filtry lze konfigurovat ve dvou formátech: pouze/kromě и Pravidla. Krátce, only/except umožňuje konfigurovat filtry podle spouštěčů (merge_request, například - nastaví úlohu, která se má provést pokaždé, když je vytvořen požadavek na stažení a pokaždé, když jsou potvrzení odeslána do větve, která je zdrojem v požadavku na sloučení) a názvy větví (včetně použití regulárních výrazů); rules umožňuje přizpůsobit sadu podmínek a volitelně změnit podmínku provádění úlohy v závislosti na úspěchu předchozích úloh (when v GitLab CI/CD).
Připomeňme si sadu požadavků – sestavení a testování pouze pro žádost o sloučení, balení a odeslání do Azure DevOps – pro žádost o sloučení a odeslání do hlavního serveru, generování dokumentace – pro odeslání do hlavního serveru.
Nejprve nastavíme úlohu sestavení kódu přidáním pravidla, které se spustí pouze při požadavku na sloučení:
build job:
# snip
only:
- merge_request
Nyní nastavíme úlohu balení tak, aby se spustila při požadavku na sloučení a přidala potvrzení do hlavního serveru:
Za podmínek můžete použít zde uvedené proměnné; pravidla rules neslučitelné s pravidly only/except.
Konfigurace ukládání artefaktů
Během úkolu build job budeme mít vytvořené artefakty, které lze znovu použít v následujících úkolech. Chcete-li to provést, musíte do klíče přidat cesty ke konfiguraci úlohy, soubory, které budete muset uložit a znovu použít v následujících úlohách artifacts:
Cesty podporují zástupné znaky, což rozhodně usnadňuje jejich nastavení.
Pokud úkol vytvoří artefakty, pak k nim bude mít přístup každý následující úkol – budou umístěny podél stejných cest vzhledem ke kořenovému adresáři úložiště, které byly shromážděny z původního úkolu. Artefakty jsou také k dispozici ke stažení na webu.
Nyní, když máme připravený (a otestovaný) konfigurační rámec, můžeme přistoupit k samotnému psaní skriptů pro úlohy.
Píšeme scénáře
Možná, kdysi dávno, v předaleké galaxii, bylo budování projektů (včetně těch na .net) z příkazového řádku bolestí. Nyní můžete projekt sestavit, testovat a publikovat ve 3 týmech:
dotnet build
dotnet test
dotnet pack
Přirozeně existují určité nuance, kvůli kterým si příkazy poněkud zkomplikujeme.
Chceme sestavení verze, nikoli sestavení ladění, takže přidáváme ke každému příkazu -c Release
Při testování chceme sbírat data o pokrytí kódu, takže musíme do testovacích knihoven zahrnout analyzátor pokrytí:
Přidejte balíček do všech testovacích knihoven coverlet.msbuild: dotnet add package coverlet.msbuild ze složky projektu
Přidejte do příkazu testovacího běhu /p:CollectCoverage=true
Přidejte klíč do konfigurace testovací úlohy, abyste získali výsledky pokrytí (viz níže)
Při balení kódu do balíčků nuget nastavte výstupní adresář pro balíčky: -o .
Sběr dat pokrytí kódem
Po provedení testů Coverlet vytiskne statistiky běhu do konzole:
GitLab umožňuje zadat regulární výraz pro získání statistik, které pak lze získat ve formě odznaku. Regulární výraz se zadává v nastavení úlohy pomocí klíče coverage; výraz musí obsahovat skupinu zachycení, jejíž hodnota bude předána odznaku:
test and cover job:
# snip
coverage: /|s*Totals*|s*(d+[,.]d+%)/
Zde získáme statistiku z linky s celkovým pokrytím linky.
Publikujte balíčky a dokumentaci
Obě akce jsou naplánovány na poslední fázi potrubí – protože montáž a testy prošly, můžeme se o náš vývoj podělit se světem.
Nejprve zvažte publikování do zdroje balíčku:
Pokud projekt nemá konfigurační soubor nuget (nuget.config), vytvořte nový: dotnet new nugetconfig
Proč: obrázek nemusí mít přístup pro zápis do globálních (uživatelských a strojových) konfigurací. Abychom nechytali chyby, jednoduše vytvoříme novou lokální konfiguraci a pracujeme s ní.
Pojďme přidat nový zdroj balíčku do místní konfigurace: nuget sources add -name <name> -source <url> -username <organization> -password <gitlab variable> -configfile nuget.config -StorePasswordInClearText
name - název místního zdroje, není kritický
url - URL zdroje z fáze "Příprava účtů", str. 6
organization – název organizace v Azure DevOps
gitlab variable - název proměnné s přístupovým tokenem přidaným do GitLabu („Příprava účtů“, str. 11). Samozřejmě ve formátu $variableName
Všechny balíčky posíláme z aktuálního adresáře, tzn *.nupkg.
name - z výše uvedeného kroku.
key - libovolný řádek. V Azure DevOps je v okně Připojit ke zdroji příkladem vždy řádek az.
-skipduplicate - při pokusu o odeslání již existujícího balíčku bez tohoto klíče zdroj vrátí chybu 409 Conflict; pomocí tlačítka bude odeslání přeskočeno.
Nyní nastavíme tvorbu dokumentace:
Nejprve v úložišti, v hlavní větvi, inicializujeme projekt docfx. Chcete-li to provést, spusťte příkaz z kořenového adresáře docfx init a interaktivně nastavit klíčové parametry pro dokumentaci stavby. Podrobný popis minimálního nastavení projektu zde.
Při konfiguraci je důležité zadat výstupní adresář ..public - GitLab ve výchozím nastavení bere obsah veřejné složky v kořenovém adresáři úložiště jako zdroj pro Pages. Protože projekt bude umístěn ve složce vnořené v úložišti - přidejte výstup o úroveň výše v cestě.
Přeneseme změny do GitLabu.
Přidejte úkol do konfigurace kanálu pages (vyhrazené slovo pro úlohy publikování webu na stránkách GitLab):
Skript:
nuget install docfx.console -version 2.51.0 - nainstalovat docfx; verze je specifikována, aby bylo zajištěno, že instalační cesty balíčku jsou správné.
Dříve jsem při nastavování projektu zadal zdroj kódu pro dokumentaci jako soubor řešení. Hlavní nevýhodou je, že dokumentace se vytváří i pro testovací projekty. V případě, že to není nutné, můžete tuto hodnotu nastavit na uzel metadata.src:
metadata.src.src: "../" - jdeme o úroveň výš vzhledem k místu docfx.json, protože ve vzorech nefunguje vyhledávání ve stromu adresářů.
metadata.src.files: ["**/*.csproj"] - globální vzor, shromažďujeme všechny projekty C # ze všech adresářů.
metadata.src.exclude: ["*.tests*/**"] - globální vzor, vyloučit vše ze složek pomocí .tests V názvu
Mezisoučet
Takovou jednoduchou konfiguraci lze vytvořit za pouhou půlhodinu a pár šálků kávy, což vám umožní zkontrolovat, zda je kód sestaven a testy projdou, sestavit nový balíček, aktualizovat dokumentaci a potěšit oko krásným odznaky v souboru README projektu s každou žádostí o sloučení a odesláním hlavnímu serveru.
Finální .gitlab-ci.yml
image: mcr.microsoft.com/dotnet/core/sdk:3.1
before_script:
- $PSVersionTable.PSVersion
- dotnet --version
- nuget help | select-string Version
stages:
- build
- test
- deploy
build job:
stage: build
script:
- dotnet build -c Release
tags:
- windows
only:
- merge_requests
- master
artifacts:
paths:
- your/path/to/binaries
test and cover job:
stage: test
tags:
- windows
script:
- dotnet test -c Release /p:CollectCoverage=true
coverage: /|s*Totals*|s*(d+[,.]d+%)/
only:
- merge_requests
- master
pack and deploy job:
stage: deploy
tags:
- windows
script:
- dotnet pack -c Release -o .
- dotnet new nugetconfig
- nuget sources add -name feedName -source https://pkgs.dev.azure.com/your-organization/_packaging/your-feed/nuget/v3/index.json -username your-organization -password $nugetFeedToken -configfile nuget.config -StorePasswordInClearText
- nuget push -source feedName -skipduplicate -apikey az *.nupkg
only:
- master
pages:
tags:
- windows
stage: deploy
script:
- nuget install docfx.console -version 2.51.0
- $env:path = "$env:path;$($(get-location).Path)"
- .docfx.console.2.51.0toolsdocfx.exe .docfxdocfx.json
artifacts:
paths:
- public
only:
- master
Když už jsme u odznaků
Kvůli nim bylo koneckonců všechno odstartováno!
Odznaky se stavy kanálu a pokrytím kódu jsou k dispozici v GitLab v nastavení CI/CD v bloku Gtntral pipelines:
Vytvořil jsem odznak s odkazem na dokumentaci na platformě shields.io - tam je vše docela jednoduché, můžete si vytvořit svůj vlastní odznak a získat jej pomocí žádosti.
![Пример с Shields.io](https://img.shields.io/badge/custom-badge-blue)
Azure DevOps Artifacts také umožňuje vytvářet odznaky pro balíčky s nejnovější verzí. Chcete-li to provést, musíte ve zdroji na webu Azure DevOps kliknout na Vytvořit odznak pro vybraný balíček a zkopírovat označení:
Přidání krásy
Zvýraznění běžných konfiguračních fragmentů
Při psaní konfigurace a prohledávání dokumentace jsem narazil na zajímavou vlastnost YAML – opětovné použití fragmentů.
Jak můžete vidět z nastavení úlohy, všechny vyžadují značku windows u běžce a jsou spuštěny, když je odeslán požadavek na sloučení do hlavního/vytvořeného (kromě dokumentace). Přidejme to k fragmentu, který znovu použijeme:
A nyní můžeme vložit fragment deklarovaný dříve v popisu úlohy:
build job:
<<: *common_tags
<<: *common_only
Názvy fragmentů musí začínat tečkou, aby nebyly interpretovány jako úkol.
Verze balíčku
Při vytváření balíčku kompilátor kontroluje přepínače příkazového řádku a v případě jejich nepřítomnosti soubory projektu; když najde uzel Version, vezme jeho hodnotu jako verzi sestavovaného balíčku. Ukázalo se, že pro vytvoření balíčku s novou verzí jej musíte buď aktualizovat v souboru projektu, nebo jej předat jako argument příkazového řádku.
Přidejme ještě jeden Wishlist - nechť vedlejší dvě čísla ve verzi představují rok a datum sestavení balíčku a přidejte předběžné verze. Tato data můžete samozřejmě přidat do souboru projektu a zkontrolovat je před každým odesláním – ale můžete to udělat také v kanálu, shromáždit verzi balíčku z kontextu a předat ji argumentem příkazového řádku.
Shodneme se, že pokud zpráva odevzdání obsahuje řádek jako release (v./ver./version) <version number> (rev./revision <revision>)?, pak vezmeme verzi balíčku z tohoto řádku, doplníme ji o aktuální datum a předáme ji jako argument příkazu dotnet pack. Při absenci řádku si balíček prostě nevyzvedneme.
Tento problém řeší následující skript:
# регулярное выражение для поиска строки с версией
$rx = "releases+(v.?|ver.?|version)s*(?<maj>d+)(?<min>.d+)?(?<rel>.d+)?s*((rev.?|revision)?s+(?<rev>[a-zA-Z0-9-_]+))?"
# ищем строку в сообщении коммита, передаваемом в одной из предопределяемых GitLab'ом переменных
$found = $env:CI_COMMIT_MESSAGE -match $rx
# совпадений нет - выходим
if (!$found) { Write-Output "no release info found, aborting"; exit }
# извлекаем мажорную и минорную версии
$maj = $matches['maj']
$min = $matches['min']
# если строка содержит номер релиза - используем его, иначе - текущий год
if ($matches.ContainsKey('rel')) { $rel = $matches['rel'] } else { $rel = ".$(get-date -format "yyyy")" }
# в качестве номера сборки - текущие месяц и день
$bld = $(get-date -format "MMdd")
# если есть данные по пререлизной версии - включаем их в версию
if ($matches.ContainsKey('rev')) { $rev = "-$($matches['rev'])" } else { $rev = '' }
# собираем единую строку версии
$version = "$maj$min$rel.$bld$rev"
# собираем пакеты
dotnet pack -c Release -o . /p:Version=$version
Přidání skriptu k úloze pack and deploy job a striktně pozorovat sestavování balíčků v přítomnosti daného řetězce ve zprávě odevzdání.
Celkem
Po asi půlhodině nebo hodině psaní konfigurace, ladění v místním powershell a možná i několika neúspěšných spuštěních jsme dostali jednoduchou konfiguraci pro automatizaci rutinních úloh.
GitLab CI / CD je samozřejmě mnohem rozsáhlejší a mnohostrannější, než by se po přečtení této příručky mohlo zdát - to vůbec není pravda. Dokonce i tam Auto DevOps jeumožňující
automaticky detekovat, sestavovat, testovat, nasazovat a monitorovat vaše aplikace
Nyní je v plánu konfigurace kanálu pro nasazení aplikací do Azure pomocí Pulumi a automatického určování cílového prostředí, čemuž se budeme věnovat v dalším článku.