Go tools & GitLab - ako robiť kontinuálnu integráciu ako šéf

Foto Todd Quackenbush na Unsplash

V spoločnosti Pantomath používame GitLab pre všetky naše vývojové práce. Účelom tohto príspevku nie je predstaviť GitLab a všetky jeho vlastnosti, ale predstaviť, ako tieto nástroje používame na uľahčenie našich životov.

O čo vlastne ide? Automatizujte všetko, čo súvisí s vaším vývojovým projektom, a nechajte sa zamerať na svoj kód. Pokryjeme chuchvalce, jednotkové testy, dátovú rasu, dezinfekciu pamäte, pokrytie kódu a zostavenie.

Celý kód uvedený v tomto príspevku je k dispozícii na adrese https://gitlab.com/pantomath-io/demo-tools. Neváhajte teda získať archív a pomocou značiek sa v ňom pohybovať. Úložisko by malo byť umiestnené v priečinku src vášho $ GOPATH:

$ go get -v -d gitlab.com/pantomath-io/demo-tools
$ cd $ GOPATH / src / gitlab.com / pantomath-io / demo-tools

Choďte nástroje

Našťastie, Go prichádza s množstvom užitočných nástrojov na zostavenie, testovanie a kontrolu vášho kódu. V skutočnosti je to všetko tam. Pridáme len ďalšie nástroje na ich zlepenie. Ale predtým, ako tam pôjdeme, musíme ich zobrať jeden po druhom a uvidíme, čo robia.

Zoznam balíkov

Váš projekt go je zbierka balíkov opísaná v oficiálnom dokumente. Väčšina z nasledujúcich nástrojov bude zásobovaná týmito balíkmi, a preto prvý príkaz, ktorý potrebujeme, je spôsob, ako vypísať zoznam balíkov. Dúfajme, že ísť pokrýva chrbát s čiastkovým príkazom zoznamu (prečítajte si podrobnú príručku a tento vynikajúci príspevok od Davea Cheneyho):

$ go list. / ...

Upozorňujeme, že sa chceme vyhnúť použitiu našich nástrojov na externé zdroje a obmedziť ich na náš kód. Preto sa musíme zbaviť adresárov dodávateľov:

$ go list. / ... | grep -v / vendor /

cupanina

Toto je prvý nástroj, ktorý v kóde používame: linter. Jeho úlohou je zabezpečiť, aby kód rešpektoval štýl kódu. Môže to znieť ako voliteľný nástroj alebo prinajmenšom „príjemné“, ale skutočne pomáha udržiavať konzistentný štýl vášho projektu.

Tento ukazovateľ nie je súčasťou samého osebe, takže ho musíte chytiť a nainštalovať ručne (pozri oficiálny dokument).

Použitie je pomerne jednoduché: stačí ho spustiť na balíčkoch kódu (môžete tiež nasmerovať súbory .go):

$ golint -set_exit_status $ (choďte na zoznam. / ... | grep -v / vendor /)

Všimnite si možnosť -set_exit_status. V predvolenom nastavení golint tlačí iba problémy so štýlom a vracia sa (s návratovým kódom 0), takže CI nikdy nepovažuje niečo pokazené. Ak zadáte -set_exit_status, návratový kód od golint sa bude líšiť od 0, ak sa vyskytne akýkoľvek problém so štýlom.

Test jednotky

Toto sú najbežnejšie testy, ktoré môžete spustiť vo svojom kóde. Pre každý súbor .go potrebujeme mať pridružený súbor _test.go obsahujúci testy jednotiek. Testy pre všetky balíčky môžete spustiť pomocou nasledujúceho príkazu:

$ go test -short $ (choďte na zoznam. / ... | grep -v / vendor /)

Preteky dát

Toto je zvyčajne ťažké pokryť, ale nástroj go to má predvolene (ale k dispozícii iba na linux / amd64, freebsd / amd64, darwin / amd64 a windows / amd64). Ďalšie informácie o dátovom závode nájdete v tomto článku. Medzitým tu je návod, ako to spustiť:

