JUnit ni GitLab CI pẹlu Kubernetes

Bi o ti jẹ pe gbogbo eniyan mọ ni pipe daradara pe idanwo sọfitiwia rẹ ṣe pataki ati pataki, ati pe ọpọlọpọ ti n ṣe ni adaṣe fun igba pipẹ, ni titobi Habr ko si ohunelo kan fun iṣeto akojọpọ iru awọn ọja olokiki ni onakan yii bi (ayanfẹ wa) GitLab ati JUnit. Jẹ ki a kun aafo yii!

JUnit ni GitLab CI pẹlu Kubernetes

Ifarahan

Ni akọkọ, jẹ ki n fun diẹ ninu awọn ọrọ-ọrọ:

  • Niwọn igba ti gbogbo awọn ohun elo wa nṣiṣẹ lori Kubernetes, a yoo ronu ṣiṣe awọn idanwo lori awọn amayederun ti o yẹ.
  • Fun apejọ ati imuṣiṣẹ ti a lo werf (ni awọn ofin ti amayederun irinše, yi tun laifọwọyi tumo si wipe Helm lowo).
  • Emi kii yoo lọ sinu awọn alaye ti ẹda gangan ti awọn idanwo: ninu ọran wa, alabara kọ awọn idanwo funrararẹ, ati pe a rii daju ifilọlẹ wọn nikan (ati wiwa ijabọ ti o baamu ni ibeere apapọ).


Kini yoo dabi awọn ilana gbogbogbo ti awọn iṣe?

  1. Ṣiṣe ohun elo naa - a yoo fi apejuwe ti ipele yii silẹ.
  2. Mu ohun elo lọ si aaye orukọ lọtọ ti iṣupọ Kubernetes ki o bẹrẹ idanwo.
  3. Wiwa awọn ohun-ọṣọ ati sisọ awọn ijabọ JUnit pẹlu GitLab.
  4. Nparẹ aaye orukọ ti o ṣẹda tẹlẹ.

Bayi - si imuse!

Ṣe akanṣe

GitLab CI

Jẹ ká bẹrẹ pẹlu kan ajeku .gitlab-ci.yaml, eyi ti o ṣe apejuwe imuṣiṣẹ ohun elo ati ṣiṣe awọn idanwo. Atokọ naa yipada lati jẹ iwọn didun pupọ, nitorinaa o jẹ afikun ni kikun pẹlu awọn asọye:

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

Bayi ni liana .helm/templates jẹ ki a ṣẹda YAML pẹlu Job - tests-job.yaml - lati ṣiṣe awọn idanwo ati awọn orisun Kubernetes ti o nilo. Wo awọn alaye lẹhin atokọ:

{{- 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 }}

Ohun ti Iru oro se apejuwe ninu yi iṣeto ni? Nigbati o ba n gbe lọ, a ṣẹda aaye orukọ alailẹgbẹ fun iṣẹ akanṣe (eyi jẹ itọkasi ni .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) ki o si gbe e jade:

  1. ConfigMap pẹlu iwe afọwọkọ idanwo;
  2. Job pẹlu apejuwe ti awọn podu ati awọn pàtó kan šẹ command, eyi ti o kan gbalaye awọn igbeyewo;
  3. PV ati PVC, eyi ti o gba ọ laaye lati tọju data idanwo.

San ifojusi si awọn iforo ipo pẹlu if ni ibẹrẹ ifihan - ni ibamu, awọn faili YAML miiran ti iwe aworan Helm pẹlu ohun elo gbọdọ wa ni tii sinu yiyipada ṣe apẹrẹ ki wọn ko ba gba ransogun lakoko idanwo. Ti o jẹ:

{{- if ne .Values.global.run_tests "yes" }}
---
я другой ямлик
{{- end }}

Sibẹsibẹ, ti o ba awọn idanwo beere diẹ ninu awọn amayederun (fun apẹẹrẹ, Redis, RabbitMQ, Mongo, PostgreSQL...) - awọn YAML wọn le jẹ kii ṣe paa. Ran wọn lọ si agbegbe idanwo daradara… ṣatunṣe wọn bi o ṣe rii pe o yẹ, dajudaju.

Ifọwọkan ipari

Nitori apejọ ati imuṣiṣẹ nipa lilo awọn iṣẹ werf fun bayi Nikan lori olupin kọ (pẹlu gitlab-runner), ati pe podu pẹlu awọn idanwo ti ṣe ifilọlẹ lori oluwa, iwọ yoo nilo lati ṣẹda itọsọna kan /mnt/tests lori oluwa ki o si fi fun olusare, fun apẹẹrẹ, nipasẹ NFS. Apeere alaye pẹlu awọn alaye ni a le rii ni K8s iwe.

Abajade yoo jẹ:

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

Ko si ẹnikan ti o ṣe idiwọ ṣiṣe pinpin NFS taara lori olusare gitlab, ati lẹhinna gbe e sinu awọn adarọ-ese.

Daakọ

O le beere idi ti idiju ohun gbogbo nipa ṣiṣẹda Job kan ti o ba le jiroro ni ṣiṣe iwe afọwọkọ kan pẹlu awọn idanwo taara lori olusare ikarahun naa? Idahun si jẹ ohun kekere…

Diẹ ninu awọn idanwo nilo iraye si awọn amayederun (MongoDB, RabbitMQ, PostgreSQL, ati bẹbẹ lọ) lati rii daju pe wọn ṣiṣẹ ni deede. A jẹ ki idanwo ni iṣọkan - pẹlu ọna yii, o rọrun lati ṣafikun iru awọn nkan afikun. Ni afikun si eyi, a gba boṣewa ọna imuṣiṣẹ (paapaa ti o ba nlo NFS, iṣagbesori afikun ti awọn ilana).

Esi

Kini a yoo rii nigba ti a ba lo iṣeto ti a pese silẹ?

Ìbéèrè ìdàpọ̀ náà yóò ṣàfihàn àwọn ìṣirò àkópọ̀ fún àwọn ìdánwò tí ń ṣiṣẹ́ nínú òpópónà tuntun rẹ̀:

JUnit ni GitLab CI pẹlu Kubernetes

Aṣiṣe kọọkan le tẹ nibi fun awọn alaye:

JUnit ni GitLab CI pẹlu Kubernetes

NB: Oluka ifarabalẹ yoo ṣe akiyesi pe a n ṣe idanwo ohun elo NodeJS kan, ati ninu awọn sikirinisoti - .NET... Maṣe jẹ yà: o kan pe lakoko ti o ngbaradi nkan naa, ko si awọn aṣiṣe ti a ri ni idanwo ohun elo akọkọ, ṣugbọn wọn won ri ninu miiran.

ipari

Bi o ti le ri, ko si ohun idiju!

Ni opo, ti o ba ti ni olugba ikarahun tẹlẹ ati pe o ṣiṣẹ, ṣugbọn iwọ ko nilo Kubernetes, sisopọ idanwo si rẹ yoo jẹ iṣẹ ti o rọrun paapaa ju ti a ṣalaye lọ. Ati ninu GitLab CI iwe iwọ yoo wa awọn apẹẹrẹ fun Ruby, Go, Gradle, Maven ati diẹ ninu awọn miiran.

PS

Ka tun lori bulọọgi wa:

orisun: www.habr.com

Fi ọrọìwòye kun