JUnit in GitLab CI apud Kubernetes

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!

JUnit in GitLab CI apud Kubernetes

Introductio

Primum, contextum exponam:

  • Cum omnes applicationes nostrae in Kubernetes currant, probationes in infrastructura correspondenti currere tractabimus.
  • Ad congregationem et dispositionem utimur werf * (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?

  1. Applicationem componendo - huius stadii descriptionem omittemus.
  2. Applicationem in separatum spatium nominum gregis Kubernetes distribui et probationes exsequere.
  3. Investigatio artefactorum et interpretatio relationum JUnit per GitLab.
  4. 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:

  1. ConfigMap cum scripto probationis;
  2. Job cum descriptione pod et mandato specificato command, quod est quod probationes currit;
  3. 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 Documentatio K8s.

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:

JUnit in GitLab CI apud Kubernetes

Singuli errores hic ad singula spectanda premere possunt:

JUnit in GitLab CI apud Kubernetes

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... Documentatio CI GitLab Exempla invenies pro Ruby, Go, Gradle, Maven et aliis quibusdam.

PS

Lege etiam in nostro diario:

Source: www.habr.com

Emptum certos hospites pro locis cum praesidio DDoS, VPS VDS servers 🔥 Eme hospitium interretiale fidum cum praesidio DDoS, servitores VPS VDS | ProHoster