{"id":347416,"date":"2023-05-14T08:26:07","date_gmt":"2023-05-14T08:26:07","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=347416"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=347416","title":{"rendered":"<span>\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 helm chart \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 + werf<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<blockquote>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 <a href=\"https:\/\/ru.werf.io\/\" rel=\"noopener noreferrer nofollow\">werf<\/a> \u043e\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 <a href=\"https:\/\/habr.com\/ru\/companies\/flant\/profile\/\" rel=\"noopener noreferrer nofollow\">\u0424\u043b\u0430\u043d\u0442<\/a> \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 CI\/CD \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 K8s.<\/p>\n<\/blockquote>\n<h2>\u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/h2>\n<p>\u0418\u043c\u0435\u0435\u043c \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0432 k8s, \u0433\u0434\u0435 \u043a\u0440\u0443\u0442\u044f\u0442\u0441\u044f \u0438 \u0434\u0435\u043f\u043b\u043e\u044f\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043d\u0430 \u043f\u0445\u043f, \u0433\u043e, js &#8230; \u041f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u043e\u043c\u0438\u043c\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u0434\u0430 \u043d\u0430\u0431\u043e\u0440 \u043a\u0443\u0431\u0435\u0440\u043d\u0435\u0442\u0438\u0441 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 (deployment, configMap, Secret, Job&#8230;)<\/p>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/478\/3c2\/7c9\/4783c27c9da2dc4ce02d8a25fd6a3cc1.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel\" width=\"708\" height=\"1414\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/478\/3c2\/7c9\/4783c27c9da2dc4ce02d8a25fd6a3cc1.png\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel<\/figcaption><\/div>\n<\/figure>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u043a\u0430<\/h2>\n<p>\u0412\u044b\u043a\u0430\u0442 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0431\u043e\u043b\u044c\u044e, \u043f\u043e \u0441\u0443\u0442\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0434\u043b\u044f k8s (\u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442), \u043d\u0435\u0442 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043a\u0443\u0431\u0443\u0440\u043d\u0435\u0442\u0438\u0441\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043c\u043d\u043e\u0433\u043e \u043b\u0438\u0448\u043d\u0438\u0445 \u0437\u043d\u0430\u043d\u0438\u0439 \u043e\u0431 \u0438\u043d\u0444\u0440\u043e\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432, \u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0431\u044b\u0432\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435, \u043a\u0442\u043e \u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0430\u043c, \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0430 \u043a\u0442\u043e \u0442\u043e \u043d\u0435\u0442, \u043f\u043e \u0441\u0443\u0442\u0438 \u0442\u0430\u043a\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0431\u044b\u043b\u0430 \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u0430 \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0434\u0435\u043f\u043b\u043e\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0438 \u0434\u0435\u0432\u043e\u043f\u0441\u043e\u0432.<\/p>\n<h2>\u0416\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/h2>\n<p>\u0418\u043c\u0435\u0442\u044c \u0435\u0434\u0438\u043d\u044b\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 helm \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 (php, go, js &#8230;), \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0432\u0435\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0447\u0430\u0440\u0442\u0430, \u0432 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u043c\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u044b values \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0434\u0435\u043f\u043b\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3c1\/60c\/114\/3c160c11461550953949967bc1822c58.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel\" width=\"692\" height=\"1680\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3c1\/60c\/114\/3c160c11461550953949967bc1822c58.png\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel<\/figcaption><\/div>\n<\/figure>\n<h2>\u0414\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043b\u0438\u0446\u0430<\/h2>\n<p><strong>Gitlab, K8s, werf, docke<\/strong>r (\u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0442\u043e \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u044b \u043a k8s, Gitlab, docker \u0443\u0436\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f)<\/p>\n<h2>\u041f\u043e\u0435\u0445\u0430\u043b\u0438!<\/h2>\n<p><strong>Werf<\/strong><\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c werf \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 Gitlab \u0441\u043b\u0435\u0434\u0443\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 (werf \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u0430 \u0445\u043e\u0441\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044f image) <a href=\"https:\/\/ru.werf.io\/documentation\/v1.2\/index.html?usage=ci&amp;ci=gitlabCiCd&amp;runnerType=hostRunner&amp;os=linux&amp;buildBackend=docker&amp;projectType=simplified&amp;sharedCICD=no&amp;repoType=application\" rel=\"noopener noreferrer nofollow\">https:\/\/ru.werf.io\/documentation\/v1.2\/index.html?usage=ci&amp;ci=gitlabCiCd&amp;runnerType=hostRunner&amp;os=linux&amp;buildBackend=docker&amp;projectType=simplified&amp;sharedCICD=no&amp;repoType=application<\/a><\/p>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c runner \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <a href=\"https:\/\/ru.werf.io\/documentation\/v1.1\/guides\/gitlab_ci_cd_integration.html\" rel=\"noopener noreferrer nofollow\">https:\/\/ru.werf.io\/documentation\/v1.1\/guides\/gitlab_ci_cd_integration.html<\/a><\/p>\n<h2>\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/h2>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 laravel-chart, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/75e\/d6b\/f20\/75ed6bf201f3b5e2d80c414bef424b3b.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\" width=\"698\" height=\"830\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/75e\/d6b\/f20\/75ed6bf201f3b5e2d80c414bef424b3b.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<ol start=\"2\">\n<li>\n<p>.helm\/charts\/laravel-chart\/Chart.yaml<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"yaml\">apiVersion: v2 name: laravel-chart description: Laravel chart  version: 1.1.1  appVersion: \"1.0.0\"<\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>.gitlab-ci.yaml \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/667338\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a><\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"yaml\">stages:   - publish-charts  variables:   REPO_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/api\/stable\/charts\"  before_script:   - set -eo pipefail   - type trdl &amp;&amp; . $(trdl use werf 1.2 stable)     # \u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c werf \u0434\u043b\u044f gitlab   - type werf &amp;&amp; source $(werf ci-env gitlab --as-file)   - |     werf helm repo update     find . -type f -regex '.*\/\\(Chart.ya?ml\\|requirements.ya?ml\\)' -exec \\       sh -c 'werf helm dependency build $(dirname \"{}\") --skip-refresh' \\;  \"publish charts\":   stage: publish-charts   script:     - |       mkdir -p .packages       while read chart; do         echo \"[PACKAGING CHART $chart]\"         werf helm package \"$chart\" -d .packages       done &lt; &lt;(find .helm\/charts -mindepth 1 -maxdepth 1 -type d)     - |       find .packages -mindepth 1 -maxdepth 1 -type f -name '*.tgz' -exec sh -c 'basename \"$0\"' '{}' \\; | while read package; do         CHART_NAME=$(echo $package | sed -e 's\/-[0-9]\\.[0-9]\\.[0-9]\\.tgz$\/\/g')         CHART_VERSION=$(echo $package | sed -e 's\/^[a-zA-Z-].*-\/\/g' | sed -e 's\/.tgz$\/\/g')         CHART_EXISTS=$(werf helm search repo -l $REPO_NAME\/$CHART_NAME | { egrep \"$REPO_NAME\/$CHART_NAME\\s\"||true; } | { egrep \"$CHART_VERSION\\s\"||true; } | wc -l)         if [ $CHART_EXISTS = 0 ]; then           curl -sSl --post301 --form \"chart=@.packages\/$package\" --user \"$REPO_PUSH:$REPO_PUSH_SECRET\" \"$REPO_URL\"         else           echo \"Chart package $package already exists in Helm repo! Skip!\"         fi       done   only:     refs:       - master   tags:     - werf<\/code><\/pre>\n<p> 3. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e, <code>Settings<\/code>\u00a0->\u00a0<code>Repository<\/code>\u00a0->\u00a0<code>Deploy tokens,<\/code>\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438\u00a0<code>read_package_registry \u0438 write_package_registry<\/code><\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f CI\/CD<\/p>\n<ul>\n<li>\n<p>REPO_NAME &#8212; laravel-chart<\/p>\n<\/li>\n<li>\n<p>REPO_PUSH &#8212; \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432\u044b\u0448\u0435<\/p>\n<\/li>\n<li>\n<p>REPO_PUSH_SECRET &#8212; \u0441\u0435\u043a\u0440\u0435\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432\u044b\u0448\u0435<\/p>\n<\/li>\n<\/ul>\n<ol start=\"4\">\n<li>\n<p>\u0417\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0443 \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448 CI \u0438 \u0438 \u0440\u0435\u0433\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c helm repo<\/p>\n<\/li>\n<\/ol>\n<pre><code>werf helm repo add --username $REPO_PUSH --password $REPO_PUSH_SECRET $REPO_NAME ${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/stable werf helm repo update<\/code><\/pre>\n<ol start=\"5\">\n<li>\n<p>\u041a\u043e\u043c\u043c\u0438\u0442\u0438\u043c \u0438 \u043f\u0443\u0448\u0438\u043c \u043d\u0430\u0448 \u0447\u0430\u0440\u0442 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043f\u043e\u0441\u043b\u0435 \u043f\u0443\u0448\u0430 \u043d\u0430\u0448 \u0447\u0430\u0440\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 <code>Packages &amp; Registries<\/code>\u00a0->\u00a0<code>Package Registry \u043d\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/code><\/p>\n<\/li>\n<\/ol>\n<h2>\u0414\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/h2>\n<p> 1. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8cf\/012\/aa1\/8cf012aa1fd013bfd0371f5cbc271384.png\" width=\"710\" height=\"673\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8cf\/012\/aa1\/8cf012aa1fd013bfd0371f5cbc271384.png\"\/><\/figure>\n<p>.<strong>helm\/Chart.yaml<\/strong><\/p>\n<pre><code class=\"yaml\">apiVersion: v2 name: laravel version: 1.0.2 dependencies:   - name: laravel-chart     export-values:       - parent: werf         child: werf     version: ~1.0     repository: \"@laravel-chart\"<\/code><\/pre>\n<p><strong>werf.yaml<\/strong><\/p>\n<pre><code>project: laravel configVersion: 1 --- image: backend dockerfile: deploy.Dockerfile target: backend --- image: frontend dockerfile: deploy.Dockerfile target: frontend<\/code><\/pre>\n<p><strong>werf-giterminism.yaml<\/strong> (\u0442\u0443\u0442 \u043c\u044b \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0433\u0438\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0437\u043c \u0432 werf \u0442.\u043a \u043d\u0430\u0448 \u0447\u0430\u0440\u0442 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u0433\u0438\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c)<\/p>\n<pre><code>giterminismConfigVersion: 1 helm:   allowUncommittedFiles:     - \".helm\/Chart.lock\"     - \".helm\/charts\/*.tgz\"<\/code><\/pre>\n<p><strong>.gitlab-ci.yaml<\/strong><\/p>\n<pre><code class=\"yaml\">stages:   - publish-chart   - build   - test   - deploy   - cleanup  variables:   REPO_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/api\/stable\/charts\"   HELM_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/stable\"   MAIN_REPO_NAME: \"laravel-chart\"   MAIN_HELM_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/{id \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f}\/packages\/helm\/stable\"  default:   before_script:     - set -eo pipefail     - type trdl &amp;&amp; . $(trdl use werf 1.2 stable)     - type werf &amp;&amp; source $(werf ci-env gitlab --as-file)     - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY  Publish Charts:   stage: publish-chart   script: |     werf helm repo add --force-update --username $MAIN_REPO_PULL --password $MAIN_REPO_PULL_SECRET $MAIN_REPO_NAME $MAIN_HELM_URL     werf helm repo update     werf helm dependency update .helm\/     find .helm\/charts -mindepth 1 -maxdepth 1 -type f -name '*.tgz' -exec sh -c 'basename \"$0\"' '{}' \\; | while read package; do           CHART_NAME=$(echo $package | sed -e 's\/-[0-9]\\.[0-9]\\.[0-9]\\.tgz$\/\/g')           CHART_VERSION=$(echo $package | sed -e 's\/^[a-zA-Z-].*-\/\/g' | sed -e 's\/.tgz$\/\/g')           CHART_EXISTS=$(werf helm search repo $CI_PROJECT_NAME | { egrep \"$MAIN_REPO_NAME\/$CHART_NAME\\s\" || true; } | { egrep \"$CHART_VERSION\\s\" || true; } | wc -l)           if [ $CHART_EXISTS = 0 ]; then             curl -sSl --post301 --form \"chart=@.helm\/charts\/$package\" --user \"$CLIENT_REPO_PUSH:$CLIENT_REPO_PUSH_SECRET\" \"$REPO_URL\"           else             echo \"Chart package $package already exists in Helm repo! Skip!\"           fi         done     werf helm repo add --username $CLIENT_REPO_PULL --password $CLIENT_REPO_PULL_SECRET $CI_PROJECT_NAME $HELM_URL     werf helm repo update   only:     - development     - staging     - master   tags: [werf]   except: [schedules]  #\u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0437\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Build and Publish:   stage: build   script:     - werf build   except: [schedules]   tags: [werf]   only:     - development     - staging     - master #\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432 \u043d\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0435\u0433\u043e Phpunit:   stage: test   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env testing --values .helm\/testing\/values.yaml     - werf kube-run backend --log-verbose=true --env testing -- vendor\/bin\/phpunit --colors=never     - werf dismiss --env testing --with-namespace   only:     - development     - staging     - master   environment:     name: ${CI_COMMIT_REF_SLUG}   tags: [werf]   except: [schedules]   dependencies:     - Build and Publish  .base_deploy:   stage: deploy   tags: [werf]   except: [schedules]   dependencies:     - Build and Publish  #\u0434\u0435\u043f\u043b\u043e\u0438\u043c \u0432 \u0434\u0435\u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 Deploy to development:   extends: .base_deploy   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env development --auto-rollback=true --values .helm\/development\/values.yaml   only:     - development   environment:     name: development  #\u0434\u0435\u043f\u043b\u043e\u0438\u043c \u0432 \u0441\u0442\u0430\u0433 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 Deploy to staging:   extends: .base_deploy   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env staging --auto-rollback=true --values .helm\/staging\/values.yaml   only:     - staging   environment:     name: staging  #\u0434\u0435\u043f\u043b\u043e\u0438\u043c \u0432 \u043f\u0440\u043e\u0434 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 Deploy to production:   extends: .base_deploy   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env production --auto-rollback=true --values .helm\/production\/values.yaml   only:     - master   environment:     name: production  #\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0430\u0441\u043a \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u043d\u0443\u0436\u043d\u044b\u0445 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438 Cleanup:   stage: cleanup   script:     - werf cr login -u nobody -p ${WERF_IMAGES_CLEANUP_PASSWORD} ${WERF_REPO}     - werf cleanup --repo=${WERF_REPO}   only: [schedules]   tags: [werf] <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e, <code>Settings<\/code>\u00a0->\u00a0<code>Repository<\/code>\u00a0->\u00a0<code>Deploy tokens,<\/code>\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b<\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 write_package_registry \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f CLIENT_REPO_PUSH \u0438 CLIENT_REPO_PUSH_SECRET<\/p>\n<\/li>\n<li>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 read_package_registry \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044fCLIENT_REPO_PULL \u0438 CLIENT_REPO_PULL_SECRET<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b <code>Settings<\/code>\u00a0->\u00a0<code>Repository<\/code>\u00a0->\u00a0<code>Deploy tokens<\/code> \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 read_package_registry, \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f MAIN_REPO_PULL \u0438 MAIN_REPO_PULL_SECRET <\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<blockquote>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432,  \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/ru.werf.io\/\" rel=\"noopener noreferrer nofollow\">werf<\/a>. \u042d\u0442\u043e \u0442\u0435\u043c\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<\/blockquote>\n<p><strong>\u0418\u0442\u043e\u0433<\/strong><\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0445 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0448 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438\u043c\u0435\u044f \u0442\u043e\u043b\u044c\u043a\u043e values \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 CI \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0447\u0430\u0440\u0442 \u0432\u044b\u043a\u0430\u0447\u0430\u0435\u0442\u0441\u044f \u0438 \u0437\u0430\u043f\u0443\u0448\u0438\u0442\u0441\u044f \u0432 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 package registry, \u0438\u043c\u0435\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0432\u0435\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><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\/articles\/734922\/\"> https:\/\/habr.com\/ru\/articles\/734922\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<blockquote>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 <a href=\"https:\/\/ru.werf.io\/\" rel=\"noopener noreferrer nofollow\">werf<\/a> \u043e\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 <a href=\"https:\/\/habr.com\/ru\/companies\/flant\/profile\/\" rel=\"noopener noreferrer nofollow\">\u0424\u043b\u0430\u043d\u0442<\/a> \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 CI\/CD \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 K8s.<\/p>\n<\/blockquote>\n<h2>\u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/h2>\n<p>\u0418\u043c\u0435\u0435\u043c \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0432 k8s, \u0433\u0434\u0435 \u043a\u0440\u0443\u0442\u044f\u0442\u0441\u044f \u0438 \u0434\u0435\u043f\u043b\u043e\u044f\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043d\u0430 \u043f\u0445\u043f, \u0433\u043e, js &#8230; \u041f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u043e\u043c\u0438\u043c\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u0434\u0430 \u043d\u0430\u0431\u043e\u0440 \u043a\u0443\u0431\u0435\u0440\u043d\u0435\u0442\u0438\u0441 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 (deployment, configMap, Secret, Job&#8230;)<\/p>\n<figure class=\"bordered full-width\">\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel<\/figcaption><\/div>\n<\/figure>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u043a\u0430<\/h2>\n<p>\u0412\u044b\u043a\u0430\u0442 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0431\u043e\u043b\u044c\u044e, \u043f\u043e \u0441\u0443\u0442\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0434\u043b\u044f k8s (\u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442), \u043d\u0435\u0442 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043a\u0443\u0431\u0443\u0440\u043d\u0435\u0442\u0438\u0441\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043c\u043d\u043e\u0433\u043e \u043b\u0438\u0448\u043d\u0438\u0445 \u0437\u043d\u0430\u043d\u0438\u0439 \u043e\u0431 \u0438\u043d\u0444\u0440\u043e\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432, \u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0431\u044b\u0432\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435, \u043a\u0442\u043e \u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0430\u043c, \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0430 \u043a\u0442\u043e \u0442\u043e \u043d\u0435\u0442, \u043f\u043e \u0441\u0443\u0442\u0438 \u0442\u0430\u043a\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0431\u044b\u043b\u0430 \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u0430 \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0434\u0435\u043f\u043b\u043e\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0438 \u0434\u0435\u0432\u043e\u043f\u0441\u043e\u0432.<\/p>\n<h2>\u0416\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/h2>\n<p>\u0418\u043c\u0435\u0442\u044c \u0435\u0434\u0438\u043d\u044b\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 helm \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 (php, go, js &#8230;), \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0432\u0435\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0447\u0430\u0440\u0442\u0430, \u0432 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u043c\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u044b values \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0434\u0435\u043f\u043b\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Laravel<\/figcaption><\/div>\n<\/figure>\n<h2>\u0414\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043b\u0438\u0446\u0430<\/h2>\n<p><strong>Gitlab, K8s, werf, docke<\/strong>r (\u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0442\u043e \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u044b \u043a k8s, Gitlab, docker \u0443\u0436\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f)<\/p>\n<h2>\u041f\u043e\u0435\u0445\u0430\u043b\u0438!<\/h2>\n<p><strong>Werf<\/strong><\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c werf \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 Gitlab \u0441\u043b\u0435\u0434\u0443\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 (werf \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u0430 \u0445\u043e\u0441\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044f image) <a href=\"https:\/\/ru.werf.io\/documentation\/v1.2\/index.html?usage=ci&amp;ci=gitlabCiCd&amp;runnerType=hostRunner&amp;os=linux&amp;buildBackend=docker&amp;projectType=simplified&amp;sharedCICD=no&amp;repoType=application\" rel=\"noopener noreferrer nofollow\">https:\/\/ru.werf.io\/documentation\/v1.2\/index.html?usage=ci&amp;ci=gitlabCiCd&amp;runnerType=hostRunner&amp;os=linux&amp;buildBackend=docker&amp;projectType=simplified&amp;sharedCICD=no&amp;repoType=application<\/a><\/p>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c runner \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <a href=\"https:\/\/ru.werf.io\/documentation\/v1.1\/guides\/gitlab_ci_cd_integration.html\" rel=\"noopener noreferrer nofollow\">https:\/\/ru.werf.io\/documentation\/v1.1\/guides\/gitlab_ci_cd_integration.html<\/a><\/p>\n<h2>\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/h2>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 laravel-chart, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\">\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<ol start=\"2\">\n<li>\n<p>.helm\/charts\/laravel-chart\/Chart.yaml<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"yaml\">apiVersion: v2 name: laravel-chart description: Laravel chart  version: 1.1.1  appVersion: \"1.0.0\"<\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>.gitlab-ci.yaml \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/667338\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a><\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"yaml\">stages:   - publish-charts  variables:   REPO_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/api\/stable\/charts\"  before_script:   - set -eo pipefail   - type trdl &amp;&amp; . $(trdl use werf 1.2 stable)     # \u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c werf \u0434\u043b\u044f gitlab   - type werf &amp;&amp; source $(werf ci-env gitlab --as-file)   - |     werf helm repo update     find . -type f -regex '.*\/\\(Chart.ya?ml\\|requirements.ya?ml\\)' -exec \\       sh -c 'werf helm dependency build $(dirname \"{}\") --skip-refresh' \\;  \"publish charts\":   stage: publish-charts   script:     - |       mkdir -p .packages       while read chart; do         echo \"[PACKAGING CHART $chart]\"         werf helm package \"$chart\" -d .packages       done &lt; &lt;(find .helm\/charts -mindepth 1 -maxdepth 1 -type d)     - |       find .packages -mindepth 1 -maxdepth 1 -type f -name '*.tgz' -exec sh -c 'basename \"$0\"' '{}' \\; | while read package; do         CHART_NAME=$(echo $package | sed -e 's\/-[0-9]\\.[0-9]\\.[0-9]\\.tgz$\/\/g')         CHART_VERSION=$(echo $package | sed -e 's\/^[a-zA-Z-].*-\/\/g' | sed -e 's\/.tgz$\/\/g')         CHART_EXISTS=$(werf helm search repo -l $REPO_NAME\/$CHART_NAME | { egrep \"$REPO_NAME\/$CHART_NAME\\s\"||true; } | { egrep \"$CHART_VERSION\\s\"||true; } | wc -l)         if [ $CHART_EXISTS = 0 ]; then           curl -sSl --post301 --form \"chart=@.packages\/$package\" --user \"$REPO_PUSH:$REPO_PUSH_SECRET\" \"$REPO_URL\"         else           echo \"Chart package $package already exists in Helm repo! Skip!\"         fi       done   only:     refs:       - master   tags:     - werf<\/code><\/pre>\n<p> 3. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e, <code>Settings<\/code>\u00a0->\u00a0<code>Repository<\/code>\u00a0->\u00a0<code>Deploy tokens,<\/code>\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438\u00a0<code>read_package_registry \u0438 write_package_registry<\/code><\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f CI\/CD<\/p>\n<ul>\n<li>\n<p>REPO_NAME &#8212; laravel-chart<\/p>\n<\/li>\n<li>\n<p>REPO_PUSH &#8212; \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432\u044b\u0448\u0435<\/p>\n<\/li>\n<li>\n<p>REPO_PUSH_SECRET &#8212; \u0441\u0435\u043a\u0440\u0435\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432\u044b\u0448\u0435<\/p>\n<\/li>\n<\/ul>\n<ol start=\"4\">\n<li>\n<p>\u0417\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0443 \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448 CI \u0438 \u0438 \u0440\u0435\u0433\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c helm repo<\/p>\n<\/li>\n<\/ol>\n<pre><code>werf helm repo add --username $REPO_PUSH --password $REPO_PUSH_SECRET $REPO_NAME ${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/stable werf helm repo update<\/code><\/pre>\n<ol start=\"5\">\n<li>\n<p>\u041a\u043e\u043c\u043c\u0438\u0442\u0438\u043c \u0438 \u043f\u0443\u0448\u0438\u043c \u043d\u0430\u0448 \u0447\u0430\u0440\u0442 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043f\u043e\u0441\u043b\u0435 \u043f\u0443\u0448\u0430 \u043d\u0430\u0448 \u0447\u0430\u0440\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 <code>Packages &amp; Registries<\/code>\u00a0->\u00a0<code>Package Registry \u043d\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/code><\/p>\n<\/li>\n<\/ol>\n<h2>\u0414\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/h2>\n<p> 1. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>.<strong>helm\/Chart.yaml<\/strong><\/p>\n<pre><code class=\"yaml\">apiVersion: v2 name: laravel version: 1.0.2 dependencies:   - name: laravel-chart     export-values:       - parent: werf         child: werf     version: ~1.0     repository: \"@laravel-chart\"<\/code><\/pre>\n<p><strong>werf.yaml<\/strong><\/p>\n<pre><code>project: laravel configVersion: 1 --- image: backend dockerfile: deploy.Dockerfile target: backend --- image: frontend dockerfile: deploy.Dockerfile target: frontend<\/code><\/pre>\n<p><strong>werf-giterminism.yaml<\/strong> (\u0442\u0443\u0442 \u043c\u044b \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0433\u0438\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0437\u043c \u0432 werf \u0442.\u043a \u043d\u0430\u0448 \u0447\u0430\u0440\u0442 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u0433\u0438\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c)<\/p>\n<pre><code>giterminismConfigVersion: 1 helm:   allowUncommittedFiles:     - \".helm\/Chart.lock\"     - \".helm\/charts\/*.tgz\"<\/code><\/pre>\n<p><strong>.gitlab-ci.yaml<\/strong><\/p>\n<pre><code class=\"yaml\">stages:   - publish-chart   - build   - test   - deploy   - cleanup  variables:   REPO_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/api\/stable\/charts\"   HELM_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/${CI_PROJECT_ID}\/packages\/helm\/stable\"   MAIN_REPO_NAME: \"laravel-chart\"   MAIN_HELM_URL: \"${CI_SERVER_URL}\/api\/v4\/projects\/{id \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f}\/packages\/helm\/stable\"  default:   before_script:     - set -eo pipefail     - type trdl &amp;&amp; . $(trdl use werf 1.2 stable)     - type werf &amp;&amp; source $(werf ci-env gitlab --as-file)     - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY  Publish Charts:   stage: publish-chart   script: |     werf helm repo add --force-update --username $MAIN_REPO_PULL --password $MAIN_REPO_PULL_SECRET $MAIN_REPO_NAME $MAIN_HELM_URL     werf helm repo update     werf helm dependency update .helm\/     find .helm\/charts -mindepth 1 -maxdepth 1 -type f -name '*.tgz' -exec sh -c 'basename \"$0\"' '{}' \\; | while read package; do           CHART_NAME=$(echo $package | sed -e 's\/-[0-9]\\.[0-9]\\.[0-9]\\.tgz$\/\/g')           CHART_VERSION=$(echo $package | sed -e 's\/^[a-zA-Z-].*-\/\/g' | sed -e 's\/.tgz$\/\/g')           CHART_EXISTS=$(werf helm search repo $CI_PROJECT_NAME | { egrep \"$MAIN_REPO_NAME\/$CHART_NAME\\s\" || true; } | { egrep \"$CHART_VERSION\\s\" || true; } | wc -l)           if [ $CHART_EXISTS = 0 ]; then             curl -sSl --post301 --form \"chart=@.helm\/charts\/$package\" --user \"$CLIENT_REPO_PUSH:$CLIENT_REPO_PUSH_SECRET\" \"$REPO_URL\"           else             echo \"Chart package $package already exists in Helm repo! Skip!\"           fi         done     werf helm repo add --username $CLIENT_REPO_PULL --password $CLIENT_REPO_PULL_SECRET $CI_PROJECT_NAME $HELM_URL     werf helm repo update   only:     - development     - staging     - master   tags: [werf]   except: [schedules]  #\u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0437\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Build and Publish:   stage: build   script:     - werf build   except: [schedules]   tags: [werf]   only:     - development     - staging     - master #\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432 \u043d\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0435\u0433\u043e Phpunit:   stage: test   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env testing --values .helm\/testing\/values.yaml     - werf kube-run backend --log-verbose=true --env testing -- vendor\/bin\/phpunit --colors=never     - werf dismiss --env testing --with-namespace   only:     - development     - staging     - master   environment:     name: ${CI_COMMIT_REF_SLUG}   tags: [werf]   except: [schedules]   dependencies:     - Build and Publish  .base_deploy:   stage: deploy   tags: [werf]   except: [schedules]   dependencies:     - Build and Publish  #\u0434\u0435\u043f\u043b\u043e\u0438\u043c \u0432 \u0434\u0435\u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 Deploy to development:   extends: .base_deploy   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env development --auto-rollback=true --values .helm\/development\/values.yaml   only:     - development   environment:     name: development  #\u0434\u0435\u043f\u043b\u043e\u0438\u043c \u0432 \u0441\u0442\u0430\u0433 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 Deploy to staging:   extends: .base_deploy   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env staging --auto-rollback=true --values .helm\/staging\/values.yaml   only:     - staging   environment:     name: staging  #\u0434\u0435\u043f\u043b\u043e\u0438\u043c \u0432 \u043f\u0440\u043e\u0434 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 Deploy to production:   extends: .base_deploy   script:     - werf helm dependency update .helm\/     - werf converge --skip-build --env production --auto-rollback=true --values .helm\/production\/values.yaml   only:     - master   environment:     name: production  #\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0430\u0441\u043a \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u043d\u0443\u0436\u043d\u044b\u0445 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438 Cleanup:   stage: cleanup   script:     - werf cr login -u nobody -p ${WERF_IMAGES_CLEANUP_PASSWORD} ${WERF_REPO}     - werf cleanup --repo=${WERF_REPO}   only: [schedules]   tags: [werf] <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e, <code>Settings<\/code>\u00a0->\u00a0<code>Repository<\/code>\u00a0->\u00a0<code>Deploy tokens,<\/code>\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b<\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 write_package_registry \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f CLIENT_REPO_PUSH \u0438 CLIENT_REPO_PUSH_SECRET<\/p>\n<\/li>\n<li>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 read_package_registry \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044fCLIENT_REPO_PULL \u0438 CLIENT_REPO_PULL_SECRET<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b <code>Settings<\/code>\u00a0->\u00a0<code>Repository<\/code>\u00a0->\u00a0<code>Deploy tokens<\/code> \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 read_package_registry, \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f MAIN_REPO_PULL \u0438 MAIN_REPO_PULL_SECRET <\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<blockquote>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432,  \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/ru.werf.io\/\" rel=\"noopener noreferrer nofollow\">werf<\/a>. \u042d\u0442\u043e \u0442\u0435\u043c\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<\/blockquote>\n<p><strong>\u0418\u0442\u043e\u0433<\/strong><\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0445 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0448 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438\u043c\u0435\u044f \u0442\u043e\u043b\u044c\u043a\u043e values \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 CI \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0447\u0430\u0440\u0442 \u0432\u044b\u043a\u0430\u0447\u0430\u0435\u0442\u0441\u044f \u0438 \u0437\u0430\u043f\u0443\u0448\u0438\u0442\u0441\u044f \u0432 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 package registry, \u0438\u043c\u0435\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0432\u0435\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/><\/br><\/p>\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-347416","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/347416","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=347416"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/347416\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=347416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=347416"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=347416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}