{"id":292604,"date":"2019-07-26T09:06:36","date_gmt":"2019-07-26T09:06:36","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=292604"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=292604","title":{"rendered":"JUnit \u0432 GitLab CI \u0441 Kubernetes"},"content":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432\u0441\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0444\u0442 \u0432\u0430\u0436\u043d\u043e \u0438 \u043d\u0443\u0436\u043d\u043e, \u0430 \u043c\u043d\u043e\u0433\u0438\u0435 \u0434\u0430\u0432\u043d\u043e \u0434\u0435\u043b\u0430\u044e\u0442 \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430\u0445 \u0425\u0430\u0431\u0440\u0430 \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0435\u0446\u0435\u043f\u0442\u0430 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0441\u0432\u044f\u0437\u043a\u0438 \u0442\u0430\u043a\u0438\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432 \u044d\u0442\u043e\u0439 \u043d\u0438\u0448\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432, \u043a\u0430\u043a (\u043b\u044e\u0431\u0438\u043c\u044b\u0439 \u043d\u0430\u043c\u0438) GitLab \u0438 JUnit. \u0412\u043e\u0441\u043f\u043e\u043b\u043d\u0438\u043c \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0431\u0435\u043b!<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/pc\/q_\/3i\/pcq_3iq519cc6s_xqbeivsqyza4.png\"><\/p>\n<h2>\u0412\u0432\u043e\u0434\u043d\u044b\u0435<\/h2>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0443 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442:<\/p>\n<ul>\n<li> \u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 Kubernetes, \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435.<\/li>\n<li> \u0414\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/flant\/werf\">werf<\/a> (\u0432 \u0441\u043c\u044b\u0441\u043b\u0435 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d Helm).<\/li>\n<li> \u0412 \u0434\u0435\u0442\u0430\u043b\u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0443: \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u0438\u0448\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0441\u0430\u043c, \u0430 \u043c\u044b \u043b\u0438\u0448\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0438\u0445 \u0437\u0430\u043f\u0443\u0441\u043a (\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u043e\u0442\u0447\u0435\u0442\u0430 \u0432 merge request&#8217;\u0435).<\/li>\n<\/ul>\n<p><a name=\"habracut\"><\/a><br \/>  \u041a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043e\u0431\u0449\u0430\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439?<\/p>\n<ol>\n<li> \u0421\u0431\u043e\u0440\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u2014 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u043c\u044b \u043e\u043f\u0443\u0441\u0442\u0438\u043c.<\/li>\n<li> \u0414\u0435\u043f\u043b\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 namespace \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 Kubernetes \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/li>\n<li> \u041f\u043e\u0438\u0441\u043a \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433 JUnit-\u043e\u0442\u0447\u0435\u0442\u0430 GitLab\u2019\u043e\u043c.<\/li>\n<li> \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u043d\u0435\u0435 namespace\u2019\u0430.<\/li>\n<\/ol>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u2014 \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438!<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430<\/h2>\n<p>  <\/p>\n<h3>GitLab CI<\/h3>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430 <code>.gitlab-ci.yaml<\/code>, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0434\u0435\u043f\u043b\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432. \u041b\u0438\u0441\u0442\u0438\u043d\u0433 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0431\u044a\u0435\u043c\u043d\u044b\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"bash\">variables: # \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e werf, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c   WERF_VERSION: \"1.0 beta\"  .base_deploy: &amp;base_deploy   script: # \u0441\u043e\u0437\u0434\u0430\u0435\u043c namespace \u0432 K8s, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u043d\u0435\u0442     - kubectl --context=\"${WERF_KUBE_CONTEXT}\" get ns ${CI_ENVIRONMENT_SLUG} || kubectl create ns ${CI_ENVIRONMENT_SLUG} # \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c werf \u0438 \u0434\u0435\u043f\u043b\u043e\u0438\u043c \u2014 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0441\u043c. \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 # (https:\/\/werf.io\/how_to\/gitlab_ci_cd_integration.html#deploy-stage)     - type multiwerf &amp;&amp; source &lt;(multiwerf use ${WERF_VERSION})     - werf version     - type werf &amp;&amp; source &lt;(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:-''}\" # \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e `run_tests` # \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u043d\u0434\u0435\u0440\u0435 Helm-\u0440\u0435\u043b\u0438\u0437\u0430       --set \"global.run_tests=${RUN_TESTS:-no}\"       --set \"global.env=${CI_ENVIRONMENT_SLUG}\" # \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c timeout (\u0431\u044b\u0432\u0430\u044e\u0442 \u0434\u043e\u043b\u0433\u0438\u0435 \u0442\u0435\u0441\u0442\u044b) \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u0440\u0435\u043b\u0438\u0437       --set \"global.ci_timeout=${CI_TIMEOUT:-900}\"      --timeout ${CI_TIMEOUT:-900}   dependencies:     - Build  .test-base: &amp;test-base   extends: .base_deploy   before_script: # \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0434\u043b\u044f \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u043e\u0442\u0447\u0435\u0442\u0430, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 $CI_COMMIT_REF_SLUG     - mkdir \/mnt\/tests\/${CI_COMMIT_REF_SLUG} || true # \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0441\u0442\u044b\u043b\u044c, \u0442.\u043a. GitLab \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0432 \u0441\u0432\u043e\u0435\u043c build-dir\u2019\u0435     - mkdir .\/tests || true     - ln -s \/mnt\/tests\/${CI_COMMIT_REF_SLUG} .\/tests\/${CI_COMMIT_REF_SLUG}   after_script: # \u043f\u043e\u0441\u043b\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0440\u0435\u043b\u0438\u0437 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 Job\u2019\u043e\u043c # (\u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0435\u0433\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439)     - type multiwerf &amp;&amp; source &lt;(multiwerf use ${WERF_VERSION})     - werf version     - type werf &amp;&amp; source &lt;(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)     - werf dismiss --namespace ${CI_ENVIRONMENT_SLUG} --with-namespace # \u043c\u044b \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u043c \u043f\u0430\u0434\u0435\u043d\u0438\u044f, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u043d\u0430\u0447\u0435   allow_failure: true   variables:     RUN_TESTS: 'yes' # \u0437\u0430\u0434\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432 werf # (https:\/\/werf.io\/how_to\/gitlab_ci_cd_integration.html#infrastructure)     WERF_KUBE_CONTEXT: 'admin@stage-cluster'   tags: # \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0440\u0430\u043d\u043d\u0435\u0440 \u0441 \u0442\u0435\u0433\u043e\u043c `werf-runner`     - werf-runner   artifacts: # \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c # \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0438 \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0432\u0434\u0443\u043c\u0447\u0438\u0432\u043e\u0433\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f     paths:       - .\/tests\/${CI_COMMIT_REF_SLUG}\/* # \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0441\u0442\u0430\u0440\u0448\u0435 \u043d\u0435\u0434\u0435\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u044b     expire_in: 7 day # \u0432\u0430\u0436\u043d\u043e: \u044d\u0442\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u043e\u0442\u0447\u0435\u0442\u0430 GitLab\u2019\u043e\u043c     reports:       junit: .\/tests\/${CI_COMMIT_REF_SLUG}\/report.xml  # \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0437\u0434\u0435\u0441\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0432\u0441\u0435\u0433\u043e \u0434\u0432\u0435 \u0441\u0442\u0430\u0434\u0438\u0438 # \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0436\u0435 \u0443 \u0432\u0430\u0441 \u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u2014 \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0438\u0437-\u0437\u0430 \u0434\u0435\u043f\u043b\u043e\u044f stages:   - build   - tests  build:   stage: build   script: # \u0441\u0431\u043e\u0440\u043a\u0430 \u2014 \u0441\u043d\u043e\u0432\u0430 \u043f\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e werf # (https:\/\/werf.io\/how_to\/gitlab_ci_cd_integration.html#build-stage)     - type multiwerf &amp;&amp; source &lt;(multiwerf use ${WERF_VERSION})     - werf version     - type werf &amp;&amp; source &lt;(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)     - werf build-and-publish --stages-storage :local   tags:     - werf-runner   except:     - schedules  run tests:   &lt;&lt;: *test-base   environment: # \"\u0441\u0430\u043c\u0430 \u0441\u043e\u043b\u044c\" \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f namespace\u2019\u0430 # (https:\/\/docs.gitlab.com\/ce\/ci\/variables\/predefined_variables.html)     name: tests-${CI_COMMIT_REF_SLUG}   stage: tests   except:     - schedules<\/code><\/pre>\n<p>  <\/p>\n<h3>Kubernetes<\/h3>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>.helm\/templates<\/code> \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c YAML \u0441 Job\u2019\u043e\u043c \u2014 <code>tests-job.yaml<\/code> \u2014 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u0435\u043c\u0443 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 Kubernetes. \u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u0441\u043c. \u043f\u043e\u0441\u043b\u0435 \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0430:<\/p>\n<pre><code class=\"plaintext\">{{- 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 }}<\/code><\/pre>\n<p>  <b>\u0427\u0442\u043e \u0437\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u044b<\/b> \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438? \u041f\u0440\u0438 \u0434\u0435\u043f\u043b\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 namespace (\u044d\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0435\u0449\u0435 \u0432 <code>.gitlab-ci.yaml<\/code> \u2014 <code>tests-${CI_COMMIT_REF_SLUG}<\/code>) \u0438 \u0432 \u043d\u0435\u0433\u043e \u0432\u044b\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u043c:<\/p>\n<ol>\n<li> <b>ConfigMap<\/b> \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u043c \u0442\u0435\u0441\u0442\u0430;<\/li>\n<li> <b>Job<\/b> \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c pod\u2019\u0430 \u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u043e\u0439 <code>command<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043a\u0430\u043a \u0440\u0430\u0437 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b;<\/li>\n<li> <b>PV \u0438 PVC<\/b>, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u043e\u0432.<\/li>\n<\/ol>\n<p>  \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0432\u0432\u043e\u0434\u043d\u043e\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0441 <code>if<\/code> \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430 \u2014 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u0440\u0443\u0433\u0438\u0435 YAML-\u0444\u0430\u0439\u043b\u044b Helm-\u0447\u0430\u0440\u0442\u0430 \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043d\u0430\u0434\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 <i>\u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e<\/i> \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u043d\u0435 \u0434\u0435\u043f\u043b\u043e\u0438\u043b\u0438\u0441\u044c \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438. \u0422\u043e \u0435\u0441\u0442\u044c:<\/p>\n<pre><code class=\"plaintext\">{{- if ne .Values.global.run_tests \"yes\" }} --- \u044f \u0434\u0440\u0443\u0433\u043e\u0439 \u044f\u043c\u043b\u0438\u043a {{- end }}<\/code><\/pre>\n<p>  \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0435\u0441\u043b\u0438 \u0442\u0435\u0441\u0442\u044b <b>\u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443<\/b> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Redis, RabbitMQ, Mongo, PostgreSQL\u2026) \u2014 \u0438\u0445 YAML\u2019\u044b \u043c\u043e\u0436\u043d\u043e <i>\u043d\u0435<\/i> \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u044c. \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0438\u0442\u0435 \u0438 \u0438\u0445 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0440\u0435\u0434\u0435\u2026 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0432 \u043f\u043e \u0441\u0432\u043e\u0435\u043c\u0443 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044e.<\/p>\n<h3>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0448\u0442\u0440\u0438\u0445<\/h3>\n<p>  \u0422.\u043a. \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u0434\u0435\u043f\u043b\u043e\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e werf \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <i>\u0442\u043e\u043b\u044c\u043a\u043e<\/i> \u043d\u0430 build-\u0441\u0435\u0440\u0432\u0435\u0440\u0435 (\u0441 gitlab-runner), \u0430 pod \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043c\u0430\u0441\u0442\u0435\u0440\u0435, \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>\/mnt\/tests<\/code> \u043d\u0430 \u043c\u0430\u0441\u0442\u0435\u0440\u0435 \u0438 \u043e\u0442\u0434\u0430\u0442\u044c \u0435\u0435 \u043d\u0430 runner, <b>\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e NFS<\/b>. \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/#persistent-volumes\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 K8s<\/a>.<\/p>\n<p>  \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u0435\u0442:<\/p>\n<pre><code class=\"plaintext\">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<\/code><\/pre>\n<p>  \u041d\u0438\u043a\u0442\u043e \u043d\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442 \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c NFS-\u0448\u0430\u0440\u0443 \u043f\u0440\u044f\u043c\u043e \u043d\u0430 gitlab-runner\u2019\u0435, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u0432 pod\u2019\u044b.<\/p>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/h3>\n<p>  \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u0435, \u0437\u0430\u0447\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c Job&#8217;\u0430, \u0435\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u0440\u044f\u043c\u043e \u043d\u0430 shell-\u0440\u0430\u043d\u043d\u0435\u0440\u0435? \u041e\u0442\u0432\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u0435\u043d\u2026<\/p>\n<p>  \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 (MongoDB, RabbitMQ, PostgreSQL \u0438 \u0442.\u043f.) \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c\u0438. \u041c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u043d\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u2014 \u043f\u0440\u0438 \u0442\u0430\u043a\u043e\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043b\u0435\u0433\u043a\u043e. \u0412\u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043a \u044d\u0442\u043e\u043c\u0443, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <b>\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439<\/b> \u043f\u043e\u0434\u0445\u043e\u0434 \u0432 \u0434\u0435\u043f\u043b\u043e\u0435 (\u043f\u0443\u0441\u0442\u044c \u0434\u0430\u0436\u0435 \u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c NFS, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432).<\/p>\n<h2>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/h2>\n<p>  \u0427\u0442\u043e \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e?<\/p>\n<p>  \u0412 merge request\u2019\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0441\u0432\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043f\u043e \u0442\u0435\u0441\u0442\u0430\u043c, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u043c \u0432 \u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/c5\/2w\/ix\/c52wixmvclqqugnkbxbwe7p6brm.png\"><\/p>\n<p>  \u041d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443 \u0437\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0436\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/3-\/0p\/dp\/3-0pdpuwwpkbkye-dajzbbdpgde.png\"><\/p>\n<p>  <i><b>NB<\/b>: \u0412\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043c\u0435\u0442\u0438\u0442, \u0447\u0442\u043e \u043c\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c NodeJS-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0430 \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430\u0445 \u2014 .NET\u2026 \u041d\u0435 \u0443\u0434\u0438\u0432\u043b\u044f\u0439\u0442\u0435\u0441\u044c: \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0437\u0430\u0442\u043e \u043d\u0430\u0448\u043b\u0438 \u0438\u0445 \u0432 \u0434\u0440\u0443\u0433\u043e\u043c.<\/i><\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e!<\/p>\n<p>  \u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c shell-\u0441\u0431\u043e\u0440\u0449\u0438\u043a \u0438 \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0430 Kubernetes \u0432\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u2014 \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043a \u043d\u0435\u043c\u0443 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0435\u0449\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439, \u0447\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0437\u0434\u0435\u0441\u044c. \u0410 \u0432 <a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/junit_test_reports.html\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 GitLab CI<\/a> \u0432\u044b \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0434\u043b\u044f Ruby, Go, Gradle, Maven \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0440\u0443\u0433\u0438\u0445.<\/p>\n<h2>P.S.<\/h2>\n<p>  \u0427\u0438\u0442\u0430\u0439\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u0432 \u043d\u0430\u0448\u0435\u043c \u0431\u043b\u043e\u0433\u0435:<\/p>\n<ul>\n<li> \u00ab<a href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/345116\/\">\u041b\u0443\u0447\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 CI\/CD \u0441 Kubernetes \u0438 GitLab (\u043e\u0431\u0437\u043e\u0440 \u0438 \u0432\u0438\u0434\u0435\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430)<\/a>\u00bb;<\/li>\n<li> \u00ab<a href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/436910\/\">\u0421\u043e\u0432\u0435\u0442\u044b \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0432 GitLab CI<\/a>\u00bb;<\/li>\n<li> \u00ab<a href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/332712\/\">GitLab CI \u0434\u043b\u044f \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0432 production<\/a>\u00bb.<\/li>\n<\/ul>\n<\/div>\n<p>               <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/460897\/\"> https:\/\/habr.com\/ru\/company\/flant\/blog\/460897\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432\u0441\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0444\u0442 \u0432\u0430\u0436\u043d\u043e \u0438 \u043d\u0443\u0436\u043d\u043e, \u0430 \u043c\u043d\u043e\u0433\u0438\u0435 \u0434\u0430\u0432\u043d\u043e \u0434\u0435\u043b\u0430\u044e\u0442 \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430\u0445 \u0425\u0430\u0431\u0440\u0430 \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0435\u0446\u0435\u043f\u0442\u0430 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0441\u0432\u044f\u0437\u043a\u0438 \u0442\u0430\u043a\u0438\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432 \u044d\u0442\u043e\u0439 \u043d\u0438\u0448\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432, \u043a\u0430\u043a (\u043b\u044e\u0431\u0438\u043c\u044b\u0439 \u043d\u0430\u043c\u0438) GitLab \u0438 JUnit. \u0412\u043e\u0441\u043f\u043e\u043b\u043d\u0438\u043c \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0431\u0435\u043b!<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/pc\/q_\/3i\/pcq_3iq519cc6s_xqbeivsqyza4.png\"><\/p>\n<h2>\u0412\u0432\u043e\u0434\u043d\u044b\u0435<\/h2>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0443 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442:<\/p>\n<ul>\n<li> \u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 Kubernetes, \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435.<\/li>\n<li> \u0414\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/flant\/werf\">werf<\/a> (\u0432 \u0441\u043c\u044b\u0441\u043b\u0435 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d Helm).<\/li>\n<li> \u0412 \u0434\u0435\u0442\u0430\u043b\u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0443: \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u0438\u0448\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0441\u0430\u043c, \u0430 \u043c\u044b \u043b\u0438\u0448\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0438\u0445 \u0437\u0430\u043f\u0443\u0441\u043a (\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u043e\u0442\u0447\u0435\u0442\u0430 \u0432 merge request&#8217;\u0435).<\/li>\n<\/ul>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-292604","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/292604","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=292604"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/292604\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=292604"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=292604"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=292604"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}