JUnit αž€αŸ’αž“αž»αž„ GitLab CI αž‡αžΆαž˜αž½αž™ Kubernetes

αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž€αžΆαžšαž–αž·αžαžŠαŸ‚αž›αžαžΆαž˜αž“αž»αžŸαŸ’αžŸαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αž“αžΆαžŠαžΉαž„αž™αŸ‰αžΆαž„αž…αŸ’αž”αžΆαžŸαŸ‹αžαžΆαž€αžΆαžšαžŸαžΆαž€αž›αŸ’αž”αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž˜αžΆαž“αžŸαžΆαžšαŸˆαžŸαŸ†αžαžΆαž“αŸ‹ αž“αž·αž„αž…αžΆαŸ†αž”αžΆαž…αŸ‹ αž αžΎαž™αž˜αž“αž»αžŸαŸ’αžŸαž‡αžΆαž…αŸ’αžšαžΎαž“αž”αžΆαž“αž’αŸ’αžœαžΎαžœαžΆαžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž’αžŸαŸ‹αžšαž™αŸˆαž–αŸαž›αž‡αžΆαž™αžΌαžšαž˜αž€αž αžΎαž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸ…αž€αŸ’αž“αž»αž„αž—αžΆαž–αž’αŸ†αž‘αžΌαž›αžΆαž™αž“αŸƒ Habr αž˜αž·αž“αž˜αžΆαž“αžšαžΌαž”αž˜αž“αŸ’αžαžαŸ‚αž˜αž½αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αž„αŸ’αž€αžΎαžαž€αžΆαžšαžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž‚αŸ’αž“αžΆαž“αŸƒαž•αž›αž·αžαž•αž›αž–αŸαž‰αž“αž·αž™αž˜αž”αŸ‚αž”αž“αŸαŸ‡αž“αŸ…αž€αŸ’αž“αž»αž„ αž‘αžΈαž•αŸ’αžŸαžΆαžšαž–αž·αžŸαŸαžŸαž“αŸαŸ‡αž‡αžΆ (αžŸαŸ†αžŽαž–αŸ’αžœαžšαž”αžŸαŸ‹αž™αžΎαž„) GitLab αž“αž·αž„ JUnit αŸ” αžαŸ„αŸ‡αž”αŸ†αž–αŸαž‰αž…αž“αŸ’αž›αŸ„αŸ‡αž“αŸαŸ‡!

JUnit αž€αŸ’αž“αž»αž„ GitLab CI αž‡αžΆαž˜αž½αž™ Kubernetes

αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†

αž‡αžΆαžŠαŸ†αž”αžΌαž„αžαŸ’αž‰αž»αŸ†αžŸαžΌαž˜αž•αŸ’αžαž›αŸ‹αž”αžšαž·αž”αž‘αž˜αž½αž™αž…αŸ†αž“αž½αž“αŸ–

  • αžŠαŸ„αž™αžŸαžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžšαž”αžŸαŸ‹αž™αžΎαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž›αžΎ Kubernetes αž™αžΎαž„αž“αžΉαž„αž–αž·αž…αžΆαžšαžŽαžΆαž€αžΆαžšαžŸαžΆαž€αž›αŸ’αž”αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž›αžΎαž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžŸαž˜αžŸαŸ’αžšαž”αŸ”
  • αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αž‚αž»αŸ† αž“αž·αž„αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ αž™αžΎαž„αž”αŸ’αžšαžΎ werf (αž”αžΎβ€‹αž“αž·αž™αžΆαž™β€‹αž–αžΈβ€‹αž•αŸ’αž“αŸ‚αž€β€‹αž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ αžœαžΆβ€‹αž€αŸβ€‹αž˜αžΆαž“β€‹αž“αŸαž™β€‹αžŸαŸ’αžœαŸαž™β€‹αž”αŸ’αžšαžœαžαŸ’αžαž·β€‹αžŠαŸ‚αžšβ€‹αžαžΆ Helm αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž…αžΌαž›β€‹αžšαž½αž˜)αŸ”
  • αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž˜αž·αž“αž…αžΌαž›αž‘αŸ…αž€αŸ’αž“αž»αž„αž–αŸαžαŸŒαž˜αžΆαž“αž›αž˜αŸ’αž’αž·αžαž“αŸƒαž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αž‘αŸαŸ– αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžšαž”αžŸαŸ‹αž™αžΎαž„ αž’αžαž·αžαž·αž‡αž“αžŸαžšαžŸαŸαžšαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„ αž αžΎαž™αž™αžΎαž„αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž’αžΆαž“αžΆαž€αžΆαžšαž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡ (αž“αž·αž„αžœαžαŸ’αžαž˜αžΆαž“αž“αŸƒαžšαž”αžΆαž™αž€αžΆαžšαžŽαŸαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ†αžŽαžΎαž”αž‰αŸ’αž…αžΌαž›αž‚αŸ’αž“αžΆ)αŸ”


