JUnit GitLab CI-s koos Kubernetesega

Kuigi kĂ”ik teavad, et oma tarkvara testimine on oluline, ja paljud teevad seda juba automaatselt, ei leidunud Habras ĂŒhtegi retsepti, mis kĂ€sitleks selliste populaarsete toodete nagu (meie lemmik) GitLab ja JUnit seostamist. TĂ€idame selle tĂŒhimiku!

JUnit GitLab CI-s koos Kubernetesega

Sissejuhatus

Alustuseks mÀÀratleksin konteksti:

  • Kuna kĂ”ik meie rakendused töötavad Kuberneteses, arutame testide kĂ€ivitamist vastavas infrastruktuuris.
  • Kogumise ja juurutamise jaoks kasutame werf (infrastruktuuri komponente silmas pidades tĂ€hendab see ka automaatselt, et on kasutusel Helm).
  • Katsesideme loomise detailidesse sĂŒvenema ei hakka: meie puhul kirjutab kliendi testid ise ning meie tagame vaid nende kĂ€ivitamise (ja vastava aruande olemasolu merge request'is).


Kuidas nĂ€eb vĂ€lja ĂŒldine tegevuste jĂ€rjestus?

  1. Rakenduse kogumine — selle etapi kirjeldamise jĂ€tame kĂ”rvale.
  2. Rakenduse juurutamine eraldi Kubernetes klastrinimesse ja testimise kÀivitamine.
  3. Artefaktide otsimine ja JUnit aruande parsimine GitLabi poolt.
  4. Varasemalt loodud nimede asendamine eemaldamine.

NĂŒĂŒd — rakenduse juurde!

Seadistamine

GitLab CI

Alustame lĂ”igust .gitlab-ci.yaml, mis sisaldab rakenduse juurutamise ja testide kĂ€ivitamise kirjeldust. Loend osutus ĂŒsna mahukaks, seega on see hoolikalt tĂ€iendatud kommentaaridega:

muutujad:
# kuulutame vÀlja werf versiooni, mida plaanime kasutada
  WERF_VERSION: "1.0 beta"

.base_deploy: &base_deploy
  skript:
# loome K8s-i nimelruumi, kui seda pole
    - kubectl --context="${WERF_KUBE_CONTEXT}" get ns ${CI_ENVIRONMENT_SLUG} || kubectl create ns ${CI_ENVIRONMENT_SLUG}
# laeme werfi ja teeme vĂ€ljalaskmise — lĂ€hemalt vt dokumentatsioonis
# (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:-''}"
# edastame muutuja `run_tests`
# seda kasutatakse Helm-vÀljalaske renderdamisel
      --set "global.run_tests=${RUN_TESTS:-no}"
      --set "global.env=${CI_ENVIRONMENT_SLUG}"
# muudame timeouti (kasutada vÔib pikki teste) ja edastame selle vÀljalaskesse
      --set "global.ci_timeout=${CI_TIMEOUT:-900}"
     --timeout ${CI_TIMEOUT:-900}
  sÔltuvused:
    - Ehitus

.test-base: &test-base
  laiendab: .base_deploy
  before_script:
# loome kausta tulevase aruande jaoks, lÀhtudes $CI_COMMIT_REF_SLUG-st
    - mkdir /mnt/tests/${CI_COMMIT_REF_SLUG} || true
# sunnitud lahendus, kuna GitLab soovib, et saaks arhiivid oma build-dir’isse
    - mkdir ./tests || true
    - ln -s /mnt/tests/${CI_COMMIT_REF_SLUG} ./tests/${CI_COMMIT_REF_SLUG}
  after_script:
# pĂ€rast testide lĂ”ppemist eemaldame vĂ€ljalaske koos Job’iga
# (ja vÔib-olla ka selle infrastruktuuriga)
    - 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
# lubame vead, kuid vÔite teha teisiti
  allow_failure: true
  muutujad:
    RUN_TESTS: 'jah'
# mÀÀrame konteksti werf-is
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#infrastructure)
    WERF_KUBE_CONTEXT: 'admin@stage-cluster'
  sildid:
# kasutame jooksjat sildiga `werf-runner`
    - werf-runner
  artefaktid:
# oluline on koguda artefakt, et saaks seda nÀha
# protsessis ja alla laadida — nĂ€iteks hoolikalt uurimiseks
    teed:
      - ./tests/${CI_COMMIT_REF_SLUG}/*
# nÀdala vanused artefaktid eemaldatakse
    expire_in: 7 pÀeva
# oluline: need read vastutavad GitLab-i aruande parsimise eest
    aruanded:
      junit: ./tests/${CI_COMMIT_REF_SLUG}/report.xml

# lihtsustamiseks on siin nÀidatud vaid kaks etappi
# tegelikult on neid rohkem — vĂ€hemalt vĂ€ljalaskmise tĂ”ttu
etapid:
  - ehitus
  - testid

ehitus:
  etapp: ehitus
  skript:
# kokkupanek — jĂ€lle werfi dokumentatsiooni jĂ€rgi
# (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
  sildid:
    - werf-runner
  vÀlja arvatud:
    - ajakavad

testide kÀitamine:
  <<: *test-base
  keskkond:
# "nime" nimete ruumi nimed
# (https://docs.gitlab.com/ce/ci/variables/predefined_variables.html)
    nimi: tests-${CI_COMMIT_REF_SLUG}
  etapp: testid
  vÀlja arvatud:
    - ajakavad

Kubernetes

NĂŒĂŒd kataloogis .helm/templates loome YAML koos Job'iga — tests-job.yaml — testide kĂ€ivitamiseks ja vajalike Kubernetes'i ressurssidega. TĂ€iendavad selgitused on loendi pĂ€rast:

{{- if eq .Values.global.run_tests "yes" }}
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: tests-script
data:
  tests.sh: |
    echo "======================"
    echo "${APP_NAME} TESTID"
    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 }}

Millised ressursid on selle konfiguratsiooni all kirjeldatud? Rakenduse juurutamisel loome projekti jaoks ainulaadse nimiruumi (see on nĂ€idatud ka .gitlab-ci.yaml — tests-${CI_COMMIT_REF_SLUG}) ja siia paigaldame:

  1. ConfigMap testi skripti;
  2. Töö pod'i kirjelduse ja mÀÀratud kÀsu command, mis kÀivitab testid;
  3. PV ja PVC, mis vÔimaldavad testide andmete salvestamist.

Pange tĂ€hele sissejuhatav tingimus if maniifesti alguses — vastavalt tuleb teised Helm-chart YAML-failid rakenduse kohta ĂŒmbritseda tagurpidi struktuuriga, et neid ei juurutataks testimise ajal. See tĂ€hendab:

{{- if ne .Values.global.run_tests "yes" }}
---
teine yaml fail
{{- end }}

Siiski, kui testid nĂ”uavad teatud infrastruktuuri (nĂ€iteks Redis, RabbitMQ, Mongo, PostgreSQL
) — nende YAML-id saab ei vĂ€lja lĂŒlitada. Juurutage need testkeskkonnas
 muidugi, kohandades vastavalt oma soovidele.

Viimane puudutus

Kuna build ja juurutamine werfi abil toimib seni ainult build-serveris (gitlab-runneriga), ja testa pod kÀivitatakse meistris, tuleb luua kataloog /mnt/tests meistris ja anda see runnerile, nÀiteks NFS. NÀidis koos selgitustega on saadaval K8s dokumendis.

Tulemuseks saab olema:

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

Keegi ei keela NFS-share tegemist otse gitlab-runner'is, mille jÀrel saab selle pod'idesse monteerida.

MĂ€rkus

VĂ”ib-olla kĂŒsite, miks ĂŒldse seda kĂ”ike keeruliseks ajada Job'i loomisega, kui saab lihtsalt kĂ€ivitada skripti testidega otse shell-runner'is? Vastus on piisavalt triviaalne


MĂ”ned testid nĂ”uavad infrastruktuuri (MongoDB, RabbitMQ, PostgreSQL jne) poole pöördumist nende Ă”ige toimimise kontrollimiseks. Me teeme testimise ĂŒhtseks — selle lĂ€henemisega on selliste lisade kaasamine lihtne. Lisaks saame tava lĂ€henemise juurutamisel (isegi NFS-i kasutamise ja kataloogide tĂ€iendava monteerimisega).

Tulemus

Mida me nÀeme, kui rakendame ettevalmistatud konfiguratsiooni?

Merge request'is kuvatakse kokkuvÔtlik statistika testide kohta, mida kÀidi lÀbi tema viimasel pipeline'il:

JUnit GitLab CI-s koos Kubernetesega

Iga vea puhul saab siia klĂ”psata, et saada ĂŒksikasju:

JUnit GitLab CI-s koos Kubernetesega

NBEttevaatlik lugeja mĂ€rkab, et testime NodeJS-rakendust, kuid ekraanipiltidel on .NET... Ärge imestage: lihtsalt artikli ettevalmistamise kĂ€igus ei leidnud me ĂŒhtegi viga esimeses rakenduses, kuid leidisime need teises.

KokkuvÔte

Nagu nÀha, pole midagi keerulist!

PĂ”himĂ”tteliselt, kui teil on juba shell-koguja ja see töötab ning Kubernetes pole vajalik — testimise ĂŒhendamine sellega on veelgi lihtsam ĂŒlesanne kui siin kirjeldatud. Ja GitLab CI dokumentatsioonist leiate nĂ€iteid Ruby, Go, Gradle, Maven ja mĂ”nede teiste jaoks.

P.S.

Lugege ka meie blogist:

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster