Napriek tomu, že každý veľmi dobre vie, že testovanie vášho softvéru je dôležité a potrebné a mnohí to už dávno robia automaticky, v rozľahlosti Habr neexistoval jediný recept na nastavenie kombinácie takýchto obľúbených produktov v r. tento výklenok ako (náš obľúbený) GitLab a JUnit . Vyplňte túto medzeru!
Úvodná
Najprv mi dovoľte uviesť kontext:
Keďže všetky naše aplikácie bežia na Kubernetes, zvážime spustenie testov na príslušnej infraštruktúre.
Na montáž a nasadenie používame werf (z hľadiska komponentov infraštruktúry to automaticky znamená aj účasť Helm).
Nebudem zachádzať do detailov samotnej tvorby testov: v našom prípade si klient píše testy sám a my zabezpečujeme len ich spustenie (a prítomnosť zodpovedajúceho reportu v žiadosti o zlúčenie).
Ako bude vyzerať všeobecná postupnosť akcií?
Budovanie aplikácie – popis tejto fázy vynecháme.
Nasaďte aplikáciu do samostatného menného priestoru klastra Kubernetes a začnite testovať.
Hľadanie artefaktov a analýza správ JUnit pomocou GitLab.
Odstránenie predtým vytvoreného priestoru názvov.
Teraz - k implementácii!
nastavenie
GitLab CI
Začnime fragmentom .gitlab-ci.yaml, ktorá popisuje nasadenie aplikácie a spustenie testov. Výpis sa ukázal byť dosť objemný, takže bol dôkladne doplnený komentármi:
variables:
# объявляем версию werf, которую собираемся использовать
WERF_VERSION: "1.0 beta"
.base_deploy: &base_deploy
script:
# создаем namespace в K8s, если его нет
- kubectl --context="${WERF_KUBE_CONTEXT}" get ns ${CI_ENVIRONMENT_SLUG} || kubectl create ns ${CI_ENVIRONMENT_SLUG}
# загружаем werf и деплоим — подробнее об этом см. в документации
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#deploy-stage)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf deploy --stages-storage :local
--namespace ${CI_ENVIRONMENT_SLUG}
--set "global.commit_ref_slug=${CI_COMMIT_REF_SLUG:-''}"
# передаем переменную `run_tests`
# она будет использоваться в рендере Helm-релиза
--set "global.run_tests=${RUN_TESTS:-no}"
--set "global.env=${CI_ENVIRONMENT_SLUG}"
# изменяем timeout (бывают долгие тесты) и передаем его в релиз
--set "global.ci_timeout=${CI_TIMEOUT:-900}"
--timeout ${CI_TIMEOUT:-900}
dependencies:
- Build
.test-base: &test-base
extends: .base_deploy
before_script:
# создаем директорию для будущего отчета, исходя из $CI_COMMIT_REF_SLUG
- mkdir /mnt/tests/${CI_COMMIT_REF_SLUG} || true
# вынужденный костыль, т.к. GitLab хочет получить артефакты в своем build-dir’е
- mkdir ./tests || true
- ln -s /mnt/tests/${CI_COMMIT_REF_SLUG} ./tests/${CI_COMMIT_REF_SLUG}
after_script:
# после окончания тестов удаляем релиз вместе с Job’ом
# (и, возможно, его инфраструктурой)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf dismiss --namespace ${CI_ENVIRONMENT_SLUG} --with-namespace
# мы разрешаем падения, но вы можете сделать иначе
allow_failure: true
variables:
RUN_TESTS: 'yes'
# задаем контекст в werf
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#infrastructure)
WERF_KUBE_CONTEXT: 'admin@stage-cluster'
tags:
# используем раннер с тегом `werf-runner`
- werf-runner
artifacts:
# требуется собрать артефакт для того, чтобы его можно было увидеть
# в пайплайне и скачать — например, для более вдумчивого изучения
paths:
- ./tests/${CI_COMMIT_REF_SLUG}/*
# артефакты старше недели будут удалены
expire_in: 7 day
# важно: эти строки отвечают за парсинг отчета GitLab’ом
reports:
junit: ./tests/${CI_COMMIT_REF_SLUG}/report.xml
# для упрощения здесь показаны всего две стадии
# в реальности же у вас их будет больше — как минимум из-за деплоя
stages:
- build
- tests
build:
stage: build
script:
# сборка — снова по документации по werf
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#build-stage)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf build-and-publish --stages-storage :local
tags:
- werf-runner
except:
- schedules
run tests:
<<: *test-base
environment:
# "сама соль" именования namespace’а
# (https://docs.gitlab.com/ce/ci/variables/predefined_variables.html)
name: tests-${CI_COMMIT_REF_SLUG}
stage: tests
except:
- schedules
Kubernetes
Teraz v adresári .helm/templates poďme vytvoriť YAML s Jobom - tests-job.yaml — na spustenie testov a zdrojov Kubernetes, ktoré potrebuje. Pozrite si vysvetlenia po uvedení:
Aké zdroje popísané v tejto konfigurácii? Pri nasadzovaní vytvoríme pre projekt jedinečný menný priestor (toto je uvedené v .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) a rozviňte ho:
ConfigMap s testovacím skriptom;
zamestnania s popisom pod a zadanej smernice command, ktorý práve spúšťa testy;
PV a PVC, ktoré vám umožňujú ukladať testovacie údaje.
Venujte pozornosť úvodnej podmienke s if na začiatku manifestu - podľa toho musia byť zabalené ďalšie YAML súbory Helmovej tabuľky s aplikáciou obrátene navrhnúť tak, aby nedošlo k ich nasadeniu počas testovania. To je:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Ak však testy vyžadujú určitú infraštruktúru (napríklad Redis, RabbitMQ, Mongo, PostgreSQL...) – ich YAML môžu byť nie vypnúť. Nasaďte ich aj do testovacieho prostredia... samozrejme upravte ich podľa vlastného uváženia.
Konečný dotyk
Pretože montáž a nasadenie pomocou werf zatiaľ funguje iba na zostavovacom serveri (s gitlab-runner) a modul s testami je spustený na hlavnom serveri, budete musieť vytvoriť adresár /mnt/tests na pána a dať to bežcovi, napríklad cez NFS. Podrobný príklad s vysvetlivkami nájdete v Dokumentácia K8s.
Nikto nezakazuje vytvoriť zdieľanie NFS priamo na gitlab-runner a potom ho namontovať do modulov.
Poznámka
Možno sa pýtate, prečo všetko komplikovať vytváraním úlohy, ak môžete jednoducho spustiť skript s testami priamo na shell runner? Odpoveď je dosť triviálna...
Niektoré testy vyžadujú prístup k infraštruktúre (MongoDB, RabbitMQ, PostgreSQL atď.), aby sa overilo, či fungujú správne. Testovanie je zjednotené – vďaka tomuto prístupu je jednoduché zahrnúť aj takéto ďalšie entity. Okrem toho dostaneme standard nasadzovací prístup (aj pri použití NFS, dodatočné pripojenie adresárov).
Výsledok
Čo uvidíme, keď aplikujeme pripravenú konfiguráciu?
Žiadosť o zlúčenie zobrazí súhrnnú štatistiku testov spustených v najnovšom kanáli:
Podrobnosti o každej chybe získate kliknutím sem:
NB: Pozorný čitateľ si všimne, že testujeme NodeJS aplikáciu a na screenshotoch - .NET... Nečudujte sa: pri príprave článku sa pri testovaní prvej aplikácie nenašli žiadne chyby, ale sa našli v inom.
Záver
Ako vidíte, nič zložité!
V zásade, ak už máte zberač shellu a funguje, ale nepotrebujete Kubernetes, pripojenie testovania k nemu bude ešte jednoduchšia úloha, ako je tu opísané. A v Dokumentácia GitLab CI nájdete príklady pre Ruby, Go, Gradle, Maven a niektoré ďalšie.