JUnit በ GitLab CI ከኩበርኔትስ ጋር

ሶፍትዌርዎን መሞከር አስፈላጊ እና አስፈላጊ መሆኑን ሁሉም ሰው ቢያውቅም፣ እና ብዙዎች ለረጅም ጊዜ በራስ-ሰር ሲያደርጉት ቢቆዩም፣ በዚህ ልዩ ቦታ (እንደ ተወዳጅ) GitLab እና JUnit ያሉ ታዋቂ ምርቶችን ጥምረት ለማዘጋጀት ስለ Habr አንድም መመሪያ ማግኘት አልቻልንም። ይህንን ክፍተት እንሙላ!

JUnit በ GitLab CI ከኩበርኔትስ ጋር

መግቢያ

በመጀመሪያ፣ አውዱን ላስቀምጥ፦

  • ሁሉም አፕሊኬሽኖቻችን በኩበርኔትስ ላይ ስለሚሰሩ፣ በተዛማጅ መሠረተ ልማት ላይ ሙከራዎችን እናካሂዳለን።
  • ለመገጣጠም እና ለማሰማራት እንጠቀማለን werf (በመሠረተ ልማት ክፍሎች ረገድ፣ ይህ ማለት ሄልም ተሳታፊ ነው ማለት ነው)።
  • በቀጥታ ሙከራዎችን ስለመፍጠር ዝርዝር ጉዳዮች አልገባም፤ በእኛ ሁኔታ፣ ደንበኛው ፈተናዎቹን የሚጽፈው እራሳቸው ናቸው፣ እና እኛ የምናረጋግጠው እነሱ መሄዳቸውን ብቻ ነው (እና ተጓዳኝ ሪፖርቱ በውህደት ጥያቄው ውስጥ መኖሩን)።


የአጠቃላይ የድርጊቶች ቅደም ተከተል ምን ይመስላል?

  1. አፕሊኬሽኑን ማሰባሰብ - የዚህን ደረጃ መግለጫ እናስወግዳለን።
  2. መተግበሪያውን ወደተለየ የኩበርኔትስ ክላስተር የስም ቦታ ያሰማሩ እና ሙከራውን ያሂዱ።
  3. በGitLab የተዘጋጁ የJUnit ሪፖርቶችን መተንተን እና ቅርሶችን መፈለግ።
  4. ቀደም ሲል የተፈጠረ የስም ቦታን በመሰረዝ ላይ።

አሁን ወደ ተግባራዊነት እንሂድ!

በደንብ ማድረግ

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

ኩባንያቶች

አሁን በማውጫው ውስጥ .helm/templates ከJob ጋር YAML እንፍጠር - tests-job.yaml — ሙከራዎችን እና የሚያስፈልጋቸውን የኩበርኔትስ ግብዓቶች ለማስኬድ። ከዝርዝሩ በኋላ ያለውን ማብራሪያ ይመልከቱ፡

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

እነዚህ ምን አይነት ሀብቶች ናቸው? በዚህ ውቅር ውስጥ ተገልጿል? ስናሰማራ፣ ለፕሮጀክቱ ልዩ የሆነ የስም ቦታ እንፈጥራለን (ይህ በ ውስጥ ተገልጿል) .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) እና እኛ እንገልጸዋለን፡

  1. ConfigMap ከሙከራ ስክሪፕት ጋር፤
  2. ሥራ ከፖድ መግለጫው እና ከተጠቀሰው መመሪያ ጋር command, ይህም ፈተናዎችን የሚያካሂደው ነው;
  3. ፒቪ እና ፒቪሲየሙከራ ውሂብን እንዲያከማቹ የሚያስችልዎ።

የመግቢያ ሁኔታውን እባክዎ ልብ ይበሉ ከ ጋር if በማኒፌስቱ መጀመሪያ ላይ - በዚህ መሠረት፣ ከመተግበሪያው ጋር የሄልም ገበታ ሌሎች የYAML ፋይሎች መጠቅለል አለባቸው። ተገላቢጦሽ በሙከራ ጊዜ እንዳይተገበሩ ዲዛይን ያድርጉ። ይህም፡

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

