Quamquam omnes sciunt probationem programmatum tuorum magni momenti et necessariam esse, et multi iam diu id automatice faciunt, nullum tamen ducem in Habr invenire potuimus ad combinationem productorum tam popularium in hoc genere quam (nobis dilectissimi) GitLab et JUnit constituendam. Hoc hiatum impleamus!

Introductio
Primum, contextum exponam:
- Cum omnes applicationes nostrae in Kubernetes currant, probationes in infrastructura correspondenti currere tractabimus.
- Ad congregationem et dispositionem utimur (Quod ad partes infrastructurae attinet, hoc etiam sponte significat Helm implicatum esse).
- In singula de creatione directa probationum non ingrediar: in nostro casu, ipse cliens probationes scribit, et nos tantum curamus ut fiant (et ut relatio correspondens in petitione fusionis adsit).
Qualis erit ordo actionum generalis?
- Applicationem componendo - huius stadii descriptionem omittemus.
- Applicationem in separatum spatium nominum gregis Kubernetes distribui et probationes exsequere.
- Investigatio artefactorum et interpretatio relationum JUnit per GitLab.
- Spatium nominum antea creatum delendo.
Nunc ad exsecutionem!
tionibus
C. GitLab
Incipiamus a fragmento .gitlab-ci.yaml, describens quomodo applicationem disponas et probationes peragas. Index satis longus est, itaque diligenter commentariis supplementatus est:
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
Nunc in directorio .helm/templates Creamus YAML cum Job — tests-job.yaml — ad probationes peragendas et opes Kubernetes quas requirunt. Vide explicationem post enumerationem:
{{- if eq .Values.global.run_tests "yes" }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: tests-script
data:
tests.sh: |
echo "======================"
echo "${APP_NAME} TESTS"
echo "======================"
cd /app
npm run test:ci
cp report.xml /app/test_results/${CI_COMMIT_REF_SLUG}/
echo ""
echo ""
echo ""
chown -R 999:999 /app/test_results/${CI_COMMIT_REF_SLUG}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Chart.Name }}-test
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-weight": "2"
"werf/watch-logs": "true"
spec:
activeDeadlineSeconds: {{ .Values.global.ci_timeout }}
backoffLimit: 1
template:
metadata:
name: {{ .Chart.Name }}-test
spec:
containers:
- name: test
command: ['bash', '-c', '/app/tests.sh']
{{ tuple "application" . | include "werf_container_image" | indent 8 }}
env:
- name: env
value: {{ .Values.global.env }}
- name: CI_COMMIT_REF_SLUG
value: {{ .Values.global.commit_ref_slug }}
- name: APP_NAME
value: {{ .Chart.Name }}
{{ tuple "application" . | include "werf_container_env" | indent 8 }}
volumeMounts:
- mountPath: /app/test_results/
name: data
- mountPath: /app/tests.sh
name: tests-script
subPath: tests.sh
tolerations:
- key: dedicated
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
restartPolicy: OnFailure
volumes:
- name: data
persistentVolumeClaim:
claimName: {{ .Chart.Name }}-pvc
- name: tests-script
configMap:
name: tests-script
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Chart.Name }}-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
storageClassName: {{ .Chart.Name }}-{{ .Values.global.commit_ref_slug }}
volumeName: {{ .Values.global.commit_ref_slug }}
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: {{ .Values.global.commit_ref_slug }}
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Mi
local:
path: /mnt/tests/
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- kube-master
persistentVolumeReclaimPolicy: Delete
storageClassName: {{ .Chart.Name }}-{{ .Values.global.commit_ref_slug }}
{{- end }}
Quales sunt hae opes? in hac configuratione descripta? Dum disponimus, spatium nominum unicum pro incepto creamus (hoc specificatur in .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) et id evolvimus:
- ConfigMap cum scripto probationis;
- Job cum descriptione pod et mandato specificato
command, quod est quod probationes currit; - PV et PVC, quod tibi permittit ut notitias probationum serves.
Nota bene condicionem introductoriam cum if in initio manifesti — proinde, alia documenta YAML chartae Helm cum applicatione involvi debent. inversum ita designa ut non in probatione explicentur. Hoc est:
{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}
Attamen, si probationes infrastructuram aliquam requirunt (exempli gratia, Redis, RabbitMQ, Mongo, PostgreSQL…) — eorum YAML possunt esse non Ea exstingue. Ea quoque in ambitum probationum colloca... scilicet, ea prout tibi videbitur aptans.
ultima tactus
Quia aedificare et disponere cum werf adhuc operatur. tantum In servo aedificationis (cum gitlab-runner), et cum pod cum probationibus in magistro currit, directorium creare debebis. /mnt/tests in magistro et da cursori, exempli gratia, per NFSExemplum accuratum cum explicationibus inveniri potest in .
Resultatum erit:
user@kube-master:~$ cat /etc/exports | grep tests
/mnt/tests IP_gitlab-builder/32(rw,nohide,insecure,no_subtree_check,sync,all_squash,anonuid=999,anongid=998)
user@gitlab-runner:~$ cat /etc/fstab | grep tests
IP_kube-master:/mnt/tests /mnt/tests nfs4 _netdev,auto 0 0
Nemo te prohibet quominus communicationem NFS directe in gitlab-runner crees et deinde in pods inseras.
illud
Forsitan te roges, cur laborem creandi officium cum simpliciter scriptum cum probationibus directe in cursore testae exsequi possis? Responsum satis simplex est...
Quaedam probationes accessum ad infrastructuram (MongoDB, RabbitMQ, PostgreSQL, etc.) requirunt ut recte operari possint. Probationes unificatas facimus—haec methodus facilem reddit includere tales entitates additionales. Praeterea, accipimus... vexillum Modus disponendi (etiam cum usu NFS et additionali montatione directoriorum).
exitum
Quid videbimus cum configurationem paratam applicabimus?
Petitio coniunctionis statisticas summarias probationum in recentissima serie processarum ostendet:

Singuli errores hic ad singula spectanda premere possunt:

NBLector attentus animadvertet nos applicationem NodeJS probare, dum imagines captae .NET utuntur... Ne mireris: dum hunc articulum parabamus, simpliciter nullos errores in prima applicatione probanda invenimus, sed in altera invenimus.
conclusio,
Ut videre potes, nihil complicatum!
In principio, si iam constructorem testae habes et is operatur, et Kubernetes non requiris, probationes ei addere erit negotium etiam simplicius quam quod hic descriptum est. Et in... Exempla invenies pro Ruby, Go, Gradle, Maven et aliis quibusdam.
PS
Lege etiam in nostro diario:
- «";
- «";
- «".
Source: www.habr.com