αžαžΎαž›αŸ†αžŠαžΆαž”αŸ‹αž‘αžΌαž‘αŸ…αž“αŸƒαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αž“αžΉαž„αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αž’αŸ’αžœαžΈ?

  1. αž€αžΆαžšαž€αžŸαžΆαž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ - αž™αžΎαž„αž“αžΉαž„αž›αž»αž”αž…αŸ„αž›αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž“αŸƒαžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αž“αŸαŸ‡αŸ”
  2. αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‘αŸ…αž€αž“αŸ’αž›αŸ‚αž„αžˆαŸ’αž˜αŸ„αŸ‡αžŠαžΆαž…αŸ‹αžŠαŸ„αž™αž‘αŸ‚αž€αž“αŸƒαž…αž„αŸ’αž€αŸ„αž˜ Kubernetes αž αžΎαž™αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŸαžΆαž€αž›αŸ’αž”αž„αŸ”
  3. αž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αžœαžαŸ’αžαž»αž”αž»αžšαžΆαžŽ αž“αž·αž„αž€αžΆαžšαž‰αŸ‚αž€αžšαž”αžΆαž™αž€αžΆαžšαžŽαŸ JUnit αž‡αžΆαž˜αž½αž™ GitLab αŸ”
  4. αž€αžΆαžšαž›αž»αž”αžˆαŸ’αž˜αŸ„αŸ‡αžŠαŸ‚αž›αž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž–αžΈαž˜αž»αž“αŸ”

αž₯αž‘αžΌαžœαž“αŸαŸ‡ - αžŠαžΎαž˜αŸ’αž”αžΈαž’αž“αž»αžœαžαŸ’αž!

αž€αžΆαžšαž›αŸƒαžαž˜αŸ’αžšαžΌαžœ

GitLab αžŸαŸŠαžΈαž’αžΆαž™

αž…αžΌαžšαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž”αŸ†αžŽαŸ‚αž€αž˜αž½αž™αŸ” .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 }}

αž’αž“αž’αžΆαž“αž”αŸ’αžšαž—αŸαž‘αžŽαžΆ αž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž“αŸαŸ‡? αž“αŸ…αž–αŸαž›αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ αž™αžΎαž„αž”αž„αŸ’αž€αžΎαžαž›αŸ†αž αžˆαŸ’αž˜αŸ„αŸ‡αžαŸ‚αž˜αž½αž™αž‚αžαŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αž˜αŸ’αžšαŸ„αž„ (αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αž„αŸ’αž’αž»αž›αž”αž„αŸ’αž αžΆαž‰αž“αŸ…αž€αŸ’αž“αž»αž„ .gitlab-ci.yaml - tests-${CI_COMMIT_REF_SLUG}) αž αžΎαž™αžšαž˜αŸ€αž›αžœαžΆαž…αŸαž‰αŸ–

  1. ConfigMap αž‡αžΆαž˜αž½αž™αžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŸαžΆαž€αž›αŸ’αž”αž„;
  2. αž€αžΆαžšαž„αžΆαžš αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž’αŸ†αž–αžΈ pod αž“αž·αž„αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αžŠαŸ‚αž›αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹ commandαžŠαŸ‚αž›αž‘αžΎαž”αžαŸ‚αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αž;
  3. PV αž“αž·αž„ PVCαžŠαŸ‚αž›αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŸαžΆαž€αž›αŸ’αž”αž„αŸ”

