JUnit в GitLab CI с Kubernetes

НСсмотря Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ всС прСкрасно Π·Π½Π°ΡŽΡ‚, Ρ‡Ρ‚ΠΎ Ρ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ свой софт Π²Π°ΠΆΠ½ΠΎ ΠΈ Π½ΡƒΠΆΠ½ΠΎ, Π° ΠΌΠ½ΠΎΠ³ΠΈΠ΅ Π΄Π°Π²Π½ΠΎ Π΄Π΅Π»Π°ΡŽΡ‚ это автоматичСски, Π½Π° просторах Π₯Π°Π±Ρ€Π° Π½Π΅ нашлось Π½ΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ€Π΅Ρ†Π΅ΠΏΡ‚Π° ΠΏΠΎ настройкС связки Ρ‚Π°ΠΊΠΈΡ… популярных Π² этой нишС ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΎΠ², ΠΊΠ°ΠΊ (Π»ΡŽΠ±ΠΈΠΌΡ‹ΠΉ Π½Π°ΠΌΠΈ) GitLab ΠΈ JUnit. Восполним этот ΠΏΡ€ΠΎΠ±Π΅Π»!

JUnit в GitLab CI с Kubernetes

Π’Π²ΠΎΠ΄Π½Ρ‹Π΅

Для Π½Π°Ρ‡Π°Π»Π° ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Ρƒ контСкст:

  • Π’Π°ΠΊ ΠΊΠ°ΠΊ всС наши прилоТСния Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² Kubernetes, Π±ΡƒΠ΄Π΅Ρ‚ рассмотрСн запуск тСстов Π² ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ инфраструктурС.
  • Для сборки ΠΈ дСплоя ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ werf (Π² смыслС инфраструктурных ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² это Ρ‚Π°ΠΊΠΆΠ΅ автоматичСски ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ задСйствован Helm).
  • Π’ Π΄Π΅Ρ‚Π°Π»ΠΈ нСпосрСдствСнного создания тСстов Π²Π΄Π°Π²Π°Ρ‚ΡŒΡΡ Π½Π΅ Π±ΡƒΠ΄Ρƒ: Π² нашСм случаС ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΈΡˆΠ΅Ρ‚ тСсты сам, Π° ΠΌΡ‹ лишь обСспСчиваСм ΠΈΡ… запуск (ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΎΡ‚Ρ‡Π΅Ρ‚Π° Π² merge request’Π΅).


Как Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ общая ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ дСйствий?

  1. Π‘Π±ΠΎΡ€ΠΊΠ° прилоТСния β€” описаниС этого этапа ΠΌΡ‹ опустим.
  2. Π”Π΅ΠΏΠ»ΠΎΠΉ прилоТСния Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ namespace кластСра Kubernetes ΠΈ запуск тСстирования.
  3. Поиск Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚ΠΎΠ² ΠΈ парсинг JUnit-ΠΎΡ‚Ρ‡Π΅Ρ‚Π° GitLab’ом.
  4. Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ созданного Ρ€Π°Π½Π΅Π΅ namespace’а.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ β€” ΠΊ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ!

Настройка

GitLab CI

НачнСм с Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π° .gitlab-ci.yaml, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰Π΅Π³ΠΎ Π΄Π΅ΠΏΠ»ΠΎΠΉ прилоТСния ΠΈ запуск тСстов. Листинг получился довольно ΠΎΠ±ΡŠΠ΅ΠΌΠ½Ρ‹ΠΌ, поэтому ΠΎΡΠ½ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ коммСнтариями:

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

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ .helm/templates создадим YAML с Job’ом β€” tests-job.yaml β€” для запуска тСстов ΠΈ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΌΠΈ Π΅ΠΌΡƒ рСсурсами Kubernetes. ПояснСния см. послС листинга:

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

Π§Ρ‚ΠΎ Π·Π° рСсурсы описаны Π² этой ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ? ΠŸΡ€ΠΈ Π΄Π΅ΠΏΠ»ΠΎΠ΅ создаСм ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ для ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° namespace (это ΡƒΠΊΠ°Π·Π°Π½ΠΎ Π΅Ρ‰Π΅ Π² .gitlab-ci.yaml β€” tests-${CI_COMMIT_REF_SLUG}) ΠΈ Π² Π½Π΅Π³ΠΎ Π²Ρ‹ΠΊΠ°Ρ‚Ρ‹Π²Π°Π΅ΠΌ:

  1. ConfigMap со скриптом тСста;
  2. Job с описаниСм pod’а ΠΈ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²ΠΎΠΉ command, которая ΠΊΠ°ΠΊ Ρ€Π°Π· ΠΈ запускаСт тСсты;
  3. PV ΠΈ PVC, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ тСстов.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Π²Π²ΠΎΠ΄Π½ΠΎΠ΅ условиС с if Π² Π½Π°Ρ‡Π°Π»Π΅ манифСста β€” соотвСтствСнно, Π΄Ρ€ΡƒΠ³ΠΈΠ΅ YAML-Ρ„Π°ΠΉΠ»Ρ‹ Helm-Ρ‡Π°Ρ€Ρ‚Π° с ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ Π½Π°Π΄ΠΎ ΠΎΠ±Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π² ΠΎΠ±Ρ€Π°Ρ‚Π½ΡƒΡŽ ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½ΠΈ Π½Π΅ дСплоились ΠΏΡ€ΠΈ тСстировании. Π’ΠΎ Π΅ΡΡ‚ΡŒ:

{{- if ne .Values.global.run_tests "yes" }}
---
я Π΄Ρ€ΡƒΠ³ΠΎΠΉ ямлик
{{- end }}