ሆኖም ግን፣ ፈተናዎች ካሉ የተወሰነ መሠረተ ልማት ይፈልጋል (ለምሳሌ፣ Redis፣ RabbitMQ፣ Mongo፣ PostgreSQL…) — የYAML ዝርዝራቸው ሊሆን ይችላል አይደለም አጥፋቸው። እንዲሁም ወደ የሙከራ አካባቢው አሰማራቸው... በእርግጥ፣ እንደፈለጉ አስተካክሏቸው።

የመጨረሻ ንክኪ

ምክንያቱም ከዌርፍ ጋር መገንባትና ማሰማራት አሁንም ይሰራል። ብቻ በግንባታ አገልጋይ (ከ gitlab-runner ጋር) ላይ፣ እና ሙከራዎች ያሉት ፖድ በዋናው ላይ ይሰራል፣ ማውጫ መፍጠር ያስፈልግዎታል። /mnt/tests በጌታው ላይ እና ለፈጣሪው ስጡት፣ ለምሳሌ፣ በ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

በ gitlab-runner ላይ የNFS ማጋራትን በቀጥታ ከመፍጠር እና ከዚያም በፖድ ውስጥ ከመጫን ማንም አያግድዎትም።

አመለከተ

ምናልባት፣ በቀጥታ በሼል ሯጭ ላይ ሙከራዎችን የያዘ ስክሪፕት ማስኬድ ሲችሉ ለምን ስራ መፍጠር ይቸገራሉ ብለህ ታስብ ይሆናል? መልሱ በጣም ቀላል ነው…

አንዳንድ ሙከራዎች ተገቢውን አሠራር ለማረጋገጥ የመሠረተ ልማት (MongoDB፣ RabbitMQ፣ PostgreSQL፣ ወዘተ) መዳረሻ ያስፈልጋቸዋል። ሙከራውን አንድ እናደርጋለን - ይህ አካሄድ እንደዚህ ያሉ ተጨማሪ አካላትን ማካተት ቀላል ያደርገዋል። በተጨማሪም፣ እናገኛለን መደበኛ የማሰማራት አቀራረብ (NFS እና ተጨማሪ ማውጫዎችን በመጫንም ቢሆን)።

ውጤት

የተዘጋጀውን ውቅር ስንተገብር ምን እናያለን?

የውህደት ጥያቄው በቅርብ ጊዜ በተሰራው የፈተና መስመር ውስጥ ለሚካሄዱት ሙከራዎች የማጠቃለያ ስታቲስቲክስን ያሳያል፡

JUnit በ GitLab CI ከኩበርኔትስ ጋር

እዚህ ላይ ለዝርዝሮች እያንዳንዱ ስህተት እዚህ ጠቅ ሊደረግ ይችላል፦

JUnit በ GitLab CI ከኩበርኔትስ ጋር

NB፦ ትኩረት የሚስብ አንባቢ የNodeJS መተግበሪያ እየሞከርን መሆኑን ያስተውላል፣ ቅጽበታዊ ገጽ እይታዎቹ .NET እየተጠቀሙ ነው... አትገረሙ፡ ይህንን ጽሑፍ በማዘጋጀት ላይ ሳለ፣ የመጀመሪያውን መተግበሪያ በመሞከር ላይ ምንም አይነት ስህተት አላገኘንም፣ ነገር ግን በሌላኛው ውስጥ አግኝተናቸዋል።

መደምደሚያ

እንደምታየው ምንም ውስብስብ ነገር የለም!

በመርህ ደረጃ፣ የሼል ገንቢ ካለዎት እና እየሰራ ከሆነ እና ኩበርኔትስ የማያስፈልግዎ ከሆነ፣ ሙከራን መጨመር እዚህ ከተገለጸው የበለጠ ቀላል ስራ ይሆናል። የጂትላብ ሲአይ ሰነድ ለሩቢ፣ ጎ፣ ግራድል፣ ማቨን እና ሌሎችም ምሳሌዎችን ያገኛሉ።

PS

በብሎጋችን ላይ ያንብቡ፡-

ምንጭ: hab.com

በDDoS ጥበቃ፣ VPS VDS አገልጋዮች ለጣቢያዎች አስተማማኝ ማስተናገጃ ይግዙ 🔥 አስተማማኝ የድር ጣቢያ ማስተናገጃ በዲዶኤስ ጥበቃ፣ በቪፒኤስ ቪዲኤስ አገልጋዮች ይግዙ | ProHoster