{"id":370136,"date":"2024-05-21T04:18:39","date_gmt":"2024-05-21T04:18:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=370136"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=370136","title":{"rendered":"<span>\u041a\u0430\u043a \u0432\u043e\u043e\u0431\u0449\u0435 \u044d\u0442\u043e\u0442 \u0432\u0430\u0448 CI CD \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440. \u042d\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f, \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u043d\u0430 \u0444\u0438\u0434\u0431\u0435\u043a \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f \u043e\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u044b\u0445 \u043b\u044e\u0434\u0435\u0439 \u0432 \u0441\u0444\u0435\u0440\u0443 \u0441\u0442\u0430\u0442\u044c\u0438, \u0434\u0430 \u0438 \u0432 \u0446\u0435\u043b\u043e\u043c \u0432 IT. \u042f \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0447\u0442\u043e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c\u0438 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u044e \u043d\u0430 \u0438\u0441\u0442\u0438\u043d\u0443 \u0438 \u0443\u0436 \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043d\u0435 \u0443\u0447\u0443 \u043a\u043e\u0433\u043e-\u0442\u043e \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u0414\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u0445\u043e\u0447\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u043c, \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430 &#8212; \u0447\u0442\u043e \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0438 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u0445\u043e\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445\u00a0\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0441\u0432\u043e\u0435\u043c \u043e\u043f\u044b\u0442\u0435 \u0438 \u043a \u0447\u0435\u043c\u0443 \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438. \u041d\u0443 \u0438 \u0432\u0441\u0435 \u0448\u0443\u0442\u043a\u0438 \u043f\u0440\u043e \u043b\u0443\u0447\u0448\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u044b &#8212; \u044d\u0442\u043e \u0432\u0441\u0435 \u0448\u0443\u0442\u043a\u0438, \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0443\u0436\u0435 1000 Best Practices \u0438\u0437 10 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438, \u0442\u0430\u043a \u0447\u0442\u043e \u0436\u0434\u0443 \u0438 \u0432\u0430\u0441 \u0442\u0430\u043c.<\/p>\n<h2>\u041a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a CI\/CD?<\/h2>\n<p>\u042f \u043f\u0440\u0438\u0448\u0435\u043b \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e, \u0443\u0436\u0435 2 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 IT \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435.\u00a0\u041f\u043e \u043d\u0430\u0447\u0430\u043b\u0443 &#8212; \u044d\u0442\u043e GitHub + Vercel(\u0434\u0430-\u0434\u0430, \u0438 \u0444\u0440\u043e\u043d\u0442 \u0438 \u0431\u0435\u043a \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 1 \u043f\u0440\u043e\u0435\u043a\u0442\u0430), \u043f\u043e\u0437\u0436\u0435 \u043d\u043e\u0432\u044b\u0439 \u0431\u0435\u043a, \u043d\u043e\u0432\u044b\u0439 \u0444\u0440\u043e\u043d\u0442 &#8212; \u0443\u0436\u0435 \u0434\u0432\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 &#8212; SSH, \u0440\u0443\u0447\u043a\u0430\u043c\u0438 git pull, nginx &#8212; \u0433\u0434\u0435-\u0442\u043e \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0430\u0445. \u041d\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u044f \u0431\u044b\u043b \u0440\u0430\u0434 &#8212; \u0438\u0431\u043e \u0443\u0436\u0435 \u043d\u0430 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u0447\u0442\u043e \u0432 Docker \u0441\u0438\u043b\u0430, \u043d\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u0430\u0443\u0442\u0441\u043e\u0440\u0441\u0435\u0440\u044b. \u041f\u043e\u0437\u0436\u0435 \u0440\u043e\u0441\u0442, \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439, \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 GitLab, \u043f\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0448\u0442\u0430\u0442\u0430 &#8212; \u043d\u0443\u0436\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c. \u041a\u0430\u043a \u0438 \u043b\u044e\u0431\u0430\u044f \u0434\u0440\u0443\u0433\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f &#8212; \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043c \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u043d\u0443\u0436\u0435\u043d \u0430\u0432\u0442\u043e\u0434\u0435\u043f\u043b\u043e\u0439. \u041d\u0430 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u0443\u0431\u0435\u0440.<\/p>\n<h2>\u041d\u0430\u0448\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0432 CI\/CD<\/h2>\n<p>\u0427\u0442\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c? \u041d\u0443 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e &#8212; \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.<\/p>\n<p>P.S. \u0421\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043d\u0430\u0448\u0435\u043b \u0441\u0435\u0431\u044f \u0432 \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u044f\u043d\u0434\u0435\u043a\u0441\u0430 &#8212; \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u0432\u0441\u0435\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f.<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/tutorials\/infrastructure-management\/gitlab-containers\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043d\u0430\u043b \u0425\u0430\u0443\u0434\u0438 \u0425\u043e<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/tutorials\/serverless\/ci-cd-serverless\" rel=\"noopener noreferrer nofollow\">\u042f\u043d\u0434\u0435\u043a\u0441 \u041f\u0440\u0430\u043a\u0442\u0438\u043a\u0443\u043c<\/a><\/p>\n<\/li>\n<\/ul>\n<p>P.P.S. \u041d\u0443 \u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u0441\u0435-\u0432\u0441\u0435-\u0432\u0441\u0435 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 gitlab \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0432\u044b\u0443\u0447\u0438\u0442\u044c &#8212; \u043d\u0435 \u0437\u0440\u044f \u043f\u0438\u0441\u0430\u043b\u0438.<\/p>\n<h3>\u0411\u0438\u043b\u0434<\/h3>\n<p>\u0421 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u044b\u043c \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0431\u0438\u043b\u0434(\u043d\u0443 \u043f\u043e\u0447\u0442\u0438) &#8212; \u0435\u0433\u043e \u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c. \u041a\u0430\u043a \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u043b \u0432\u044b\u0448\u0435 &#8212; Docker \u044d\u0442\u043e \u043c\u043e\u0449\u044c, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u044b \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u043d\u0435\u0434\u0440\u0438\u043b\u0438 \u0435\u0433\u043e \u0432 \u043d\u0430\u0448 \u043f\u0440\u043e\u0434\u0443\u043a\u0442. \u041d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 Dockerfile&#8217;\u044b &#8212; \u043f\u0438\u0448\u0435\u043c \u043d\u0430\u0448 CI:<\/p>\n<pre><code class=\"yaml\"># templates\/build\/kaniko.yaml variables:   TAG: $CI_COMMIT_SHA   DOCKERFILE: $CI_PROJECT_DIR\/Dockerfile   ARGUMENTS: \"\"  build-kaniko:   stage: build   image:     name: gcr.io\/kaniko-project\/executor:v1.21.0-debug     entrypoint: [ \"\" ]   script:     - echo \"Build with tag $TAG\"     - mkdir -p \/kaniko\/.docker     - echo \"{\\\"auths\\\":{\\\"${CI_REGISTRY}\\\":{\\\"auth\\\":\\\"$(printf \"%s:%s\" \"${CI_REGISTRY_USER}\" \"${CI_REGISTRY_PASSWORD}\" | base64 | tr -d '\\n')\\\"},\\\"$(echo -n $CI_DEPENDENCY_PROXY_SERVER | awk -F[:] '{print $1}')\\\":{\\\"auth\\\":\\\"$(printf \"%s:%s\" ${CI_DEPENDENCY_PROXY_USER} \"${CI_DEPENDENCY_PROXY_PASSWORD}\" | base64 | tr -d '\\n')\\\"}}}\" > \/kaniko\/.docker\/config.json     - echo \"Run this build ${CI_REGISTRY_IMAGE}-${CI_ENVIRONMENT_NAME}\"     - >-       \/kaniko\/executor       --context $CI_PROJECT_DIR       --dockerfile $DOCKERFILE       --destination $CI_REGISTRY_IMAGE:$TAG       --cache=true       $ARGUMENTS   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: on_success     - when: never <\/code><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0443\u0442 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f? \u041d\u0443 \u0432\u043e \u043f\u0435\u0440\u0432\u044b\u0445 &#8212; \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0442\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043e\u0431\u0440\u0430\u0437\u044b \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u0445 \u0432 Registry &#8212; \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0448 \u0431\u0438\u043b\u0434 \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u044b \u0441 \u0442\u0435\u0433\u043e\u043c $CI_COMMIT_SHA &#8212; \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0438\u043c\u0435\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0435\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u043a\u043e\u043c\u0438\u0442\u0443 &#8212; \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0434\u043d\u043e \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0435, \u043c\u0435\u043b\u043e\u0447\u044c, \u0430 \u043f\u0440\u0438\u044f\u0442\u043d\u043e. \u0422\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c &#8212; \u0447\u0442\u043e \u0431\u0438\u043b\u0434 \u0432\u0441\u0435\u0433\u043e 1.<\/p>\n<p>\u041f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 Registry:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/administration\/packages\/container_registry.html#configure-s3-and-gcs-storage-drivers-for-linux-package-installations\" rel=\"noopener noreferrer nofollow\">\u041e\u043d\u043b\u0430\u0439\u043d \u043f\u043b\u043e\u0449\u0430\u0434\u043a\u0430 SkillBox<\/a><\/p>\n<\/li>\n<\/ul>\n<h3>\u0414\u0435\u043f\u043b\u043e\u0439<\/h3>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e \u043a\u0443\u0431\u0435\u0440, \u043c\u044b \u0436\u0435 \u0445\u043e\u0442\u0438\u043c \u0434\u0435\u043f\u043b\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c &#8212; \u0432\u0435\u0440\u043d\u043e?<\/p>\n<pre><code class=\"yaml\"># templates\/deploy\/kubernetes.yaml variables:   DOCKER_IMAGE: $CI_REGISTRY_IMAGE   DOCKER_TAG: $CI_COMMIT_SHA   DEPLOYMENT_DATE: `date +%Y%m%d-%H-%M-%S`   MANIFEST_FOLDER: \"k8s\"   KUBECONFIG: \"\"   deploy-k8s:   stage: deploy   image:     name: alpine:3.19   script:     - apk update &amp;&amp; apk add gettext     - wget https:\/\/storage.googleapis.com\/kubernetes-release\/release\/v1.26.0\/bin\/linux\/amd64\/kubectl     - chmod +x .\/kubectl     - .\/kubectl create secret docker-registry regcred --docker-server=$CI_REGISTRY --docker-username=$CI_DEPLOY_USER --docker-password=$CI_DEPLOY_PASSWORD -n $CI_ENVIRONMENT_NAME || true     - >-        for MANIFEST in $MANIFEST_FOLDER\/*; do         envsubst &lt; $MANIFEST | .\/kubectl apply -n $CI_ENVIRONMENT_NAME -f -;       done   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: on_success     - when: never  <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0431\u0435\u0436\u0438\u043c\u0441\u044f \u043f\u043e \u0432\u0430\u0436\u043d\u043e\u043c\u0443. DOCKER_IMAGE \u0438 DOCKER_TAG \u0443 \u043d\u0430\u0441 \u0432 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0435 \u0434\u0435\u043f\u043b\u043e\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u044b, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e envsubst \u043c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430 \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f \u0435\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u0443\u0431\u0435\u0440. KUBECONFIG \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 CI\/CD > Variables, \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0444\u0430\u0439\u043b\u0430. \u0422\u0430\u043a\u0436\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u043a\u0430\u0437\u0430\u0442\u044c &#8212; \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u043a\u0443\u0431\u0435\u0440, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 &#8212; \u0447\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0432 \u0435\u043d\u0432\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c(\u043b\u0438\u0431\u043e \u0432 variables \u0432 gitlab-ci \u043f\u0440\u043e\u0435\u043a\u0442\u0430).<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044f \u0441\u043e\u0437\u0434\u0430\u044e \u0441\u0435\u043a\u0440\u0435\u0442 regcred &#8212; \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043a\u0440\u0435\u0434\u044b \u0434\u043b\u044f registry.<\/p>\n<p>\u041f\u043e regcred \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/pull-image-private-registry\/\" rel=\"noopener noreferrer nofollow\">\u042f\u042e\u043d\u0438\u043e\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/user\/packages\/container_registry\/authenticate_with_container_registry.html\" rel=\"noopener noreferrer nofollow\">\u042f\u043d\u0434\u0435\u043a\u0441 \u041c\u0435\u0442\u0440\u0438\u043a\u0430<\/a><\/p>\n<\/li>\n<\/ul>\n<h2>\u0410 \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/h2>\n<p>\u0412\u043e\u0442 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0434\u0435\u043f\u043b\u043e\u0439. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 &#8212; \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0436\u0435\u043b\u0430\u043d\u0438\u0435, \u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u043c <s>\u0431\u0435\u0437\u0434\u0443\u043c\u043d\u043e<\/s> \u0432\u0441\u0435 \u0432 \u043f\u0440\u043e\u0434 \u043f\u0438\u0445\u0430\u0442\u044c. \u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u043a\u043e\u043b\u044c\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0431\u0438\u0437\u043d\u0435\u0441 \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u044b\u043a\u0430\u0442\u044c \u0432\u0441\u0435 \u0440\u0443\u0447\u043a\u0430\u043c\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0430\u043b\u043e \u043d\u0430 dev \u0438 prod \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 &#8212; \u0433\u0434\u0435 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0443\u0448\u0438\u0442\u0441\u044f \u0432\u0441\u0435 \u0432 dev, \u043f\u043e\u0437\u0436\u0435 \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0432\u0441\u0435 \u043e\u043a &#8212; \u043b\u0435\u0442\u0438\u0442 \u0432 prod.<\/p>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0431\u044b\u043b\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f. \u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u043c 2 \u0432\u0435\u0442\u043a\u0438, stable \u0438 main(\u0443 \u043d\u0430\u0441 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 dev), CI \u0434\u043b\u044f main &#8212; \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0439 \u0431\u0438\u043b\u0434, \u043e\u0442\u043f\u0440\u0430\u0432\u044c \u043d\u0430 dev, CI \u0434\u043b\u044f stable &#8212; \u0441\u043e\u0437\u0434\u0430\u0439 \u0431\u0438\u043b\u0434, \u043e\u0442\u043f\u0440\u0430\u0432\u044c \u043d\u0430 prod. \u0411\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0430\u043b\u043e \u044f\u0441\u043d\u043e, \u0447\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u044d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043a\u0435\u0439\u0441. \u0414\u043e\u043b\u0433\u043e \u0437\u0430\u043e\u0441\u0442\u0440\u044f\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443, \u043a\u043e\u0440\u043e\u0442\u043a\u043e \u0441\u043a\u0430\u0436\u0443 &#8212; \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0437, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430 dev != \u043e\u0431\u0440\u0430\u0437 \u043d\u0430 prod, \u0430 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043d\u0435 \u0443\u043c\u043d\u044b\u0439 \u0447\u0435\u043b\u043e\u0432\u0435\u043a~~(\u044f)~~ \u0437\u0430\u043f\u0443\u0448\u0438\u0442 \u043d\u0430 stable \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e? \u0412 \u043e\u0431\u0449\u0435\u043c \u043e\u0442 \u0438\u0434\u0435\u0438 \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c, \u043f\u043e\u0448\u043b\u0438 \u0434\u0443\u043c\u0430\u0442\u044c.<br \/> \u0412\u044b\u0445\u043e\u0434 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430\u0448\u043b\u0438 \u043d\u0435 \u0431\u044b\u0441\u0442\u0440\u043e, \u0432 \u0433\u043e\u043b\u043e\u0432\u0435 \u0442\u043e \u0438 \u043a\u0440\u0443\u0442\u0438\u043b\u0430\u0441\u044c \u0444\u0440\u0430\u0437\u0430 &#171;\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f. \u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0430&#187;. \u0410 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u043e\u0442 \u0436\u0435 \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 CI \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0442\u044c? \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u0448\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<h3>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445<\/h3>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u0438\u0441\u044c \u043e\u0442 2\u0445 \u0431\u0438\u043b\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0435\u043d\u0432\u043e\u0432. \u0422\u0435\u043f\u0435\u0440\u044c 1 \u0431\u0438\u043b\u0434 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 dev, \u0430 \u043f\u043e\u0437\u0436\u0435 \u043e\u043d \u0436\u0435 \u043b\u0435\u0442\u0438\u0442 \u0432 prod &#8212; \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c 2 \u0440\u0430\u0437\u043d\u044b\u0445 \u0434\u0435\u043f\u043b\u043e\u044f \u0432 \u043a\u0443\u0431\u0435\u0440 &#8212; \u043e\u0434\u0438\u043d \u0434\u043b\u044f dev, \u0434\u0440\u0443\u0433\u043e\u0439 \u0434\u043b\u044f prod. \u041a\u0430\u043a?<\/p>\n<pre><code class=\"yaml\"># templates\/deploy\/kubernetes.yaml ...  .deploy-k8s-template:   stage: deploy   image:     name: alpine:3.19  ... <\/code><\/pre>\n<p>\u0414\u0430 \u0432 \u043e\u0431\u0449\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e, \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u0442\u043e\u0447\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u043d\u0430\u0448\u0435\u0439 \u0434\u0436\u043e\u0431\u044b, \u043d\u0443 \u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c \u0438 \u0438\u0437 \u043d\u0435\u0433\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 2 \u0434\u0436\u043e\u0431\u044b!<\/p>\n<pre><code class=\"yaml\"># templates\/deploy\/kubernetes.yaml ...  deploy-dev:   environment: dev   extends: .deploy-k8s-template  deploy-prod:   environment: prod   extends: .deploy-k8s-template   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: manual     - when: never     <\/code><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0443\u0442 \u0432\u0430\u0436\u043d\u043e? \u0414\u0430 \u0432 \u0446\u0435\u043b\u043e\u043c \u043e\u0441\u043e\u0431\u043e \u043d\u0438\u0447\u0435\u0433\u043e. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u0435\u043d\u044f\u0435\u043c environment &#8212; \u0442\u043e \u0435\u0441\u0442\u044c \u0442\u043e, \u0432 \u043a\u0430\u043a\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043d\u0430\u0448.<\/p>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/environments\/\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043d\u0430\u043b \u0413\u043e\u0448\u0430 \u0414\u0443\u0434\u0430\u0440\u044c<\/a><\/p>\n<\/li>\n<\/ul>\n<h2>\u0420\u0435\u043b\u0438\u0437?<\/h2>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u0441\u0435 &#8212; <s>\u0434\u0435\u043d\u044c\u0433\u0438, \u0442\u0430\u0447\u043a\u0438<\/s> \u0431\u0438\u043b\u0434, \u0434\u0435\u043f\u043b\u043e\u0439 \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u0440\u043e\u0441\u043b\u0430, \u043f\u043e\u044f\u0432\u043b\u044f\u043b\u043e\u0441\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043d\u0430\u0448 \u043c\u043e\u043d\u043e\u043b\u0438\u0442 \u043f\u043e\u0442\u0438\u0445\u043e\u043d\u044c\u043a\u0443 \u0440\u0430\u0441\u043f\u0438\u043b\u0438\u0432\u0430\u043b\u0441\u044f(\u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0447\u0435\u0440\u0435\u0437 \u043b\u0435\u0442 10 \u0440\u0430\u0441\u043f\u0438\u043b\u0438\u0442\u0441\u044f). \u0421\u0442\u0430\u043b\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0442\u044c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e &#8212; \u0447\u0442\u043e \u0437\u0430 \u0432\u0435\u0440\u0441\u0438\u044f. \u0410 \u043a\u0430\u043a \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c? \u0418\u0441\u043a\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u043c\u0438\u0442? \u041c\u043d\u043e\u0433\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0432\u043e\u0434\u044b \u0443\u0442\u0435\u043a\u043b\u043e \u0432 \u044d\u0442\u043e\u0442 \u043f\u0435\u0440\u0438\u043e\u0434 \u0438 \u0438\u0434\u0435\u044f \u0431\u044b\u043b\u0430 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0440\u0435\u043b\u0438\u0437\u043e\u0432 \u0438 \u0442\u0435\u0433\u043e\u0432. \u042f, \u043a\u0430\u043a \u043e\u0447\u0435\u043d\u044c \u043d\u0435 \u043b\u044e\u0431\u044f\u0449\u0438\u0439 \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0443\u043a\u0430\u043c\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0440\u0435\u0448\u0438\u043b \u044d\u0442\u043e \u0432\u0441\u0435 \u0434\u0435\u043b\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0427\u0442\u043e \u043d\u0430\u043c \u0434\u0435\u043b\u0430\u0442\u044c? \u041f\u043e\u043b\u0435\u0437\u043b\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442, \u043d\u0430\u0448\u043b\u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0442\u0430\u043c \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f, semver, \u043d\u043e \u0432\u043e\u0442 \u043d\u0435 \u0437\u0430\u0434\u0430\u0447\u0430. \u0412\u043e \u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043b\u0430\u0434\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 \u043a\u043e\u043c\u0438\u0442\u043e\u0432 &#8212; \u0441\u0434\u0435\u043b\u0430\u043b\u0438, \u0432\u043e \u0432\u0442\u043e\u0440\u044b\u0445 semver \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 1 \u044f\u0437\u044b\u043a\u0430, \u043d\u0435 \u043f\u043e\u0440\u044f\u0434\u043e\u043a<\/p>\n<p>\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441 &#171;\u0421\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435\u043c \u043e \u043a\u043e\u043c\u0438\u0442\u0430\u0445&#187; \u0438 \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 CI \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u043a-\u0442\u043e \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d \u043d\u0430\u0448\u0438\u043c, \u0442\u043e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c(\u043b\u0438\u0431\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c)<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.conventionalcommits.org\/ru\/v1.0.0-beta.4\/\" rel=\"noopener noreferrer nofollow\">IT CRINGE<\/a> P.S \u041b\u0443\u0447\u0448\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c &#8212; \u0442\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043d\u043e \u043a\u043e\u043c\u0443 \u043a\u0430\u043a \u0441 \u044f\u0437\u044b\u043a\u043e\u043c<\/p>\n<\/li>\n<\/ul>\n<h3>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0442\u0435\u0433\u0430<\/h3>\n<pre><code class=\"yaml\">#templates\/release\/analyze_commit.yaml variables:   MAJOR_CHANGE_PATTERN: 'BREAKING\\sCHANGE:'   MINOR_CHANGE_PATTERN: '^feat(\\(.*\\))?!?:\\s'   PATCH_CHANGE_PATTERN: '^(fix|perf|refactor)(\\(.*\\))?!?:\\s'   RELEASE_NOTE_FILE: \"RELEASE_NOTE.md\"   CHANGES_PATTERN: '^(feat|fix|docs|style|refactor|perf|test|chore|wip)(\\(.*\\))?(!)?:\\s?.+$'  stages:   - prepare_release    .generate_release_tag: &amp;generate_release_tag   - >-     if [ -z \"$LAST_TAG\" ]; then       echo \"No previous tag found, using the full commit history.\"       COMMITS=$(git log --oneline)     else       echo \"Analyzing commits since $LAST_TAG...\"       COMMITS=$(git log --oneline $LAST_TAG..$CI_COMMIT_SHA)     fi    - echo \"Commits to analyze ${COMMITS}\"    - VERSION_CHANGE=\"\"   - >-     if echo \"$COMMITS\" | grep -qE \"$MAJOR_CHANGE_PATTERN\"; then       VERSION_CHANGE=\"major\"     elif echo \"$COMMITS\" | grep -qE \"$MINOR_CHANGE_PATTERN\"; then       VERSION_CHANGE=\"minor\"     elif echo \"$COMMITS\" | grep -qE \"$PATCH_CHANGE_PATTERN\"; then       VERSION_CHANGE=\"patch\"     fi   - echo \"Change type defined $VERSION_CHANGE\"    - >-     if echo \"$LAST_TAG\" | grep -E \"^v[0-9]+\\.[0-9]+\\.[0-9]+$\" >\/dev\/null; then       echo \"Valid previous tag found: $LAST_TAG\"       MAJOR=$(echo \"$LAST_TAG\" | cut -d 'v' -f 2 | cut -d '.' -f 1)       MINOR=$(echo \"$LAST_TAG\" | cut -d '.' -f 2)       PATCH=$(echo \"$LAST_TAG\" | cut -d '.' -f 3)         else       echo \"No valid previous tag found or format is incorrect. Starting from 1.0.0\"       MAJOR=1; MINOR=0; PATCH=0     fi    - >-     case \"$VERSION_CHANGE\" in     major)       MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;     minor)       MINOR=$((MINOR + 1)); PATCH=0 ;;     patch)       PATCH=$((PATCH + 1)) ;;     *)     echo \"No version change detected stopping the release.\" exit 0 ;;     esac    - NEW_TAG=\"v${MAJOR}.${MINOR}.${PATCH}\"   - echo \"New tag $NEW_TAG\"   - echo \"NEW_TAG=$NEW_TAG\" >> variables.env  .generate_release_note: &amp;generate_release_note   - >-     if [ -z \"$LAST_TAG\" ]; then       RANGE=\"\"     else       RANGE=\"$LAST_TAG..$CI_COMMIT_SHA\"     fi   - echo \"# Release Notes\" > \"$RELEASE_NOTE_FILE\"   - echo \"\" >> \"$RELEASE_NOTE_FILE\"   - |-     add_commit_to_release_note() {         commit_data=\"$1\"          commit_hash=$(echo \"$commit_data\" | sed -n '1p')         commit_author=$(echo \"$commit_data\" | sed -n '2p')         commit_date=$(echo \"$commit_data\" | sed -n '3p')          echo \"## Commit: $commit_hash\" >> \"$RELEASE_NOTE_FILE\"         echo \"**Author:** $commit_author\" >> \"$RELEASE_NOTE_FILE\"         echo \"\" >> \"$RELEASE_NOTE_FILE\"         echo \"**Date:** $commit_date\" >> \"$RELEASE_NOTE_FILE\"         echo \"\" >> \"$RELEASE_NOTE_FILE\"         echo \"**Updates:**\" >> \"$RELEASE_NOTE_FILE\"         echo \"\" >> \"$RELEASE_NOTE_FILE\"          messages=$(echo \"$commit_data\" | sed '1,3d')          IFS=$'\\n'         for message in $messages; do             if echo \"$message\" | grep -Eq \"$CHANGES_PATTERN\"; then                 echo \"- $message\" >> \"$RELEASE_NOTE_FILE\"             else                 echo \"> $message\" >> \"$RELEASE_NOTE_FILE\"             fi         done          echo \"\" >> \"$RELEASE_NOTE_FILE\"     }   - |-     process_git_log() {         range=\"$1\"         commit_data=\"\"          git log \"$range\" --pretty=format:\"%H%n%an &lt;%ae>%n%ad%n%B%n&lt;ENDCOMMIT>\" | while IFS= read -r line || [ -n \"$line\" ]; do             if [ \"$line\" = \"&lt;ENDCOMMIT>\" ]; then                 add_commit_to_release_note \"$(echo -e \"$commit_data\")\"                 commit_data=\"\"             else                 commit_data=\"${commit_data}${line}\\n\"             fi         done     }   - process_git_log \"$RANGE\"   analyze_commit:   image:     name: alpine\/git     entrypoint: [ '' ]   stage: prepare_release   script:     - apk add --no-cache curl jq     - echo \"Analyze commit...\"      - LAST_TAG=$(git describe --tags --abbrev=0 $(git rev-list --tags --max-count=1) 2>\/dev\/null || echo \"\")      - *generate_release_tag     - *generate_release_note   variables:     SHELL: '\/bin\/bash'   artifacts:     paths:       - $RELEASE_NOTE_FILE     reports:       dotenv: variables.env   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   when: on_success     - when: never <\/code><\/pre>\n<p>\u041d\u0443 \u0442\u0443\u0442 \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0446\u0435\u043b\u044c \u044d\u0442\u043e\u0439 \u0434\u0436\u043e\u0431\u044b &#8212; \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0438\u0442 \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0421\u0443\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0442\u043e\u043c, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0435\u0441\u0442\u044c fix:, perf:, refactor: \u0432 \u0442\u0435\u0445 \u043a\u043e\u043c\u043c\u0438\u0442\u0430\u0445, \u0447\u0442\u043e \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u043b\u0438 \u0432 main &#8212; \u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c PATCH \u0432\u0435\u0440\u0441\u0438\u044e. \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c feat: &#8212; \u0442\u043e \u0434\u0435\u043b\u0430\u0435\u043c MINOR \u0432\u0435\u0440\u0441\u0438\u044e, \u0430 \u0435\u0441\u043b\u0438 BREAKING CHANGE &#8212; \u0442\u043e \u043c\u0430\u0436\u043e\u0440\u043d\u0443\u044e. \u041b\u043e\u0433\u0438\u043a\u0430 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u0432\u0430\u043c \u0432\u043f\u043e\u043b\u043d\u0435 \u0433\u043e\u0434\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442\u0435\u0440 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e Release Note, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043a\u0430 \u0437\u0430 \u0433\u043b\u0430\u0437\u0430 \u0438 \u0447\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043a\u0430\u043a \u0438 \u0434\u043b\u044f \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>\u041f\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0443 \u043d\u0430\u0441 \u043d\u0430 \u0442\u0435\u0441\u0442\u0435, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043e\u043d\u0430 \u043f\u0440\u0435\u0442\u0435\u0440\u043f\u0438\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438\u043b\u0438 \u0432\u043e\u0432\u0441\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u0441\u044f, \u043d\u043e \u043f\u043e\u043a\u0430 \u0442\u0430\u043a. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0437\u0436\u0435 \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u044e, \u043d\u043e <s>\u0436\u0435\u043b\u0430\u043d\u0438\u044f<\/s> \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0435\u0442.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0436\u043e\u0431\u044b \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0440\u0442\u0438\u0444\u0430\u043a\u0442, \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439, \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0432\u0430\u0436\u043d\u043e\u0439 \u0434\u0436\u043e\u0431\u044b.<\/p>\n<h3>\u0420\u0435\u043b\u0438\u0437<\/h3>\n<pre><code class=\"yaml\">#templates\/release\/release.yaml include:   - local: templates\/release\/analyze_commit.yaml  stages:   - prepare_release   - release  release:   stage: release   needs:     - job: analyze_commit       artifacts: true   image: registry.gitlab.com\/gitlab-org\/release-cli:latest   script:     - echo \"Release with tag $NEW_TAG\"   release:     name: 'Release $NEW_TAG'     tag_name: '$NEW_TAG'     description: RELEASE_NOTE.md     ref: '$CI_COMMIT_SHA'     assets:       links:         - name: \"GitLab Registry Image\"           url: \"https:\/\/$CI_REGISTRY_IMAGE:$NEW_TAG\"   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   when: manual     - when: never <\/code><\/pre>\n<p>\u0422\u0443\u0442 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0430\u0440\u0442\u0438\u0444\u0430\u043a\u0442 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0434\u0436\u043e\u0431\u044b \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u0435\u0433\u0430 \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e Release Note. \u0414\u0436\u043e\u0431\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f &#8212; \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0440\u0435\u043b\u0438\u0437. \u0427\u0442\u043e \u0435\u0449\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c?<\/p>\n<p>\u041f\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430\u043c:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/user\/project\/releases\/\" rel=\"noopener noreferrer nofollow\">Linkedin<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/user\/project\/releases\/release_cicd_examples.html\" rel=\"noopener noreferrer nofollow\">\u041a\u0440\u0435\u0434\u0438\u0442\u043a\u0430 \u043e\u0442 \u0422\u0438\u043d\u044c\u043a\u043e\u0444\u0444 \u0411\u0430\u043d\u043a\u0430<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0449\u0435\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 &#8212; \u0441\u0443\u043f\u0435\u0440 \u043c\u0435\u0433\u0430 \u0432\u0430\u0436\u043d\u043e \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f. \u0412\u0441\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u043e\u0441\u044c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 CI \u043d\u0430 \u0432\u0435\u0442\u043a\u0438, \u0441\u0430\u043c \u0440\u0435\u043b\u0438\u0437 \u0442\u043e\u0436\u0435 \u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0442\u0435\u0433 &#8212; \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0437\u0430\u0432\u0435\u0442\u043d\u044b\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c. \u0427\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0432 \u0442\u0430\u043a\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0435 &#8212; \u0441 \u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u0438\u043b\u0434\u0430 \u0434\u043e \u0440\u0435\u043b\u0438\u0437\u0430 &#8212; \u044d\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u0440\u0435\u043b\u0438\u0437\u0443(\u043d\u0435 \u043a\u0430\u043a \u0434\u0436\u043e\u0431\u0435) &#8212; \u043a\u0430\u043a \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438 \u043a prod \u0441\u0440\u0435\u0434\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0442\u0435\u0433, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e, \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c\u0441\u044f, \u043e\u043f\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0438 \u0436\u0435 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0432 HELM \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0447\u0442\u043e \u0435\u0449\u0435. \u041c\u044b \u043f\u043e\u043a\u0430 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0430\u043c\u043e\u0433\u043e \u0434\u0435\u043f\u043b\u043e\u044f \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u0435\u043c, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c.<\/p>\n<h3>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437\u043e\u0432<\/h3>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0442\u0435\u0433 \u0441\u043e\u0437\u0434\u0430\u043b\u0441\u044f &#8212; \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0436\u043e\u0431\u044b, \u0447\u0442\u043e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044f\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u0433 &#8212; \u043c\u043e\u0433\u0443\u0442 \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0443. \u0422\u0430\u043a \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c 2 \u0441\u0442\u0430\u0434\u0438\u0438 &#8212; \u0434\u043e \u0440\u0435\u043b\u0438\u0437\u0430 \u0438 \u043f\u043e\u0441\u043b\u0435.<\/p>\n<pre><code class=\"yaml\"># templates\/publish\/docker.yaml  stages:   - prepare_publish   - publish      publish_latest:   stage: prepare_publish   script:     - echo \"Tagging image $CI_COMMIT_SHA as latest...\"     - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest     - docker push $CI_REGISTRY_IMAGE:latest   rules:     - if: $CI_COMMIT_TAG       when: on_success     - when: never  publish_release_tag:   stage: prepare_publish   script:     - echo \"Tagging image $CI_COMMIT_SHA as $CI_COMMIT_TAG...\"     - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG     - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG   rules:     - if: $CI_COMMIT_TAG       when: on_success     - when: never  publish_stable:   stage: publish   script:     - echo \"Tagging image $CI_COMMIT_SHA as stable...\"     - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:stable     - docker push $CI_REGISTRY_IMAGE:stable   rules:     - if: $CI_COMMIT_TAG       when: on_success     - when: never <\/code><\/pre>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u0431\u044b \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0437 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0441\u043f\u0438\u043b\u0438\u043c \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u0442\u0435\u0433\u0430\u043c &#8212; \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c latest &#8212; \u043e\u043d \u0432\u0441\u0435 \u0442\u0430\u043a\u0438 dev \u043f\u0440\u043e\u0448\u0435\u043b \u0438 \u043c\u044b \u0435\u0433\u043e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u043b\u0438. \u041f\u043e\u0437\u0436\u0435 \u0441\u0430\u043c \u0442\u0435\u0433 &#8212; \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437. \u041c\u043e\u043c\u0435\u043d\u0442 \u0441 stable \u043f\u043e\u043a\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u0435 &#8212; \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0444\u0438\u043d\u0430\u043b\u043e\u043c.<\/p>\n<h3>\u041a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0434\u0435\u043f\u043b\u043e\u0439<\/h3>\n<pre><code class=\"yaml\"># templates\/deploy\/kubernetes.yaml ...  deploy-dev:   extends: .deploy-k8s-template   environment:     name: dev     action: start     kubernetes:       namespace: dev  deploy-prod:   extends: .deploy-k8s-template   variables:     DOCKER_TAG: $CI_COMMIT_TAG   rules:     - if: $CI_COMMIT_TAG       when: manual     - when: never   environment:     name: prod     action: start     kubernetes:       namespace: prod  <\/code><\/pre>\n<p>\u0412\u043e\u0442 \u0442\u0443\u0442 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441 \u0441 \u0434\u0435\u043f\u043b\u043e\u0435\u043c \u0432 \u043f\u0440\u043e\u0434 &#8212; \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u043b\u0438\u0437\u0430 \u0438 \u0438\u043c\u0435\u0435\u0442 \u0442\u0435\u0433 \u0441\u0438\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439. \u0422\u0430\u043a\u0436\u0435 \u0447\u0443\u0442\u044c \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412\u043e\u0442 \u043c\u044b \u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u0435\u043f\u043b\u043e\u0439. \u0412\u0441\u0435\u043c peace \u0438 \u0443\u0441\u043f\u0435\u0445\u043e\u0432.<\/p>\n<h2>\u0415\u0449\u0435 \u043d\u0435 \u0432\u0441\u0435?<\/h2>\n<p>\u0423\u0436 \u0431\u043e\u043b\u044c\u043d\u043e \u044f \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0439\u043d\u044b\u0439 \u0447\u0435\u043b\u043e\u0432\u0435\u043a. \u041c\u043d\u0435 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0438\u0437 \u0432\u0441\u0435\u0433\u043e \u0432\u044b\u0448\u0435\u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0439, \u0447\u0442\u043e \u044f \u0437\u0430\u0432\u0442\u0440\u0430 \u043f\u043e\u043c\u0435\u043d\u044f\u044e \u0447\u0442\u043e-\u0442\u043e \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u0445 \u0438 \u0432\u0441\u0435 \u043d\u0435 \u043f\u043e\u0441\u044b\u043f\u0435\u0442\u0441\u044f. \u041f\u043e \u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u044c\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u044e \u044f \u0440\u0435\u0448\u0438\u043b <s>\u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445<\/s> \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u0434\u0435\u043b\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u0430\u0441\u043f\u0435\u043a\u0442\u0443 \u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043d\u0430\u0448 CI \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<pre><code class=\"yaml\"># .gitlab-ci.yml include:   - local: \"templates\/release\/release.yaml\"  variables:   GITLAB_CI_LINT_API_URL: \"${CI_API_V4_URL}\/projects\/${CI_PROJECT_ID}\/ci\/lint\"   PRIVATE_TOKEN: $GITLAB_ACCESS_TOKEN   TEMPLATES_FILE: templates  stages:   - lint   - prepare_release   - release  validate_templates:   stage: lint   image: alpine:3.19   rules:     - if: $CI_COMMIT_BRANCH       when: always   before_script:     - apk add --no-cache curl jq   script:     - |       find $TEMPLATES_FILE -type f \\( -name '*.yml' -o -name '*.yaml' \\) -print0 | while IFS= read -r -d $'\\0' file; do         printf \"Validating %s\\n\" \"${file}\"                yaml_content=$(cat \"${file}\")         data=$(jq --null-input --arg yaml \"$yaml_content\" '. | {content: $yaml}')         response=$(curl \"${GITLAB_CI_LINT_API_URL}\" \\               --header \"PRIVATE-TOKEN: ${PRIVATE_TOKEN}\" \\               --header \"Content-Type: application\/json\" \\               --data \"$data\" -s)                valid=$(printf \"%s\" \"$response\" | jq --raw-output '.valid')                if [ \"$valid\" != true ]; then           printf \"Validation failed for %s:\\n\" \"${file}\"           printf \"%s\" \"$response\" | jq -r '.errors[]'           exit 1         else           printf \"Validation successful for %s\\n\" \"${file}\"         fi                warnings=$(printf \"%s\" \"$response\" | jq '.warnings | length')         if [ \"$warnings\" -ne 0 ]; then           printf \"Warnings for %s:\\n\" \"${file}\"           printf \"%s\" \"$response\" | jq -r '.warnings[]'         fi                printf \"\\n\"       done  analyze_commit:   needs: [ ]   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: on_success  release:   needs:     - job: validate_templates     - job: analyze_commit   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: on_success <\/code><\/pre>\n<p>\u041f\u043e\u0435\u0445\u0430\u043b\u0438 \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u0422\u0430\u043a\u0430\u044f \u0444\u0438\u0447\u0430, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e CI \u0438 \u043d\u0435 \u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0435 \u0431\u0435\u0437 \u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e &#8212; \u0435\u0441\u043b\u0438 CI \u043e\u0434\u043d\u0430\u0436\u0434\u044b \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043f\u043e\u043b\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 &#8212; \u0437\u043d\u0430\u0447\u0438\u0442 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0435\u0447\u043d\u043e.<\/p>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e<\/p>\n<p>\u0412\u043e \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0430, \u0432\u0438\u0434\u0438\u043c \u0441\u0442\u0440\u0430\u043d\u043d\u0443\u044e \u0434\u0436\u043e\u0431\u0443 \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u044d\u0442\u0430\u043f\u0435 &#8212; lint. \u041a\u043e\u0440\u043e\u0442\u043a\u043e \u043e\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0432\u0441\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 \u043f\u0430\u043f\u043a\u0435 \u0441 \u0442\u0435\u043c\u043f\u043b\u0435\u0439\u0442\u0430\u043c\u0438. \u0422\u043e \u0435\u0441\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0432\u044b\u0448\u0435 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 &#8212; \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0430\u043c Gitlab, \u043b\u0438\u0431\u043e \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u043d\u0430\u0448\u0435\u043b(\u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b\u0438\u043a \u043d\u0435 .gitlab-ci.yml &#8212; \u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0439 \u0438 \u043d\u0435 \u0441\u043a\u0440\u0438\u043f\u0442 \u0432\u043e\u0432\u0441\u0435 &#8212; \u0435\u0433\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f). \u0424\u043e\u0440\u043c\u0443\u043b\u0430 \u0442\u0430 \u0436\u0435 &#8212; \u0447\u0442\u043e \u0438 \u0432 Pipeline Editor(\u043a\u0430\u043a \u044f \u043f\u043e\u043d\u044f\u043b).<\/p>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0434\u0436\u043e\u0431\u044b \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0438 \u0440\u0435\u043b\u0438\u0437\u0430 &#8212; \u0432 \u0446\u0435\u043b\u043e\u043c \u0432\u0441\u0435.<\/p>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0438\u043c\u043f\u043e\u0440\u0442 \u0432 \u0432\u0430\u0448\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"yaml\">include:     - project: 'devops\/ci-cd-includes'       file: '\/templates\/build\/kaniko.yaml'       ref: 'v1.7.0'     - project: 'devops\/ci-cd-includes'       file: 'templates\/deploy\/helm.yaml'       ref: 'v1.7.0' <\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0442\u043e\u0447\u043d\u043e \u043a\u043e\u043d\u0435\u0446, \u043a\u043b\u0430\u043d\u044f\u044e\u0441\u044c.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/5d3\/6a3\/872\/5d36a3872eb2cc3246324c8c92e49b5d.jpeg\" alt=\"\u041a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043d\u0430\u0433\u043b\u043e \u0441\u0432\u043e\u0440\u043e\u0432\u0430\u043d\u0430\" title=\"\u041a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043d\u0430\u0433\u043b\u043e \u0441\u0432\u043e\u0440\u043e\u0432\u0430\u043d\u0430\" width=\"1496\" height=\"974\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5d3\/6a3\/872\/5d36a3872eb2cc3246324c8c92e49b5d.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption><a href=\"https:\/\/habr.com\/ru\/companies\/jugru\/articles\/527110\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043d\u0430\u0433\u043b\u043e \u0441\u0432\u043e\u0440\u043e\u0432\u0430\u043d\u0430<\/a><\/figcaption><\/div>\n<\/figure>\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\/798551\/\"> https:\/\/habr.com\/ru\/articles\/798551\/<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440. \u042d\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f, \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u043d\u0430 \u0444\u0438\u0434\u0431\u0435\u043a \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f \u043e\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u044b\u0445 \u043b\u044e\u0434\u0435\u0439 \u0432 \u0441\u0444\u0435\u0440\u0443 \u0441\u0442\u0430\u0442\u044c\u0438, \u0434\u0430 \u0438 \u0432 \u0446\u0435\u043b\u043e\u043c \u0432 IT. \u042f \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0447\u0442\u043e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c\u0438 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u044e \u043d\u0430 \u0438\u0441\u0442\u0438\u043d\u0443 \u0438 \u0443\u0436 \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043d\u0435 \u0443\u0447\u0443 \u043a\u043e\u0433\u043e-\u0442\u043e \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u0414\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u0445\u043e\u0447\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u043c, \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430 &#8212; \u0447\u0442\u043e \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0438 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u0445\u043e\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445\u00a0\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0441\u0432\u043e\u0435\u043c \u043e\u043f\u044b\u0442\u0435 \u0438 \u043a \u0447\u0435\u043c\u0443 \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438. \u041d\u0443 \u0438 \u0432\u0441\u0435 \u0448\u0443\u0442\u043a\u0438 \u043f\u0440\u043e \u043b\u0443\u0447\u0448\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u044b &#8212; \u044d\u0442\u043e \u0432\u0441\u0435 \u0448\u0443\u0442\u043a\u0438, \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0443\u0436\u0435 1000 Best Practices \u0438\u0437 10 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438, \u0442\u0430\u043a \u0447\u0442\u043e \u0436\u0434\u0443 \u0438 \u0432\u0430\u0441 \u0442\u0430\u043c.<\/p>\n<h2>\u041a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a CI\/CD?<\/h2>\n<p>\u042f \u043f\u0440\u0438\u0448\u0435\u043b \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e, \u0443\u0436\u0435 2 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 IT \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435.\u00a0\u041f\u043e \u043d\u0430\u0447\u0430\u043b\u0443 &#8212; \u044d\u0442\u043e GitHub + Vercel(\u0434\u0430-\u0434\u0430, \u0438 \u0444\u0440\u043e\u043d\u0442 \u0438 \u0431\u0435\u043a \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 1 \u043f\u0440\u043e\u0435\u043a\u0442\u0430), \u043f\u043e\u0437\u0436\u0435 \u043d\u043e\u0432\u044b\u0439 \u0431\u0435\u043a, \u043d\u043e\u0432\u044b\u0439 \u0444\u0440\u043e\u043d\u0442 &#8212; \u0443\u0436\u0435 \u0434\u0432\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 &#8212; SSH, \u0440\u0443\u0447\u043a\u0430\u043c\u0438 git pull, nginx &#8212; \u0433\u0434\u0435-\u0442\u043e \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0430\u0445. \u041d\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u044f \u0431\u044b\u043b \u0440\u0430\u0434 &#8212; \u0438\u0431\u043e \u0443\u0436\u0435 \u043d\u0430 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u0447\u0442\u043e \u0432 Docker \u0441\u0438\u043b\u0430, \u043d\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u0430\u0443\u0442\u0441\u043e\u0440\u0441\u0435\u0440\u044b. \u041f\u043e\u0437\u0436\u0435 \u0440\u043e\u0441\u0442, \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439, \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 GitLab, \u043f\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0448\u0442\u0430\u0442\u0430 &#8212; \u043d\u0443\u0436\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c. \u041a\u0430\u043a \u0438 \u043b\u044e\u0431\u0430\u044f \u0434\u0440\u0443\u0433\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f &#8212; \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043c \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u043d\u0443\u0436\u0435\u043d \u0430\u0432\u0442\u043e\u0434\u0435\u043f\u043b\u043e\u0439. \u041d\u0430 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u0443\u0431\u0435\u0440.<\/p>\n<h2>\u041d\u0430\u0448\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0432 CI\/CD<\/h2>\n<p>\u0427\u0442\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c? \u041d\u0443 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e &#8212; \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.<\/p>\n<p>P.S. \u0421\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043d\u0430\u0448\u0435\u043b \u0441\u0435\u0431\u044f \u0432 \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u044f\u043d\u0434\u0435\u043a\u0441\u0430 &#8212; \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u0432\u0441\u0435\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f.<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/tutorials\/infrastructure-management\/gitlab-containers\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043d\u0430\u043b \u0425\u0430\u0443\u0434\u0438 \u0425\u043e<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/tutorials\/serverless\/ci-cd-serverless\" rel=\"noopener noreferrer nofollow\">\u042f\u043d\u0434\u0435\u043a\u0441 \u041f\u0440\u0430\u043a\u0442\u0438\u043a\u0443\u043c<\/a><\/p>\n<\/li>\n<\/ul>\n<p>P.P.S. \u041d\u0443 \u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u0441\u0435-\u0432\u0441\u0435-\u0432\u0441\u0435 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 gitlab \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0432\u044b\u0443\u0447\u0438\u0442\u044c &#8212; \u043d\u0435 \u0437\u0440\u044f \u043f\u0438\u0441\u0430\u043b\u0438.<\/p>\n<h3>\u0411\u0438\u043b\u0434<\/h3>\n<p>\u0421 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u044b\u043c \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0431\u0438\u043b\u0434(\u043d\u0443 \u043f\u043e\u0447\u0442\u0438) &#8212; \u0435\u0433\u043e \u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c. \u041a\u0430\u043a \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u043b \u0432\u044b\u0448\u0435 &#8212; Docker \u044d\u0442\u043e \u043c\u043e\u0449\u044c, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u044b \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u043d\u0435\u0434\u0440\u0438\u043b\u0438 \u0435\u0433\u043e \u0432 \u043d\u0430\u0448 \u043f\u0440\u043e\u0434\u0443\u043a\u0442. \u041d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 Dockerfile&#8217;\u044b &#8212; \u043f\u0438\u0448\u0435\u043c \u043d\u0430\u0448 CI:<\/p>\n<pre><code class=\"yaml\"># templates\/build\/kaniko.yaml variables:   TAG: $CI_COMMIT_SHA   DOCKERFILE: $CI_PROJECT_DIR\/Dockerfile   ARGUMENTS: \"\"  build-kaniko:   stage: build   image:     name: gcr.io\/kaniko-project\/executor:v1.21.0-debug     entrypoint: [ \"\" ]   script:     - echo \"Build with tag $TAG\"     - mkdir -p \/kaniko\/.docker     - echo \"{\\\"auths\\\":{\\\"${CI_REGISTRY}\\\":{\\\"auth\\\":\\\"$(printf \"%s:%s\" \"${CI_REGISTRY_USER}\" \"${CI_REGISTRY_PASSWORD}\" | base64 | tr -d '\\n')\\\"},\\\"$(echo -n $CI_DEPENDENCY_PROXY_SERVER | awk -F[:] '{print $1}')\\\":{\\\"auth\\\":\\\"$(printf \"%s:%s\" ${CI_DEPENDENCY_PROXY_USER} \"${CI_DEPENDENCY_PROXY_PASSWORD}\" | base64 | tr -d '\\n')\\\"}}}\" > \/kaniko\/.docker\/config.json     - echo \"Run this build ${CI_REGISTRY_IMAGE}-${CI_ENVIRONMENT_NAME}\"     - >-       \/kaniko\/executor       --context $CI_PROJECT_DIR       --dockerfile $DOCKERFILE       --destination $CI_REGISTRY_IMAGE:$TAG       --cache=true       $ARGUMENTS   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: on_success     - when: never <\/code><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0443\u0442 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f? \u041d\u0443 \u0432\u043e \u043f\u0435\u0440\u0432\u044b\u0445 &#8212; \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0442\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043e\u0431\u0440\u0430\u0437\u044b \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u0445 \u0432 Registry &#8212; \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0448 \u0431\u0438\u043b\u0434 \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u044b \u0441 \u0442\u0435\u0433\u043e\u043c $CI_COMMIT_SHA &#8212; \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0438\u043c\u0435\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0435\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u043a\u043e\u043c\u0438\u0442\u0443 &#8212; \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0434\u043d\u043e \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0435, \u043c\u0435\u043b\u043e\u0447\u044c, \u0430 \u043f\u0440\u0438\u044f\u0442\u043d\u043e. \u0422\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c &#8212; \u0447\u0442\u043e \u0431\u0438\u043b\u0434 \u0432\u0441\u0435\u0433\u043e 1.<\/p>\n<p>\u041f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 Registry:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/administration\/packages\/container_registry.html#configure-s3-and-gcs-storage-drivers-for-linux-package-installations\" rel=\"noopener noreferrer nofollow\">\u041e\u043d\u043b\u0430\u0439\u043d \u043f\u043b\u043e\u0449\u0430\u0434\u043a\u0430 SkillBox<\/a><\/p>\n<\/li>\n<\/ul>\n<h3>\u0414\u0435\u043f\u043b\u043e\u0439<\/h3>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e \u043a\u0443\u0431\u0435\u0440, \u043c\u044b \u0436\u0435 \u0445\u043e\u0442\u0438\u043c \u0434\u0435\u043f\u043b\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c &#8212; \u0432\u0435\u0440\u043d\u043e?<\/p>\n<pre><code class=\"yaml\"># templates\/deploy\/kubernetes.yaml variables:   DOCKER_IMAGE: $CI_REGISTRY_IMAGE   DOCKER_TAG: $CI_COMMIT_SHA   DEPLOYMENT_DATE: `date +%Y%m%d-%H-%M-%S`   MANIFEST_FOLDER: \"k8s\"   KUBECONFIG: \"\"   deploy-k8s:   stage: deploy   image:     name: alpine:3.19   script:     - apk update &amp;&amp; apk add gettext     - wget https:\/\/storage.googleapis.com\/kubernetes-release\/release\/v1.26.0\/bin\/linux\/amd64\/kubectl     - chmod +x .\/kubectl     - .\/kubectl create secret docker-registry regcred --docker-server=$CI_REGISTRY --docker-username=$CI_DEPLOY_USER --docker-password=$CI_DEPLOY_PASSWORD -n $CI_ENVIRONMENT_NAME || true     - >-        for MANIFEST in $MANIFEST_FOLDER\/*; do         envsubst &lt; $MANIFEST | .\/kubectl apply -n $CI_ENVIRONMENT_NAME -f -;       done   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: on_success     - when: never  <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0431\u0435\u0436\u0438\u043c\u0441\u044f \u043f\u043e \u0432\u0430\u0436\u043d\u043e\u043c\u0443. DOCKER_IMAGE \u0438 DOCKER_TAG \u0443 \u043d\u0430\u0441 \u0432 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0435 \u0434\u0435\u043f\u043b\u043e\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u044b, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e envsubst \u043c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430 \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f \u0435\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u0443\u0431\u0435\u0440. KUBECONFIG \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 CI\/CD > Variables, \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0444\u0430\u0439\u043b\u0430. \u0422\u0430\u043a\u0436\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u043a\u0430\u0437\u0430\u0442\u044c &#8212; \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u043a\u0443\u0431\u0435\u0440, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 &#8212; \u0447\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0432 \u0435\u043d\u0432\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c(\u043b\u0438\u0431\u043e \u0432 variables \u0432 gitlab-ci \u043f\u0440\u043e\u0435\u043a\u0442\u0430).<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044f \u0441\u043e\u0437\u0434\u0430\u044e \u0441\u0435\u043a\u0440\u0435\u0442 regcred &#8212; \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043a\u0440\u0435\u0434\u044b \u0434\u043b\u044f registry.<\/p>\n<p>\u041f\u043e regcred \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/pull-image-private-registry\/\" rel=\"noopener noreferrer nofollow\">\u042f\u042e\u043d\u0438\u043e\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/user\/packages\/container_registry\/authenticate_with_container_registry.html\" rel=\"noopener noreferrer nofollow\">\u042f\u043d\u0434\u0435\u043a\u0441 \u041c\u0435\u0442\u0440\u0438\u043a\u0430<\/a><\/p>\n<\/li>\n<\/ul>\n<h2>\u0410 \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/h2>\n<p>\u0412\u043e\u0442 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0434\u0435\u043f\u043b\u043e\u0439. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 &#8212; \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0436\u0435\u043b\u0430\u043d\u0438\u0435, \u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u043c <s>\u0431\u0435\u0437\u0434\u0443\u043c\u043d\u043e<\/s> \u0432\u0441\u0435 \u0432 \u043f\u0440\u043e\u0434 \u043f\u0438\u0445\u0430\u0442\u044c. \u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u043a\u043e\u043b\u044c\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0431\u0438\u0437\u043d\u0435\u0441 \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u044b\u043a\u0430\u0442\u044c \u0432\u0441\u0435 \u0440\u0443\u0447\u043a\u0430\u043c\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0430\u043b\u043e \u043d\u0430 dev \u0438 prod \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 &#8212; \u0433\u0434\u0435 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0443\u0448\u0438\u0442\u0441\u044f \u0432\u0441\u0435 \u0432 dev, \u043f\u043e\u0437\u0436\u0435 \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0432\u0441\u0435 \u043e\u043a &#8212; \u043b\u0435\u0442\u0438\u0442 \u0432 prod.<\/p>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0431\u044b\u043b\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f. \u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u043c 2 \u0432\u0435\u0442\u043a\u0438, stable \u0438 main(\u0443 \u043d\u0430\u0441 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 dev), CI \u0434\u043b\u044f main &#8212; \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0439 \u0431\u0438\u043b\u0434, \u043e\u0442\u043f\u0440\u0430\u0432\u044c \u043d\u0430 dev, CI \u0434\u043b\u044f stable &#8212; \u0441\u043e\u0437\u0434\u0430\u0439 \u0431\u0438\u043b\u0434, \u043e\u0442\u043f\u0440\u0430\u0432\u044c \u043d\u0430 prod. \u0411\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0430\u043b\u043e \u044f\u0441\u043d\u043e, \u0447\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u044d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043a\u0435\u0439\u0441. \u0414\u043e\u043b\u0433\u043e \u0437\u0430\u043e\u0441\u0442\u0440\u044f\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443, \u043a\u043e\u0440\u043e\u0442\u043a\u043e \u0441\u043a\u0430\u0436\u0443 &#8212; \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0437, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430 dev != \u043e\u0431\u0440\u0430\u0437 \u043d\u0430 prod, \u0430 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043d\u0435 \u0443\u043c\u043d\u044b\u0439 \u0447\u0435\u043b\u043e\u0432\u0435\u043a~~(\u044f)~~ \u0437\u0430\u043f\u0443\u0448\u0438\u0442 \u043d\u0430 stable \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e? \u0412 \u043e\u0431\u0449\u0435\u043c \u043e\u0442 \u0438\u0434\u0435\u0438 \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c, \u043f\u043e\u0448\u043b\u0438 \u0434\u0443\u043c\u0430\u0442\u044c.<br \/> \u0412\u044b\u0445\u043e\u0434 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430\u0448\u043b\u0438 \u043d\u0435 \u0431\u044b\u0441\u0442\u0440\u043e, \u0432 \u0433\u043e\u043b\u043e\u0432\u0435 \u0442\u043e \u0438 \u043a\u0440\u0443\u0442\u0438\u043b\u0430\u0441\u044c \u0444\u0440\u0430\u0437\u0430 &#171;\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f. \u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0430&#187;. \u0410 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u043e\u0442 \u0436\u0435 \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 CI \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0442\u044c? \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u0448\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<h3>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445<\/h3>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u0438\u0441\u044c \u043e\u0442 2\u0445 \u0431\u0438\u043b\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0435\u043d\u0432\u043e\u0432. \u0422\u0435\u043f\u0435\u0440\u044c 1 \u0431\u0438\u043b\u0434 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 dev, \u0430 \u043f\u043e\u0437\u0436\u0435 \u043e\u043d \u0436\u0435 \u043b\u0435\u0442\u0438\u0442 \u0432 prod &#8212; \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c 2 \u0440\u0430\u0437\u043d\u044b\u0445 \u0434\u0435\u043f\u043b\u043e\u044f \u0432 \u043a\u0443\u0431\u0435\u0440 &#8212; \u043e\u0434\u0438\u043d \u0434\u043b\u044f dev, \u0434\u0440\u0443\u0433\u043e\u0439 \u0434\u043b\u044f prod. \u041a\u0430\u043a?<\/p>\n<pre><code class=\"yaml\"># templates\/deploy\/kubernetes.yaml ...  .deploy-k8s-template:   stage: deploy   image:     name: alpine:3.19  ... <\/code><\/pre>\n<p>\u0414\u0430 \u0432 \u043e\u0431\u0449\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e, \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u0442\u043e\u0447\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u043d\u0430\u0448\u0435\u0439 \u0434\u0436\u043e\u0431\u044b, \u043d\u0443 \u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c \u0438 \u0438\u0437 \u043d\u0435\u0433\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 2 \u0434\u0436\u043e\u0431\u044b!<\/p>\n<pre><code class=\"yaml\"># templates\/deploy\/kubernetes.yaml ...  deploy-dev:   environment: dev   extends: .deploy-k8s-template  deploy-prod:   environment: prod   extends: .deploy-k8s-template   rules:     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       when: manual     - when: never     <\/code><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0443\u0442 \u0432\u0430\u0436\u043d\u043e? \u0414\u0430 \u0432 \u0446\u0435\u043b\u043e\u043c \u043e\u0441\u043e\u0431\u043e \u043d\u0438\u0447\u0435\u0433\u043e. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u0435\u043d\u044f\u0435\u043c environment &#8212; \u0442\u043e \u0435\u0441\u0442\u044c \u0442\u043e, \u0432 \u043a\u0430\u043a\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043d\u0430\u0448.<\/p>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/environments\/\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043d\u0430\u043b \u0413\u043e\u0448\u0430 \u0414\u0443\u0434\u0430\u0440\u044c<\/a><\/p>\n<\/li>\n<\/ul>\n<h2>\u0420\u0435\u043b\u0438\u0437?<\/h2>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u0441\u0435 &#8212; <s>\u0434\u0435\u043d\u044c\u0433\u0438, \u0442\u0430\u0447\u043a\u0438<\/s> \u0431\u0438\u043b\u0434, \u0434\u0435\u043f\u043b\u043e\u0439 \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u0440\u043e\u0441\u043b\u0430, \u043f\u043e\u044f\u0432\u043b\u044f\u043b\u043e\u0441\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043d\u0430\u0448 \u043c\u043e\u043d\u043e\u043b\u0438\u0442 \u043f\u043e\u0442\u0438\u0445\u043e\u043d\u044c\u043a\u0443 \u0440\u0430\u0441\u043f\u0438\u043b\u0438\u0432\u0430\u043b\u0441\u044f(\u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0447\u0435\u0440\u0435\u0437 \u043b\u0435\u0442 10 \u0440\u0430\u0441\u043f\u0438\u043b\u0438\u0442\u0441\u044f). \u0421\u0442\u0430\u043b\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0442\u044c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e &#8212; \u0447\u0442\u043e \u0437\u0430 \u0432\u0435\u0440\u0441\u0438\u044f. \u0410 \u043a\u0430\u043a \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c? \u0418\u0441\u043a\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u043c\u0438\u0442? \u041c\u043d\u043e\u0433\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0432\u043e\u0434\u044b \u0443\u0442\u0435\u043a\u043b\u043e \u0432 \u044d\u0442\u043e\u0442 \u043f\u0435\u0440\u0438\u043e\u0434 \u0438 \u0438\u0434\u0435\u044f \u0431\u044b\u043b\u0430 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0440\u0435\u043b\u0438\u0437\u043e\u0432 \u0438 \u0442\u0435\u0433\u043e\u0432. \u042f, \u043a\u0430\u043a \u043e\u0447\u0435\u043d\u044c \u043d\u0435 \u043b\u044e\u0431\u044f\u0449\u0438\u0439 \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0443\u043a\u0430\u043c\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0440\u0435\u0448\u0438\u043b \u044d\u0442\u043e \u0432\u0441\u0435 \u0434\u0435\u043b\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0427\u0442\u043e \u043d\u0430\u043c \u0434\u0435\u043b\u0430\u0442\u044c? \u041f\u043e\u043b\u0435\u0437\u043b\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442, \u043d\u0430\u0448\u043b\u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0442\u0430\u043c \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f, semver, \u043d\u043e \u0432\u043e\u0442 \u043d\u0435 \u0437\u0430\u0434\u0430\u0447\u0430. \u0412\u043e \u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043b\u0430\u0434\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 \u043a\u043e\u043c\u0438\u0442\u043e\u0432 &#8212; \u0441\u0434\u0435\u043b\u0430\u043b\u0438, \u0432\u043e \u0432\u0442\u043e\u0440\u044b\u0445 semver \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 1 \u044f\u0437\u044b\u043a\u0430, \u043d\u0435 \u043f\u043e\u0440\u044f\u0434\u043e\u043a<\/p>\n<p>\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441 &#171;\u0421\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435\u043c \u043e \u043a\u043e\u043c\u0438\u0442\u0430\u0445&#187; \u0438 \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 CI \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u043a-\u0442\u043e \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d \u043d\u0430\u0448\u0438\u043c, \u0442\u043e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c(\u043b\u0438\u0431\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c)<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.conventionalcommits.org\/ru\/v1.0.0-beta.4\/\" rel=\"noopener noreferrer nofollow\">IT CRINGE<\/a> P.S \u041b\u0443\u0447\u0448\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c &#8212; \u0442\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043d\u043e \u043a\u043e\u043c\u0443 \u043a\u0430\u043a \u0441 \u044f\u0437\u044b\u043a\u043e\u043c<\/p>\n<\/li>\n<\/ul>\n<h3>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0442\u0435\u0433\u0430<\/h3>\n<pre><code class=\"yaml\">#templates\/release\/analyze_commit.yaml variables:   MAJOR_CHANGE_PATTERN: 'BREAKING\\sCHANGE:'   MINOR_CHANGE_PATTERN: '^feat(\\(.*\\))?!?:\\s'   PATCH_CHANGE_PATTERN: '^(fix|perf|refactor)(\\(.*\\))?!?:\\s'   RELEASE_NOTE_FILE: \"RELEASE_NOTE.md\"   CHANGES_PATTERN: '^(feat|fix|docs|style|refactor|perf|test|chore|wip)(\\(.*\\))?(!)?:\\s?.+$'  stages:   - prepare_release    .generate_release_tag: &amp;generate_release_tag   - >-     if [ -z \"$LAST_TAG\" ]; then       echo \"No previous tag found, using the full commit history.\"       COMMITS=$(git log --oneline)     else       echo \"Analyzing commits since $LAST_TAG...\"       COMMITS=$(git log --oneline $LAST_TAG..$CI_COMMIT_SHA)     fi    - echo \"Commits to analyze ${COMMITS}\"    - VERSION_CHANGE=\"\"   - >-     if echo \"$COMMITS\" | grep -qE \"$MAJOR_CHANGE_PATTERN\"; then       VERSION_CHANGE=\"major\"     elif echo \"$COMMITS\" | grep -qE \"$MINOR_CHANGE_PATTERN\"; then       VERSION_CHANGE=\"minor\"     elif echo \"$COMMITS\" | grep -qE \"$PATCH_CHANGE_PATTERN\"; then       VERSION_CHANGE=\"patch\"     fi   - echo \"Change type defined $VERSION_CHANGE\"    - >-     if echo \"$LAST_TAG\" | grep -E \"^v[0-9]+\\.[0-9]+\\.[0-9]+$\" >\/dev\/null; then       echo \"Valid previous tag found: $LAST_TAG\"       MAJOR=$(echo \"$LAST_TAG\" | cut -d 'v' -f 2 | cut -d '.' -f 1)       MINOR=$(echo \"$LAST_TAG\" | cut -d '.' -f 2)       PATCH=$(echo \"$LAST_TAG\" | cut -d '.' -f 3)         else       echo \"No valid previous tag found or format is incorrect. Starting from 1.0.0\"       MAJOR=1; MINOR=0; PATCH=0     fi    - >-     case \"$VERSION_CHANGE\" in     major)       MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;     minor)       MINOR=$((MINOR + 1)); PATCH=0 ;;     patch)       PATCH=$((PATCH + 1)) ;;     *)     echo \"No version change detected stopping the release.\" exit 0 ;;     esac    - NEW_TAG=\"v${MAJOR}.${MINOR}.${PATCH}\"   - echo \"New tag $NEW_TAG\"   - echo \"NEW_TAG=$NEW_TAG\" >> variables.env  .generate_release_note: &amp;generate_release_note   - >-     if [ -z \"$LAST_TAG\" ]; then       RANGE=\"\"     else       RANGE=\"$LAST_TAG..$CI_COMMIT_SHA\"     fi   - echo \"# Release Notes\" > \"$RELEASE_NOTE_FILE\"   - echo \"\" >> \"$RELEASE_NOTE_FILE\"   - |-     add_commit_to_release_note() <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\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-370136","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370136","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=370136"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370136\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=370136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=370136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=370136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}