Π’ΠΏΡ€ΠΎΡ‡Π΅ΠΌ, Ссли тСсты Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ инфраструктуру (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Redis, RabbitMQ, Mongo, PostgreSQL…) β€” ΠΈΡ… YAML’ы ΠΌΠΎΠΆΠ½ΠΎ Π½Π΅ Π²Ρ‹ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ. Π Π°Π·Π²Π΅Ρ€Π½ΠΈΡ‚Π΅ ΠΈ ΠΈΡ… Π² тСстовой срСдС… ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ ΠΆΠ΅, ΠΏΠΎΠ΄ΠΏΡ€Π°Π²ΠΈΠ² ΠΏΠΎ своСму ΡƒΡΠΌΠΎΡ‚Ρ€Π΅Π½ΠΈΡŽ.

Π€ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΡˆΡ‚Ρ€ΠΈΡ…

Π’.ΠΊ. сборка ΠΈ Π΄Π΅ΠΏΠ»ΠΎΠΉ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ werf ΠΏΠΎΠΊΠ° Ρ‡Ρ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° build-сСрвСрС (с gitlab-runner), Π° pod с тСстами запускаСтся Π½Π° мастСрС, потрСбуСтся ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ /mnt/tests Π½Π° мастСрС ΠΈ ΠΎΡ‚Π΄Π°Ρ‚ΡŒ Π΅Π΅ Π½Π° runner, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΠΎ NFS. Π Π°Π·Π²Π΅Ρ€Π½ΡƒΡ‚Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ с пояснСниями ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ K8s.

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ станСт:

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

Никто Π½Π΅ Π·Π°ΠΏΡ€Π΅Ρ‰Π°Π΅Ρ‚ ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ NFS-ΡˆΠ°Ρ€Ρƒ прямо Π½Π° gitlab-runner’С, послС Ρ‡Π΅Π³ΠΎ ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π΅Ρ‘ Π² pod’ы.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π²Ρ‹ спроситС, Π·Π°Ρ‡Π΅ΠΌ Π²ΠΎΠΎΠ±Ρ‰Π΅ всС ΡƒΡΠ»ΠΎΠΆΠ½ΡΡ‚ΡŒ созданиСм Job’Π°, Ссли ΠΌΠΎΠΆΠ½ΠΎ просто Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ скрипт с тСстами прямо Π½Π° shell-Ρ€Π°Π½Π½Π΅Ρ€Π΅? ΠžΡ‚Π²Π΅Ρ‚ достаточно тривиалСн…

НСкоторыС тСсты Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ обращСния ΠΊ инфраструктурС (MongoDB, RabbitMQ, PostgreSQL ΠΈ Ρ‚.ΠΏ.) для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ коррСктности Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π½ΠΈΠΌΠΈ. ΠœΡ‹ Π΄Π΅Π»Π°Π΅ΠΌ тСстированиС ΡƒΠ½ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ β€” ΠΏΡ€ΠΈ Ρ‚Π°ΠΊΠΎΠΌ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π΅ Π²ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Π΅ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ сущности становится Π»Π΅Π³ΠΊΠΎ. Π’Π΄ΠΎΠ±Π°Π²ΠΎΠΊ ΠΊ этому, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ стандартный ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Π² Π΄Π΅ΠΏΠ»ΠΎΠ΅ (ΠΏΡƒΡΡ‚ΡŒ Π΄Π°ΠΆΠ΅ ΠΈ с использованиСм NFS, Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ²).

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚

Π§Ρ‚ΠΎ ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²Π»Π΅Π½Π½ΡƒΡŽ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ?

Π’ merge request’С Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Π½Π° сводная статистика ΠΏΠΎ тСстам, Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹ΠΌ Π² Π΅Π³ΠΎ послСднСм ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π΅:

JUnit в GitLab CI с Kubernetes

На ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ΠΎΡˆΠΈΠ±ΠΊΡƒ здСсь ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΆΠ°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ подробности:

JUnit в GitLab CI с Kubernetes

NB: Π’Π½ΠΈΠΌΠ°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΡŒ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ тСстируСм NodeJS-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π° Π½Π° ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚Π°Ρ… β€” .NET… НС ΡƒΠ΄ΠΈΠ²Π»ΡΠΉΡ‚Π΅ΡΡŒ: просто Π² Ρ€Π°ΠΌΠΊΠ°Ρ… ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠΈ ΡΡ‚Π°Ρ‚ΡŒΠΈ Π½Π΅ нашлось ошибок Π² тСстировании ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ прилоТСния, Π·Π°Ρ‚ΠΎ нашли ΠΈΡ… Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Как Π²ΠΈΠ΄Π½ΠΎ, Π½ΠΈΡ‡Π΅Π³ΠΎ слоТного!

Π’ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅, Ссли Ρƒ вас ΡƒΠΆΠ΅ Π΅ΡΡ‚ΡŒ shell-сборщик ΠΈ ΠΎΠ½ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, Π° Kubernetes Π²Π°ΠΌ Π½Π΅ Π½ΡƒΠΆΠ΅Π½ β€” ΠΏΡ€ΠΈΠΊΡ€ΡƒΡ‚ΠΈΡ‚ΡŒ ΠΊ Π½Π΅ΠΌΡƒ тСстированиС Π±ΡƒΠ΄Π΅Ρ‚ Π΅Ρ‰Π΅ Π±ΠΎΠ»Π΅Π΅ простой Π·Π°Π΄Π°Ρ‡Π΅ΠΉ, Ρ‡Π΅ΠΌ описанная здСсь. А Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ GitLab CI Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ для Ruby, Go, Gradle, Maven ΠΈ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π΄Ρ€ΡƒΠ³ΠΈΡ….

P.S.

Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π² нашСм Π±Π»ΠΎΠ³Π΅:

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com