$ go test -race -short $ (choďte na zoznam. / ... | grep -v / vendor /)

Sanitizér pamäte

Clang má pekný detektor pre neinicializované čítania s názvom MemorySanitizer. Nástroj go test je taký láskavý, aby mohol pracovať s týmto modulom Clang (hneď ako sa nachádzate na hostiteľovi linux / amd64 a používate najnovšiu verziu programu Clang / LLVM (> = 3,8.0). Týmto príkazom ho spustíte:

$ go test -msan -short $ (choďte na zoznam. / ... | grep -v / vendor /)

Pokrytie kódom

Je to tiež potrebné vyhodnotiť zdravie vášho kódu a zistiť, ktorá časť kódu je predmetom jednotkových testov a ktorá nie. Rob Pike napísal celý príspevok na túto tému.

Aby sme mohli vypočítať pomer pokrytia kódu, musíme spustiť nasledujúci skript:

$ PKG_LIST = $ (choďte na zoznam. / ... | grep -v / vendor /)
$ za balík v $ {PKG_LIST}; robiť
    go test -covermode = count -coverprofile "cover / $ {package ## * /}. cov" "$ package";
hotový
$ tail -q -n +2 cover / *. cov >> cover / cover.cov
$ go tool cover -func = krytie / krytie.cov

Ak chceme získať správu o pokrytí vo formáte HTML, musíme pridať nasledujúci príkaz:

$ go tool cover -html = cover / krytie.cov -o krytie.html

vybudovať

V neposlednom rade, akonáhle bol kód úplne otestovaný, možno ho budeme chcieť skompilovať, aby sme mohli vytvoriť funkčný binárny kód.

$ go build -i -v gitlab.com/pantomath-io/demo-tools

Makefile

git tag: init-makefile

Foto Matt Artz na Unsplash

Teraz máme všetky nástroje, ktoré môžeme použiť v kontexte kontinuálnej integrácie, môžeme ich všetky zabaliť do Makefilu a mať jednotný spôsob, ako ich nazvať.

Účelom tohto dokumentu nie je prezentovať značku, ale o oficiálnych dokumentoch sa môžete dozvedieť viac.

PROJECT_NAME: = "demo-nástroje"
PKG: = "gitlab.com/pantomath-io/$(PROJECT_NAME)"
PKG_LIST: = $ (shell go list $ {PKG} / ... | grep -v / vendor /)
GO_FILES: = $ (shell find. -Name '* .go' | grep -v / vendor / | grep -v _test.go)
.PHONY: všetky dep stavajú čisté testovacie pokrytie
všetko: build
lint: ## Lint súbory
 @golint -set_exit_status $ {PKG_LIST}
test: ## Spustenie testov jednotiek
 @go test -short $ {PKG_LIST}
závod: dep ## Spustiť detektor závodov s údajmi
 @go test -race -short $ {PKG_LIST}
msan: dep ## Spustenie dezinfekčného zariadenia pamäte
 @go test -msan -short $ {PKG_LIST}
pokrytie: ## Generovať správu o globálnom pokrytí kódu
 ./tools/coverage.sh;
coverhtml: ## Generovanie správy o globálnom pokrytí kódu v HTML
 ./tools/coverage.sh html;
dep: ## Získajte závislosti
 @go get -v -d. / ...
build: dep ## Zostavte binárny súbor
 @go build -i -v $ (PKG)
clean: ## Odstrániť predchádzajúce zostavenie
 @rm -f $ (PROJECT_NAME)
help: ## Zobraziť túto obrazovku pomocníka
 @grep -h -E '^ [a-zA-Z _-] +:. *? ##. * $$' $ (MAKEFILE_LIST) | awk 'BEGIN {FS = ":. *? ##"}; {printf "\ 033 [36m% -30s \ 033 [0m% s \ n", $$ 1, $$ 2} '

Čo máme teraz? Jeden cieľ pre akýkoľvek predtým predstavený nástroj a 3 ďalšie ciele pre:

  • inštalácia závislostí (dep);
  • upratovanie projektu (čisté);
  • nejaká pekná a lesklá pomoc (pomoc).

Všimnite si, že sme museli tiež vytvoriť skript pre prácu s pokrytím kódu. Je to preto, že implementácia slučiek na súbory v makefile je bolesť. Takže práca sa vykonáva v bash skripte a Makefile spustí iba tento skript.

Makefile môžete vyskúšať pomocou nasledujúcich príkazov:

$ pomôcť
$ make lint
$ zarobiť

Nepretržitá integrácia

git tag: init-ci

Foto: Max Panamá, Unsplash

Nástroje sú už k dispozícii a my môžeme v našom kóde spustiť rôzne testy, radi by sme ich vo vašom úložisku automatizovali. Našťastie GitLab ponúka práve na tento účel plynovody CI. A nastavenie je veľmi jednoduché: všetko, čo vytvoríte, je súbor .gitlab-ci.yml v koreňovom adresári úložiska.

Úplná dokumentácia k tomuto súboru Yaml ponúka všetky možnosti, ale môžete začať s týmto súborom .gitlab-ci.yml:

obrázok: golang: 1.9
cache:
  cesty:
    - / apt-cache
    - /go/src/github.com
    - /go/src/golang.org
    - /go/src/google.golang.org
    - /go/src/gopkg.in
etapy:
  - test
  - stavať
before_script:
  - mkdir -p /go/src/gitlab.com/pantomath-io / go / src / _ / builds
  - cp -r $ CI_PROJECT_DIR /go/src/gitlab.com/pantomath-io/pantomath
  - ln -s /go/src/gitlab.com/pantomath-io / go / src / _ / builds / pantomath-io
  - urobiť dep
unit_tests:
  fáza: test
  scenár:
    - urobiť test
race_detector:
  fáza: test
  scenár:
    - urobiť závod
memory_sanitizer:
  fáza: test
  scenár:
    urobiť msan
code_coverage:
  fáza: test
  scenár:
    - urobiť krytie
code_coverage_report:
  fáza: test
  scenár:
    urobte coverhtml
  iba:
  - majster
lint_code:
  fáza: test
  scenár:
    - urobiť chĺpky
zostavení:
  fáza: zostavenie
  scenár:
    - urobiť

Ak súbor rozdelíte, uvádzame niekoľko vysvetlení jeho obsahu:

  • Prvou vecou je vybrať, aký obrázok Docker sa použije na spustenie CI. Zamierte na Docker Hub a vyberte si ten správny obrázok pre svoj projekt.
  • Potom určíte niektoré priečinky tohto obrázka, ktoré sa majú uložiť do vyrovnávacej pamäte. Cieľom je zabrániť tomu, aby sa ten istý obsah niekoľkokrát sťahoval. Po dokončení úlohy sa uvedené cesty archivujú a ďalšia úloha použije ten istý archív.
  • Definujete rôzne fázy, ktoré zoskupia vaše úlohy. V našom prípade máme dve fázy (ktoré sa majú spracovať v tomto poradí): test a zostavenie. Mohli by sme mať aj iné fázy, napríklad nasadenie.
  • Sekcia before_script definuje príkazy, ktoré sa majú spustiť v kontajneri Docker tesne pred vykonaním úlohy. V našom kontexte príkazy jednoducho skopírujú alebo prepojia úložisko nasadené v $ GOPATH a nainštalujú závislosti.
  • Potom príďte skutočné úlohy pomocou cieľov Makefile. Všimnite si špeciálny prípad pre code_coverage_report, kde je vykonávanie obmedzené na hlavnú vetvu (nechceme napríklad aktualizovať správu o pokrytí kódu napríklad z vetiev funkcií).

Keď v úložisku potvrdíme / vytlačíme súbor .gitlab-ci.yml, automaticky sa spustí CI. A potrubie zlyhá. Ako to?

Úloha lint_code zlyhá, pretože nemôže nájsť binárny golint:

$ make lint
make: golint: Príkaz nebol nájdený
Makefile: 11: Recept na cieľovú 'vlákna' zlyhal
make: *** [lint] Chyba 127

Takže aktualizujte svoj Makefile tak, aby nainštaloval golint ako súčasť cieľa dep.

Úloha memory_sanitizer zlyhá, pretože gcc si sťažuje:

$ make msan
# runtime / cgo
gcc: error: nerozpoznaný argument pre -fsanitize = option: 'memory'
Makefile: 20: Recept na cieľový msan zlyhal
make: *** [msan] Chyba 2

Nezabudnite však, že na použitie príkazu -msan v príkaze go test je potrebné použiť Clang / LLVM> = 3.8.0.

Máme tu dve možnosti:

  • buď nastavíme Clang v úlohe (pomocou before_script);
  • alebo použijeme obrázok Docker s predvolene nainštalovaným programom Clang.

Prvá možnosť je pekná, ale z toho vyplýva, že toto nastavenie je potrebné vykonať pre každú jednotlivú úlohu. Bude to tak dlho, mali by sme to urobiť raz a navždy. Preto dávame prednosť druhej možnosti, čo je dobrý spôsob, ako si zahrať s registrom GitLab.

git tag: use-own-docker

Musíme pre kontajner vytvoriť súbor Dockerfile (ako obvykle: ďalšie možnosti nájdete v oficiálnej dokumentácii):

# Základný obrázok: https://hub.docker.com/_/golang/
OD golang: 1.9
MAINTAINER Julien Andrieux 
# Nainštalovať golint
ENV GOPATH / go
ENV PATH $ {GOPATH} / bin: $ PATH
RUN go get -u github.com/golang/lint/golint
# Pridanie kľúča apt pre úložisko LLVM
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | add apt key -
# Pridať úložisko apt LLVM
RUN echo "deb http://apt.llvm.org/stretch/ llvm-toolchain-stretch-5.0 main" | tee -a /etc/apt/sources.list
# Nainštalovať zvuk z úložiska LLVM
RUN apt-get update && apt-get install -y --no-install-recommend \
    clang-5.0 \
    && apt-get clean \
    && rm -rf / var / lib / apt / zoznamy / * / tmp / * / var / tmp / *
# Nastaviť Clang ako predvolený CC
ENV set_clang /etc/profile.d/set-clang-cc.sh
RUN echo "export CC = clang-5.0" | tee -a $ {set_clang} && chmod a + x $ {set_clang}

Kontajner zostavený z tohto súboru Dockerfile bude založený na obrázku golang: 1.9 (kontajner, na ktorý sa odkazuje v súbore .gitlab-ci.yml).

Zatiaľ čo sme pri tom, inštalujeme golint do kontajnera, takže ho máme k dispozícii. Potom nasledujeme oficiálny spôsob inštalácie Clang 5.0 z úložiska LLVM.

Teraz máme Dockerfile na svojom mieste, musíme zostaviť obraz kontajnera a sprístupniť ho pre GitLab:

$ docker login register.gitlab.com
$ docker build -t registry.gitlab.com/pantomath-io/demo-tools.
$ docker push register.gitlab.com/pantomath-io/demo-tools

Prvý príkaz vás spojí s registrom GitLab. Potom vytvoríte obraz kontajnera opísaný v dokovacom súbore. Nakoniec ho vložíte do registra GitLab.

Pozrite sa do registra svojho úložiska, uvidíte obrázok, ktorý je pripravený na použitie. A ak chcete, aby CI používal váš obrázok, stačí aktualizovať súbor .gitlab-ci.yml:

obrázok: golang: 1.9

stáva

image: registry.gitlab.com/pantomath-io/demo-tools:latest

Jeden posledný detail: musíte povedať, aby CI použil správny kompilátor (t. J. Premennú prostredia CC), takže pridáme inicializáciu premennej do súboru .gitlab-ci.yml:

export CC = clang-5.0

Po dokončení úpravy bude ďalšie potvrdenie spustiť plynovod, ktorý teraz funguje:

https://gitlab.com/pantomath-io/demo-tools/pipelines/13497136

odznaky

git tag: init-badges

Foto Jakob Owens on Unsplash

Teraz sú tieto nástroje na svojom mieste, každý záväzok spustí testovaciu sadu a pravdepodobne to chcete ukázať, a to je legitímne :) Najlepším spôsobom, ako to urobiť, je použiť odznaky a najlepším miestom je súbor README.

Upravte ho a pridajte 4 nasledujúce odznaky:

  • Stav zostavenia: stav posledného potrubia v hlavnej vetve:
[! [Build Status] (https://gitlab.com/pantomath-io/demo-tools/badges/master/build.svg)] (https://gitlab.com/pantomath-io/demo-tools/commits / master)
  • Správa o pokrytí: percento kódu, na ktorý sa vzťahujú testy
[! [Report of Coverage] (https://gitlab.com/pantomath-io/demo-tools/badges/master/coverage.svg)] (https://gitlab.com/pantomath-io/demo-tools/commits / master)
  • Karta prehľadu Go:
[! [Go Report Card] (https://goreportcard.com/badge/gitlab.com/pantomath-io/demo-tools)] (https://goreportcard.com/report/gitlab.com/pantomath-io/ demo-tools)
  • licencie:
[! [License MIT] (https://img.shields.io/badge/License-MIT-brightgreen.svg)] (https://img.shields.io/badge/License-MIT-brightgreen.svg)

Správa o pokrytí vyžaduje osobitnú konfiguráciu. Musíte povedať spoločnosti GitLab, ako získať tieto informácie, berúc do úvahy, že v KI je úloha, ktorá ich zobrazuje pri spustení.
Existuje konfigurácia, ktorá poskytuje GitLabu regexp, ktorý sa používa vo výstupe akejkoľvek úlohy. Ak sa regexp zhoduje, GitLab považuje zhodu za výsledok pokrytia kódom.

Takže choďte do Nastavenia> CI / CD vo vašom úložisku, prejdite nadol na nastavenie Testovanie analýzy pokrytia v časti Všeobecné nastavenia potrubí a použite nasledujúci regexp:

celkom: \ s + \ (príkazy \) \ s + (\ d + \ d + \.%)

Všetci ste pripravený! Zamierte na prehľad svojho archívu a pozrite sa na svoj README:

záver

Čo bude ďalej? Pravdepodobne viac testov vo vašom KI. Môžete sa tiež pozrieť na CD (Continuous Deployment) na automatizáciu rozmiestnenia vašich zostav. Dokumentáciu je možné vykonať pomocou GoDoc. Upozorňujeme, že pomocou kódu code_coverage_report vygenerujete prehľad o pokrytí, ale v CI ho nepoužívate. Úlohu môžete skopírovať do súboru HTML na webový server pomocou scp (pozrite si túto dokumentáciu o tom, ako používať kľúče SSH).

Ďakujeme Charlesovi Francoiseovi, ktorý spoluautorom tohto príspevku a https://gitlab.com/pantomath-io/demo-tools.

V súčasnosti pracujeme na Pantomathe. Pantomath je moderné riešenie s otvoreným zdrojovým kódom, skonštruované pre výkon, ktoré premosťuje medzery na všetkých úrovniach vašej spoločnosti. Blaho vašej infraštruktúry je záležitosťou každého. Držte krok s projektom