Malgraŭ tio, ke ĉiuj scias perfekte, ke provi vian programaron estas grava kaj necesa, kaj multaj faras ĝin aŭtomate delonge, en la vasteco de Habr ne ekzistis eĉ unu recepto por starigi kombinaĵon de tiaj popularaj produktoj en ĉi tiu niĉo kiel (nia plej ŝatata) GitLab kaj JUnit . Ni plenigu ĉi tiun mankon!
Enkonduka
Unue, lasu min doni iom da kunteksto:
Ĉar ĉiuj niaj aplikaĵoj funkcias per Kubernetes, ni konsideros fari provojn sur la taŭga infrastrukturo.
Por muntado kaj deplojo ni uzas werf (laŭ infrastrukturaj komponantoj, tio ankaŭ aŭtomate signifas, ke Helm estas implikita).
Mi ne eniros la detalojn pri la efektiva kreado de testoj: en nia kazo, la kliento mem skribas la testojn, kaj ni nur certigas ilian lanĉon (kaj la ĉeeston de responda raporto en la kunfanda peto).
Kiel aspektos la ĝenerala sinsekvo de agoj?
Konstruante la aplikaĵon - ni preterlasos la priskribon de ĉi tiu etapo.
Deploji la aplikaĵon al aparta nomspaco de la Kubernetes-areo kaj komencu testi.
Serĉante artefaktojn kaj analizante JUnit-raportojn kun GitLab.
Forigante antaŭe kreitan nomspacon.
Nun - al efektivigo!
alĝustigo
GitLab CI
Ni komencu per fragmento .gitlab-ci.yaml, kiu priskribas deploji la aplikaĵon kaj ruli testojn. La listo montriĝis sufiĉe granda, do ĝi estis plene kompletigita per komentoj:
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
Kubernetoj
Nun en la dosierujo .helm/templates ni kreu YAML kun Job - tests-job.yaml — por ruli testojn kaj la rimedojn de Kubernetes, kiujn ĝi bezonas. Vidu klarigojn post listigo:
Kiaj rimedoj priskribita en ĉi tiu agordo? Dum deplojiĝo, ni kreas unikan nomspacon por la projekto (ĉi tio estas indikita en .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) kaj rulu ĝin:
ConfigMap kun prova skripto;
job kun priskribo de la pod kaj la specifita direktivo command, kiu nur kuras la testojn;
PV kaj PVC, kiuj permesas vin stoki testajn datumojn.
Atentu la enkondukan kondiĉon kun if komence de la manifesto - sekve, aliaj YAML-dosieroj de la Helm-diagramo kun la aplikaĵo devas esti envolvitaj en reverso desegni por ke ili ne estu deplojitaj dum testado. Tio estas:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Tamen, se la provoj postulas iom da infrastrukturo (ekzemple, Redis, RabbitMQ, Mongo, PostgreSQL...) - iliaj YAMLoj povas esti ne Malŝalti. Deploji ilin ankaŭ en testan medion... ĝustigante ilin laŭplaĉe, kompreneble.
fina tuŝo
Ĉar muntado kaj deplojo uzante werf funkcias nuntempe nur sur la konstruservilo (kun gitlab-runner), kaj la pod kun testoj estas lanĉita sur la majstro, vi devos krei dosierujon /mnt/tests sur la mastro kaj donu ĝin al la kuristo, ekzemple, per NFS. Detala ekzemplo kun klarigoj troviĝas en K8s-dokumentado.
Neniu malpermesas fari NFS-dividadon rekte sur gitlab-runner, kaj poste munti ĝin en podoj.
Примечание
Vi eble demandas, kial kompliki ĉion kreante Laborpostenon, se vi povas simple ruli skripton kun testoj rekte sur la ŝelkurilo? La respondo estas sufiĉe bagatela...
Iuj provoj postulas aliron al la infrastrukturo (MongoDB, RabbitMQ, PostgreSQL, ktp.) por kontroli, ke ili funkcias ĝuste. Ni igas testadon unuigita - kun ĉi tiu aliro, fariĝas facile inkluzivi tiajn kromajn entojn. Krom ĉi tio, ni ricevas normo deplojo aliro (eĉ se uzante NFS, kroma muntado de dosierujoj).
rezulto
Kion ni vidos kiam ni aplikas la pretan agordon?
La kunfanda peto montros resumajn statistikojn por testoj rulitaj en sia plej nova dukto:
Ĉiu eraro povas esti klakita ĉi tie por detaloj:
NB: La atentema leganto rimarkos, ke ni testas aplikaĵon de NodeJS, kaj en la ekrankopioj - .NET... Ne miru: nur, ke dum la preparado de la artikolo, oni ne trovis erarojn en la testado de la unua aplikaĵo, sed ili estis trovitaj en alia.
konkludo
Kiel vi povas vidi, nenio komplika!
Principe, se vi jam havas ŝelkolektilon kaj ĝi funkcias, sed vi ne bezonas Kubernetes, alligi testadon al ĝi estos eĉ pli simpla tasko ol priskribita ĉi tie. Kaj en GitLab CI-dokumentado vi trovos ekzemplojn por Ruby, Go, Gradle, Maven kaj iuj aliaj.