αž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αž›αžΎαž›αž€αŸ’αžαžαžŽαŸ’αžŒαžŽαŸ‚αž“αžΆαŸ†αž‡αžΆαž˜αž½αž™ if αž“αŸ…αžŠαžΎαž˜αžŠαŸ†αž”αžΌαž„αž“αŸƒαž€αžΆαžšαž”αž„αŸ’αž αžΆαž‰ - αž™αŸ„αž„αž‘αŸ…αžαžΆαž˜αž―αž€αžŸαžΆαžš YAML αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž“αŸƒαž‚αŸ†αž“αžΌαžŸαžαžΆαž„ Helm αž‡αžΆαž˜αž½αž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αžšαžΌαžœαžαŸ‚αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž»αŸ†αž“αŸ…αž€αŸ’αž“αž»αž„ αž”αž‰αŸ’αž…αŸ’αžšαžΆαžŸ αž€αžΆαžšαžšαž…αž“αžΆαžŠαžΎαž˜αŸ’αž”αžΈαž€αž»αŸ†αž±αŸ’αž™αž–αž½αž€αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž€αŸ†αž‘αž»αž„αž–αŸαž›αž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαŸ” αž“αŸ„αŸ‡αž‚αžΊαŸ–

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

αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αž αž‘αžΆαž˜αž‘αžΆαžšαž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž˜αž½αž™αž…αŸ†αž“αž½αž“ (αž§αž‘αžΆαž αžšαžŽαŸ Redis, RabbitMQ, Mongo, PostgreSQL ... ) - YAMLs αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαž’αžΆαž…αž‡αžΆ αž˜αž·αž“αž˜αžΆαž“ αž”αž·αž‘αŸ” αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αž½αž€αžœαžΆαž‘αŸ…αž€αŸ’αž“αž»αž„αž”αžšαž·αž™αžΆαž€αžΆαžŸαžŸαžΆαž€αž›αŸ’αž”αž„αž•αž„αžŠαŸ‚αžš... αž€αžΆαžšαž€αŸ‚αžαž˜αŸ’αžšαžΌαžœαž–αž½αž€αžœαžΆαžαžΆαž˜αžŠαŸ‚αž›αž’αŸ’αž“αž€αžƒαžΎαž‰αžαžΆαžŸαž˜αŸ”

αž€αžΆαžšαž”αŸ‰αŸ‡αž…αž»αž„αž€αŸ’αžšαŸ„αž™

αžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚ αž€αžΆαžšαž•αŸ’αž‚αž»αŸ†αž“αž·αž„αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸ„αž™αž”αŸ’αžšαžΎ werf αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αŸαž›αž“αŸαŸ‡ αžαŸ‚ αž“αŸ…αž›αžΎ build server (αž‡αžΆαž˜αž½αž™ gitlab-runner) αž αžΎαž™ pod with tests αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαžΆαž€αŸ‹αž±αŸ’αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸ…αž›αžΎ master αž’αŸ’αž“αž€αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αž„αŸ’αž€αžΎαž directory /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

αž‚αŸ’αž˜αžΆαž“αž“αžšαžŽαžΆαž˜αŸ’αž“αžΆαž€αŸ‹αž αžΆαž˜αžƒαžΆαžαŸ‹αž€αžΆαžšαž…αŸ‚αž€αžšαŸ†αž›αŸ‚αž€ NFS αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž“αŸ…αž›αžΎ gitlab-runner αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αž‘αžΎαž„αžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„ pods αŸ”

αž€αžΆαžšαž€αžαŸ‹αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹

αž’αŸ’αž“αž€αž”αŸ’αžšαž αŸ‚αž›αž‡αžΆαž€αŸ†αž–αž»αž„αžŸαž½αžšαžαžΆαž αŸαžαž»αž’αŸ’αžœαžΈαž”αžΆαž“αž‡αžΆαž’αŸ’αžœαžΎαž±αŸ’αž™αž’αŸ’αžœαžΈαŸ—αž˜αžΆαž“αž—αžΆαž–αžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰αžŠαŸ„αž™αž”αž„αŸ’αž€αžΎαž Job αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž’αžΆαž…αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ’αž‚αŸ’αžšαžΈαž”αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž“αŸ…αž›αžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαžαŸ‹αžŸαŸ‚αž›? αž…αž˜αŸ’αž›αžΎαž™β€‹αž‚αžΊβ€‹αž‡αžΆβ€‹αžšαžΏαž„β€‹αžαžΌαž…αžαžΆαž…...

αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαž˜αž½αž™αž…αŸ†αž“αž½αž“αžαž˜αŸ’αžšαžΌαžœαž±αŸ’αž™αž˜αžΆαž“αž€αžΆαžšαž…αžΌαž›αž‘αŸ…αž€αžΆαž“αŸ‹αž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ (MongoDB, RabbitMQ, PostgreSQL αŸ”αž›αŸ”) αžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αžαžΆαž–αž½αž€αžœαžΆαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž”αžΆαž“αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαŸ” αž™αžΎαž„αž’αŸ’αžœαžΎαž±αŸ’αž™αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαž”αž„αŸ’αžšαž½αž”αž”αž„αŸ’αžšαž½αž˜ - αž‡αžΆαž˜αž½αž™αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαž“αŸαŸ‡ αžœαžΆαž„αžΆαž™αžŸαŸ’αžšαž½αž›αžŠαžΆαž€αŸ‹αž”αž‰αŸ’αž…αžΌαž›αž’αž„αŸ’αž‚αž—αžΆαž–αž”αž“αŸ’αžαŸ‚αž˜αž”αŸ‚αž”αž“αŸαŸ‡αŸ” αž”αž“αŸ’αžαŸ‚αž˜αž–αžΈαž›αžΎαž“αŸαŸ‡αž™αžΎαž„αž‘αž‘αž½αž›αž”αžΆαž“ αžŸαŸ’αžαž„αŸ‹αžŠαžΆαžš αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ (αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž”αŸ’αžšαžΎ NFS αž€αžΆαžšαž—αŸ’αž‡αžΆαž”αŸ‹αž”αž“αŸ’αžαŸ‚αž˜αž“αŸƒαžαž) αŸ”

αž›αž‘αŸ’αž’αž•αž›

αžαžΎβ€‹αž™αžΎαž„β€‹αž“αžΉαž„β€‹αžƒαžΎαž‰β€‹αž’αŸ’αžœαžΈβ€‹αž–αŸαž›β€‹αž™αžΎαž„β€‹αž’αž“αž»αžœαžαŸ’αžβ€‹αž€αžΆαžšβ€‹αž€αŸ†αžŽαžαŸ‹β€‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’β€‹αžŠαŸ‚αž›β€‹αž”αžΆαž“β€‹αžšαŸ€αž”αž…αŸ†?

αžŸαŸ†αžŽαžΎαž”αž‰αŸ’αž…αžΌαž›αž‚αŸ’αž“αžΆαž“αžΉαž„αž”αž„αŸ’αž αžΆαž‰αžŸαŸ’αžαž·αžαž·αžŸαž„αŸ’αžαŸαž”αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸ…αž€αŸ’αž“αž»αž„αž”αŸ†αž–αž„αŸ‹αž…αž»αž„αž€αŸ’αžšαŸ„αž™αž”αŸ†αž•αž»αžαžšαž”αžŸαŸ‹αžœαžΆαŸ–

JUnit αž€αŸ’αž“αž»αž„ GitLab CI αž‡αžΆαž˜αž½αž™ Kubernetes

αž€αŸ†αž αž»αžŸαž“αžΈαž˜αž½αž™αŸ—αž’αžΆαž…αž…αž»αž…αž“αŸ…αž‘αžΈαž“αŸαŸ‡αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αž›αž˜αŸ’αž’αž·αžαŸ–

JUnit αž€αŸ’αž“αž»αž„ GitLab CI αž‡αžΆαž˜αž½αž™ Kubernetes

NBαŸ– αž’αŸ’αž“αž€αž’αžΆαž“αžŠαŸ‚αž›αž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αž“αžΉαž„αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αžƒαžΎαž‰αžαžΆαž™αžΎαž„αž€αŸ†αž–αž»αž„αžŸαžΆαž€αž›αŸ’αž”αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ NodeJS αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„αžšαžΌαž”αžαžαž’αŸαž€αŸ’αžšαž„αŸ‹ - .NET... αž€αž»αŸ†αž—αŸ’αž‰αžΆαž€αŸ‹αž•αŸ’αž’αžΎαž›αŸ– αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž‡αžΆαž•αŸ’αž“αŸ‚αž€αž˜αž½αž™αž“αŸƒαž€αžΆαžšαžšαŸ€αž”αž…αŸ†αž’αžαŸ’αžαž”αž‘ αž˜αž·αž“αž˜αžΆαž“αž€αŸ†αž αž»αžŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αžƒαžΎαž‰αž€αŸ’αž“αž»αž„αž€αžΆαžšαžŸαžΆαž€αž›αŸ’αž”αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ†αž”αžΌαž„αž‘αžΎαž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž–αž½αž€αž‚αŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαžšαž€αžƒαžΎαž‰αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αž½αž™αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαŸ”

αžŸαŸαž…αž€αŸ’αžαžΈαžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“

αžŠαžΌαž…αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžƒαžΎαž‰αž‚αŸ’αž˜αžΆαž“αž’αŸ’αžœαžΈαžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰αž‘αŸ!

αž‡αžΆαž‚αŸ„αž›αž€αžΆαžšαžŽαŸ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αžΆαž“αž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαž˜αžΌαž›αžŸαŸ‚αž›αžšαž½αž…αž αžΎαž™ αž αžΎαž™αžœαžΆαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž’αŸ’αž“αž€αž˜αž·αž“αžαŸ’αžšαžΌαžœαž€αžΆαžš Kubernetes αž‘αŸ αž€αžΆαžšαž—αŸ’αž‡αžΆαž”αŸ‹αž€αžΆαžšαžŸαžΆαž€αž›αŸ’αž”αž„αž‡αžΆαž˜αž½αž™αžœαžΆαž“αžΉαž„αž‡αžΆαž€αž·αž…αŸ’αž…αž€αžΆαžšαžŸαžΆαž˜αž‰αŸ’αž‰αž‡αžΆαž„αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž“αŸ…αž‘αžΈαž“αŸαŸ‡αŸ” αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„ αž―αž€αžŸαžΆαžš GitLab CI αž’αŸ’αž“αž€αž“αžΉαž„αžƒαžΎαž‰αž§αž‘αžΆαž αžšαžŽαŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Ruby, Go, Gradle, Maven αž“αž·αž„αž˜αž½αž™αž…αŸ†αž“αž½αž“αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαŸ”

PS

αžŸαžΌαž˜αž’αžΆαž“αž•αž„αžŠαŸ‚αžšαž“αŸ…αž›αžΎαž”αŸ’αž›αž€αŸ‹αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ–

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