{"id":462020,"date":"2025-06-03T21:01:48","date_gmt":"2025-06-03T21:01:48","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=462020"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=462020","title":{"rendered":"<span>CI\/CD \u043d\u0430 GitHub Actions \u0438 GitLab CI \u0434\u043b\u044f \u0441\u0430\u043c\u044b\u0445 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445. \u0427\u0430\u0441\u0442\u044c 3<\/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<h4>\u0427\u0430\u0441\u0442\u044c3: CI\/CD \u2013 \u0432\u0435\u0442\u043a\u0438, \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h4>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0434\u043e\u0448\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0432 \u0441\u0435\u0440\u0438\u0438, \u0442\u043e \u0432\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c\u0438 CI\/CD \u0438 \u0434\u0430\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d. \u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u044e! \u0412\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u0430\u0436\u043d\u044b\u0439 \u0448\u0430\u0433 \u0432 \u043c\u0438\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041d\u043e \u043a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0433\u0434\u0435 \u043f\u043e\u0441\u043b\u0435 &#171;Hello World&#187; \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435, \u0432 CI\/CD \u043f\u043e\u0441\u043b\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u044b\u0439 \u043c\u0438\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439.<\/p>\n<blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043f\u0430\u043b\u0438 \u0441\u044e\u0434\u0430 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e, \u0438\u043b\u0438 \u043d\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0432\u0443\u0445 \u0447\u0430\u0441\u0442\u0435\u0439, \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f:<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/914560\/\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0430\u0441\u0442\u044c 1: \u041e\u0441\u043d\u043e\u0432\u044b CI\/CD \u2013 \u0447\u0442\u043e \u044d\u0442\u043e \u0438 \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u043e; GitHub Actions \u0438 GitLab CI<\/strong><\/a><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/914614\/\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0430\u0441\u0442\u044c 2: \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 GitHub Actions \u0438 GitLab CI \u2013 \u043f\u0435\u0440\u0432\u044b\u0439 workflow \u0438 \u0434\u0435\u043f\u043b\u043e\u0439<\/strong><\/a><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/915370\/\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0430\u0441\u0442\u044c3: CI\/CD \u2013 \u0432\u0435\u0442\u043a\u0438, \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/strong><\/a><\/p>\n<p><strong>^ \u0412\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0437\u0434\u0435\u0441\u044c ^<\/strong><\/p>\n<\/blockquote>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0430\u0448 CI\/CD \u043f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0433\u0438\u0431\u043a\u0438\u043c \u0438 \u043c\u043e\u0449\u043d\u044b\u043c. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c:<\/p>\n<ul>\n<li>\n<p><strong>\u0412\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/strong> \u2014 \u043a\u0430\u043a \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0432\u0435\u0441\u0442\u0438 \u0441\u0435\u0431\u044f \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0435\u0442\u043a\u0438 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/strong> \u2014 \u043a\u0430\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 \u044d\u0442\u0430\u043f\u044b<\/strong> \u2014 \u043a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0443\u043f\u0435\u043d\u0447\u0430\u0442\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0430\u043c\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0442\u043b\u0430\u0434\u043a\u0443 \u0438 \u0440\u0430\u0437\u0431\u043e\u0440 \u043e\u0448\u0438\u0431\u043e\u043a<\/strong> \u2014 \u043a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a, \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u0438 \u0442\u0435\u043c\u044b \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u044b \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0421\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0438, \u0430 \u043d\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0438\u0442. \u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043f\u0430\u0440\u043e\u043b\u0438 \u0438 \u0442\u043e\u043a\u0435\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043b\u044c\u0437\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0432\u0438\u0434\u0435. \u0410 \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u2014 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d.<\/p>\n<p>\u041d\u0435 \u0432\u043e\u043b\u043d\u0443\u0439\u0442\u0435\u0441\u044c, \u0435\u0441\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u043a\u0430\u0436\u0443\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438. \u041c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0432\u0441\u0451 \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e, \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c\u0438. \u041a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 CI\/CD-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0438\u0441\u0442\u0435\u0433\u043d\u0438\u0442\u0435 \u0440\u0435\u043c\u043d\u0438 \u2014 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u0432 \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u0435 \u043f\u043e \u043c\u0438\u0440\u0443 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0433\u043e CI\/CD, \u0433\u0434\u0435 \u0432\u0430\u0448 \u043a\u043e\u0434 \u0441\u0430\u043c \u0441\u0435\u0431\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u0442 \u0438 \u0434\u0435\u043f\u043b\u043e\u0438\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a, \u043a\u0430\u043a \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e. \u0418 \u043f\u043e\u043c\u043d\u0438\u0442\u0435: \u043c\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430\u0448 &#171;Hello World&#187; workflow \u0432\u043e \u0432\u0437\u0440\u043e\u0441\u043b\u0443\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445. <\/p>\n<h2>\u0412\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432 workflow<\/h2>\n<h3>\u041a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u044f \u0432 Git \u0438 CI\/CD<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043a\u043e\u0433\u0434\u0430-\u043d\u0438\u0431\u0443\u0434\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441 Git, \u0442\u043e \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0432\u0435\u0442\u043a\u0438 \u2014 \u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u0435\u0433\u043e \u0441\u0430\u043c\u044b\u0445 \u043c\u043e\u0449\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439. \u041e\u043d\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0434 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438, \u043d\u0435 \u043c\u0435\u0448\u0430\u044f \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443. \u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0432\u0435\u0442\u043e\u043a \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><code>main<\/code> (\u0438\u043b\u0438 <code>master<\/code>) \u2014 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f, \u0433\u043e\u0442\u043e\u0432\u0430\u044f \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e<\/p>\n<\/li>\n<li>\n<p><code>develop<\/code> \u2014 \u0432\u0435\u0442\u043a\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u0443\u0434\u0430 \u0441\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>feature\/*<\/code> \u2014 \u0432\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><code>hotfix\/*<\/code> \u2014 \u0441\u0440\u043e\u0447\u043d\u044b\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a<\/p>\n<\/li>\n<li>\n<p><code>release\/*<\/code> \u2014 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u0432\u044b\u043f\u0443\u0441\u043a\u0443 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u043e \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u0434\u043b\u044f CI\/CD? \u0410 \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0432\u0435\u0442\u043a\u0438 \u0440\u0430\u0432\u043d\u044b! \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u0430\u0433\u0430\u0437\u0438\u043d \u043e\u0434\u0435\u0436\u0434\u044b. \u0412\u044b \u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u0436\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u043d\u0435\u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0439 \u044d\u0441\u043a\u0438\u0437 \u043e\u0442 \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u0430? \u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043c\u0438\u0442 \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0442\u043a\u0438.<\/p>\n<p>\u0412\u043e\u0442 \u0433\u0434\u0435 \u043d\u0430 \u0441\u0446\u0435\u043d\u0443 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 <strong>\u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/strong> \u0432 CI\/CD. \u041e\u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0435\u0442\u043a\u0438 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u0439:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043e\u043a <code>feature\/*<\/code> \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>develop<\/code> \u2014 \u043f\u043e\u043b\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>main<\/code> \u2014 \u043f\u043e\u043b\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u043e \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0443 \u0432\u0430\u0441 \u0431\u044b\u043b \u0443\u043c\u043d\u044b\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043d\u0430 \u0444\u0430\u0431\u0440\u0438\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u0437\u0434\u0435\u043b\u0438\u0435\u043c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0435\u0433\u043e \u043c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u043a\u0438.<\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 GitHub Actions<\/h3>\n<p>\u0412 GitHub Actions \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430 \u0434\u0432\u0443\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445:<\/p>\n<ol>\n<li>\n<p><strong>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 workflow<\/strong> \u2014 \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 job \u0438\u043b\u0438 step<\/strong> \u2014 \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430<\/p>\n<\/li>\n<\/ol>\n<h4>\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 workflow<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c workflow \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0432\u0435\u0442\u043e\u043a, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0435\u043a\u0446\u0438\u044e <code>on<\/code>:<\/p>\n<pre><code class=\"yaml\">name: CI Pipeline  on:   push:     branches: [ main, develop, 'feature\/**' ]   pull_request:     branches: [ main, develop ]<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0433\u043e\u0432\u043e\u0440\u0438\u0442: &#171;\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043f\u0440\u0438 \u043f\u0443\u0448\u0435 \u0432 \u0432\u0435\u0442\u043a\u0438 main, develop \u0438\u043b\u0438 \u043b\u044e\u0431\u0443\u044e \u0432\u0435\u0442\u043a\u0443, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0443\u044e\u0441\u044f \u0441 feature\/, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 PR \u0432 main \u0438\u043b\u0438 develop&#187;.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 <code>'feature\/**'<\/code> \u2014 \u044d\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d (pattern), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0441\u0435\u043c \u0432\u0435\u0442\u043a\u0430\u043c, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u043c\u0441\u044f \u0441 <code>feature\/<\/code>. \u0417\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u0438 \u0437\u0434\u0435\u0441\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u0430\u043a \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0437\u043d\u0430\u043a\u0438.<\/p>\n<h4>\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 workflow<\/h4>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 <code>if<\/code> \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 job \u0438\u043b\u0438 step:<\/p>\n<pre><code class=\"yaml\">jobs:   test:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Run tests         run: npm test    deploy-to-staging:     runs-on: ubuntu-latest     needs: test     if: github.ref == 'refs\/heads\/develop'     steps:       - uses: actions\/checkout@v3       - name: Deploy to staging         run: .\/deploy.sh staging    deploy-to-production:     runs-on: ubuntu-latest     needs: test     if: github.ref == 'refs\/heads\/main'     steps:       - uses: actions\/checkout@v3       - name: Deploy to production         run: .\/deploy.sh production <\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0442\u0435\u0441\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u0435\u0442\u043e\u043a, \u043d\u043e \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 staging \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>develop<\/code>, \u0430 \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 production \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>main<\/code>.<\/p>\n<p>\u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <code>github.ref == 'refs\/heads\/main'<\/code> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0432\u0435\u0442\u043a\u0430 main. GitHub Actions \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445:<\/p>\n<ul>\n<li>\n<p><code>github.ref<\/code> \u2014 \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f \u0441\u0441\u044b\u043b\u043a\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>refs\/heads\/main<\/code> \u0438\u043b\u0438 <code>refs\/tags\/v1.0.0<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>github.event_name<\/code> \u2014 \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>push<\/code>, <code>pull_request<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>github.actor<\/code> \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0432\u0448\u0438\u0439 \u0441\u043e\u0431\u044b\u0442\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0438 \u043c\u043d\u043e\u0433\u0438\u0435 <a href=\"https:\/\/docs.github.com\/en\/actions\/writing-workflows\/choosing-what-your-workflow-does\/accessing-contextual-information-about-workflow-runs#github-context\" rel=\"noopener noreferrer nofollow\">\u0434\u0440\u0443\u0433\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 <code>&amp;&amp;<\/code> (\u0418) \u0438 <code>||<\/code> (\u0418\u041b\u0418):<\/p>\n<pre><code class=\"yaml\">if: github.ref == 'refs\/heads\/main' &amp;&amp; github.event_name == 'push'<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u0442\u0438\u043d\u043d\u044b\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u0443\u0448\u0435\u0439 \u0432 \u0432\u0435\u0442\u043a\u0443 main.<\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 GitLab CI<\/h3>\n<p>GitLab CI \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u0435, \u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0434\u043b\u044f \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<h4>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: only\/except<\/h4>\n<p>\u0422\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 GitLab CI \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432 <code>only<\/code> \u0438 <code>except<\/code>:<\/p>\n<pre><code class=\"yaml\">stages:   - test   - deploy  test:   stage: test   script:     - npm test  deploy-staging:   stage: deploy   script:     - .\/deploy.sh staging   only:     - develop  deploy-production:   stage: deploy   script:     - .\/deploy.sh production   only:     - main<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c <code>only: - develop<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 &#171;\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u0435\u0442\u043a\u0438 develop&#187;. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, <code>except<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0434\u043b\u044f \u043a\u0430\u043a\u0438\u0445 \u0432\u0435\u0442\u043e\u043a \u0437\u0430\u0434\u0430\u0447\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u041d\u0415 \u043d\u0443\u0436\u043d\u043e.<\/p>\n<h4>\u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: rules<\/h4>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u044b\u0439 \u0438 \u0433\u0438\u0431\u043a\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>rules<\/code>:<\/p>\n<pre><code class=\"yaml\">deploy-staging:   stage: deploy   script:     - .\/deploy.sh staging   rules:     - if: $CI_COMMIT_BRANCH == \"develop\"       when: on_success     - when: never<\/code><\/pre>\n<p>\u0421\u0435\u043a\u0446\u0438\u044f <code>rules<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0430\u0432\u0438\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u041f\u0435\u0440\u0432\u043e\u0435 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0435\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u0431\u0443\u0434\u0435\u0442 \u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u0432\u0435\u0442\u043a\u0430 \u2014 <code>develop<\/code> \u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0448\u0430\u0433\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u044b. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u043e <code>when: never<\/code>, \u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0430.<\/p>\n<p>GitLab CI \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p><code>$CI_COMMIT_BRANCH<\/code> \u2014 \u0438\u043c\u044f \u0432\u0435\u0442\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code>$CI_PIPELINE_SOURCE<\/code> \u2014 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>push<\/code>, <code>merge_request_event<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>$CI_COMMIT_TAG<\/code> \u2014 \u0438\u043c\u044f \u0442\u0435\u0433\u0430 (\u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c)<\/p>\n<\/li>\n<li>\n<p>\u0438 \u043c\u043d\u043e\u0433\u0438\u0435 <a href=\"https:\/\/docs.gitlab.com\/ci\/variables\/predefined_variables\/\" rel=\"noopener noreferrer nofollow\">\u0434\u0440\u0443\u0433\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u0443\u044f \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"yaml\">rules:   - if: $CI_COMMIT_BRANCH == \"main\" &amp;&amp; $CI_PIPELINE_SOURCE == \"push\"     when: on_success   - if: $CI_COMMIT_BRANCH =~ \/^feature\\\/.*\/     when: manual   - when: never<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442: &#171;\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043b\u044f \u043f\u0443\u0448\u0435\u0439 \u0432 main, \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043b\u044f \u0432\u0435\u0442\u043e\u043a <code>feature\/*<\/code>, \u0438 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432&#187;.<\/p>\n<h4>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u043d\u043e\u0433\u043e workflow<\/h4>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043c\u043e\u0449\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u0435\u0442\u043e\u043a \u2014 \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043e\u043a <code>feature\/*<\/code> \u2014 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u0438\u043d\u0442\u0438\u043d\u0433 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0438\u043f\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>develop<\/code> \u2014 \u0432\u0441\u0451 \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 + e2e-\u0442\u0435\u0441\u0442\u044b + \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>main<\/code> \u2014 \u0432\u0441\u0451 \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 + \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d (\u0441 \u0440\u0443\u0447\u043d\u044b\u043c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c)<\/p>\n<\/li>\n<\/ol>\n<h4>GitHub Actions<\/h4>\n<pre><code class=\"yaml\">name: CI\/CD Pipeline  on:   push:     branches: [ main, develop, 'feature\/**' ]   pull_request:     branches: [ main, develop ]  jobs:   build:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Build         run: npm run build       - name: Run basic tests         run: npm test    lint-and-typecheck:     runs-on: ubuntu-latest     if: startsWith(github.ref, 'refs\/heads\/feature\/')     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Lint         run: npm run lint       - name: Type check         run: npm run typecheck    e2e-tests:     runs-on: ubuntu-latest     needs: [build]     if: github.ref == 'refs\/heads\/develop' || github.ref == 'refs\/heads\/main'     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Run E2E tests         run: npm run test:e2e    deploy-staging:     runs-on: ubuntu-latest     needs: [build, e2e-tests]     if: github.ref == 'refs\/heads\/develop'     steps:       - uses: actions\/checkout@v3       - name: Deploy to staging         run: |           echo \"Deploying to staging environment...\"           # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440    deploy-production:     runs-on: ubuntu-latest     needs: [build, e2e-tests]     if: github.ref == 'refs\/heads\/main'     environment:       name: production       url: https:\/\/example.com     steps:       - uses: actions\/checkout@v3       - name: Deploy to production         run: |           echo \"Deploying to production environment...\"           # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d<\/code><\/pre>\n<h4>GitLab CI<\/h4>\n<pre><code class=\"yaml\">stages:   - build   - test   - deploy  build:   stage: build   script:     - npm ci     - npm run build   artifacts:     paths:       - dist\/  basic-tests:   stage: test   script:     - npm test  lint-and-typecheck:   stage: test   script:     - npm run lint     - npm run typecheck   rules:     - if: $CI_COMMIT_BRANCH =~ \/^feature\\\/.*\/       when: on_success     - when: never  e2e-tests:   stage: test   script:     - npm run test:e2e   rules:     - if: $CI_COMMIT_BRANCH == \"develop\" || $CI_COMMIT_BRANCH == \"main\"       when: on_success     - when: never  deploy-staging:   stage: deploy   script:     - echo \"Deploying to staging environment...\"     # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440   environment:     name: staging     url: https:\/\/staging.example.com   rules:     - if: $CI_COMMIT_BRANCH == \"develop\"       when: on_success     - when: never  deploy-production:   stage: deploy   script:     - echo \"Deploying to production environment...\"     # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d   environment:     name: production     url: https:\/\/example.com   rules:     - if: $CI_COMMIT_BRANCH == \"main\"       when: manual     - when: never<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u043a\u0430\u043a \u0432 GitLab CI \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>when: manual<\/code> \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d, \u0447\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f.<\/p>\n<h4>\u0412\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u0439<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0435\u0433\u043e \u043a\u0430\u043a \u0431\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0443:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u0435 (\u043f\u0443\u0448, PR) \u2192 \u0417\u0430\u043f\u0443\u0441\u043a workflow<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u0442\u043a\u0438: <\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 <code>feature\/*<\/code> \u2192 \u0421\u0431\u043e\u0440\u043a\u0430 + \u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b + \u041b\u0438\u043d\u0442\u0438\u043d\u0433<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 <code>develop<\/code> \u2192 \u0421\u0431\u043e\u0440\u043a\u0430 + \u0412\u0441\u0435 \u0442\u0435\u0441\u0442\u044b + \u0414\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 <code>main<\/code> \u2192 \u0421\u0431\u043e\u0440\u043a\u0430 + \u0412\u0441\u0435 \u0442\u0435\u0441\u0442\u044b + \u0414\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d (\u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c)<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0412\u0435\u0442\u043e\u043a \u0432 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0432\u0435\u0442\u043e\u043a \u043d\u0430 \u043d\u043e\u0432\u043e\u0433\u043e\u0434\u043d\u0435\u0439 \u0451\u043b\u043a\u0435 \u2014 CI\/CD \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0438\u0442\u044c \u0438\u0445 \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0442\u043e\u0447\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0432\u0435\u0442\u043a\u0438 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c, \u0430 \u043a\u0430\u043a\u0438\u0435 \u2014 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u043e\u0439\u0442\u0438 \u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443.<\/p>\n<h2>\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h2>\n<h3>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0432 CI\/CD<\/h3>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u0441\u0442\u0440\u043e\u0438\u0442\u0435 \u0434\u043e\u043c. \u0412\u044b \u0436\u0435 \u043d\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043a\u043b\u044e\u0447\u0438 \u043e\u0442 \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0434\u0432\u0435\u0440\u0438 \u043f\u043e\u0434 \u043a\u043e\u0432\u0440\u0438\u043a\u043e\u043c, \u0433\u0434\u0435 \u0438\u0445 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0445\u043e\u0436\u0438\u0439? \u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u0432 \u043c\u0438\u0440\u0435 CI\/CD \u0435\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043b\u044c\u0437\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0432\u0438\u0434\u0435: \u043f\u0430\u0440\u043e\u043b\u0438 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a API, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0438 \u043a\u043e\u0434\u0430 \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435.<\/p>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b CI\/CD (<code>.github\/workflows\/*.yml<\/code> \u0438\u043b\u0438 <code>.gitlab-ci.yml<\/code>) \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c \u0438\u043b\u0438 \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043b\u044e\u0434\u0435\u0439. \u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0437\u0430\u043f\u0438\u0448\u0435\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0432 \u0442\u0430\u043a\u043e\u0439 \u0444\u0430\u0439\u043b, \u043e\u043d \u0441\u0442\u0430\u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432\u0441\u0435\u043c, \u043a\u0442\u043e \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e. \u042d\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 PIN-\u043a\u043e\u0434 \u043d\u0430 \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u043e\u0439 \u043a\u0430\u0440\u0442\u0435.<\/p>\n<p>\u0412\u043e\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u0432\u0438\u0434\u044b \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0437\u0430\u0449\u0438\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0430\u0440\u043e\u043b\u0438<\/strong> \u2014 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c, \u0431\u0430\u0437\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442.\u0434.<\/p>\n<\/li>\n<li>\n<p><strong>API-\u0442\u043e\u043a\u0435\u043d\u044b<\/strong> \u2014 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p><strong>SSH-\u043a\u043b\u044e\u0447\u0438<\/strong> \u2014 \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b<\/strong> \u2014 \u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0438 \u043a\u043e\u0434\u0430 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u0447\u0451\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432<\/strong> \u2014 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 \u0432 AWS, Azure, GCP \u0438 \u0442.\u0434.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0438 GitHub Actions, \u0438 GitLab CI \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 <strong>\u0441\u0435\u043a\u0440\u0435\u0442\u044b<\/strong> \u0438 <strong>\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/strong>.<\/p>\n<h4>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438 \u0432 GitHub Actions<\/h4>\n<p>GitHub Actions \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0430 \u0442\u0440\u0451\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445:<\/p>\n<ol>\n<li>\n<p><strong>\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/strong> \u2014 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438<\/strong> \u2014 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043e \u0432\u0441\u0435\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u0445 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/strong> \u2014 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, production)<\/p>\n<\/li>\n<\/ol>\n<h4>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u0430 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/h4>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0441\u0432\u043e\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 &#171;Settings&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0431\u043e\u043a\u043e\u0432\u043e\u043c \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 &#171;Secrets and variables&#187; \u2192 &#171;Actions&#187;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;New repository secret&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>DATABASE_PASSWORD<\/code>) \u0438 \u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;Add secret&#187;<\/p>\n<\/li>\n<\/ol>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432 \u0432 workflow<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u0430 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0441\u0432\u043e\u0451\u043c workflow \u0447\u0435\u0440\u0435\u0437 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 <code>${{ secrets.SECRET_NAME }}<\/code>:<\/p>\n<pre><code class=\"yaml\">jobs:   deploy:     runs-on: ubuntu-latest     steps:       - name: Deploy to server         run: |           sshpass -p ${{ secrets.SERVER_PASSWORD }} ssh user@example.com \"cd \/var\/www &amp;&amp; git pull\" <\/code><\/pre>\n<p>\u0412\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e GitHub \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u0430\u0441\u043a\u0438\u0440\u0443\u0435\u0442 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0432 \u043b\u043e\u0433\u0430\u0445. \u0415\u0441\u043b\u0438 \u0441\u0435\u043a\u0440\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u043f\u043e\u043f\u0430\u0434\u0451\u0442 \u0432 \u0432\u044b\u0432\u043e\u0434 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, GitHub \u0437\u0430\u043c\u0435\u043d\u0438\u0442 \u0435\u0433\u043e \u0437\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u0430\u043c\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0435 \u0441\u0435\u043a\u0440\u0435\u0442 \u0438\u043b\u0438 \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0435\u0440\u0435\u0437 <code>echo ${{ secrets.API_TOKEN }}<\/code>.<\/p>\n<h4>\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 GitHub \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b, \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0445 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u0430\u0448\u0435\u0439 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 &#171;Settings&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0431\u043e\u043a\u043e\u0432\u043e\u043c \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 &#171;Secrets and variables&#187; \u2192 &#171;Actions&#187;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;New organization secret&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043a \u043a\u0430\u043a\u0438\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u0435\u043a\u0440\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;Add secret&#187;<\/p>\n<\/li>\n<\/ol>\n<h3>\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0414\u043b\u044f \u043e\u0441\u043e\u0431\u043e \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u043a\u043b\u044e\u0447\u0438 \u043e\u0442 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0412 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 &#171;Settings&#187; \u2192 &#171;Environments&#187;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;Add secret&#187; \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0441\u0435\u043a\u0440\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u0412 workflow \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f job-\u0430:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"yaml\">jobs:   deploy-production:     runs-on: ubuntu-latest     environment: production     steps:       - name: Deploy to production         run: .\/deploy.sh ${{ secrets.PRODUCTION_API_KEY }} <\/code><\/pre>\n<p>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0449\u0438\u0442\u043d\u044b\u0435 \u043c\u0435\u0440\u044b \u0434\u043b\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0443\u0447\u043d\u043e\u0435 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.<\/p>\n<h4>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438 \u0432 GitLab CI<\/h4>\n<p>GitLab CI \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u0435\u0440\u043c\u0438\u043d &#171;\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435&#187; (variables) \u0432\u043c\u0435\u0441\u0442\u043e &#171;\u0441\u0435\u043a\u0440\u0435\u0442\u044b&#187;, \u043d\u043e \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0442\u0430 \u0436\u0435. \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u044b\u043c\u0438 (protected) \u0438\/\u0438\u043b\u0438 \u043c\u0430\u0441\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 (masked).<\/p>\n<ul>\n<li>\n<p><strong>\u0417\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/strong> \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u044b\u0445 \u0432\u0435\u0442\u043a\u0430\u0445 \u0438 \u0442\u0435\u0433\u0430\u0445<\/p>\n<\/li>\n<li>\n<p><strong>\u041c\u0430\u0441\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/strong> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043b\u043e\u0433\u0430\u0445<\/p>\n<\/li>\n<\/ul>\n<h4>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 GitLab<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 &#171;Settings&#187; \u2192 &#171;CI\/CD&#187;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0438\u0442\u0435 \u0441\u0435\u043a\u0446\u0438\u044e &#171;Variables&#187;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;Add variable&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>DATABASE_PASSWORD<\/code>) \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442\u043c\u0435\u0442\u044c\u0442\u0435 &#171;Protect variable&#187; \u0438\/\u0438\u043b\u0438 &#171;Mask variable&#187;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;Add variable&#187;<\/p>\n<\/li>\n<\/ol>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432 pipeline<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u0432 \u0441\u0432\u043e\u0451\u043c <code>.gitlab-ci.yml<\/code>:<\/p>\n<pre><code class=\"yaml\">deploy:   stage: deploy   script:     - sshpass -p $DATABASE_PASSWORD ssh user@example.com \"cd \/var\/www &amp;&amp; git pull\" <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432 GitLab CI \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 <code>$VARIABLE_NAME<\/code>, \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430.<\/p>\n<h4>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0433\u0440\u0443\u043f\u043f\u044b<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0432 GitLab, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0433\u0440\u0443\u043f\u043f\u044b:<\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u0430\u0448\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u044b<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 &#171;Settings&#187; \u2192 &#171;CI\/CD&#187;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0438\u0442\u0435 \u0441\u0435\u043a\u0446\u0438\u044e &#171;Variables&#187;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u044d\u0442\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b, \u043d\u043e \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<h4>\u0422\u0438\u043f\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432 GitLab CI<\/h4>\n<p>GitLab CI \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0430 \u0442\u0438\u043f\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u044b (environment variables)<\/strong> \u2014 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u0445<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u043e\u0432\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 (file variables)<\/strong> \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u0444\u0430\u0439\u043b\u044b \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441\u0431\u043e\u0440\u043a\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0424\u0430\u0439\u043b\u043e\u0432\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432, \u043a\u043b\u044e\u0447\u0435\u0439 SSH \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044b\u0447\u043d\u043e \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0430\u0445:<\/p>\n<pre><code class=\"yaml\">deploy:   stage: deploy   script:     - ssh -i $SSH_PRIVATE_KEY_FILE user@example.com \"cd \/var\/www &amp;&amp; git pull\" <\/code><\/pre>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432 \u0432 CI\/CD.<\/p>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0440 1: \u0414\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0447\u0435\u0440\u0435\u0437 SSH<\/h3>\n<p><strong>GitHub Actions:<\/strong><\/p>\n<pre><code class=\"yaml\">jobs:   deploy:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3              - name: Install SSH key         uses: shimataro\/ssh-key-action@v2         with:           key: ${{ secrets.SSH_PRIVATE_KEY }}           known_hosts: ${{ secrets.KNOWN_HOSTS }}                  - name: Deploy to server         run: |           ssh user@example.com \"cd \/var\/www &amp;&amp; git pull &amp;&amp; npm ci &amp;&amp; npm run build\" <\/code><\/pre>\n<p><strong>GitLab CI:<\/strong><\/p>\n<pre><code class=\"yaml\">deploy:   stage: deploy   before_script:     - 'which ssh-agent || ( apt-get update -y &amp;&amp; apt-get install openssh-client -y )'     - eval $(ssh-agent -s)     - echo \"$SSH_PRIVATE_KEY\" | tr -d '\\r' | ssh-add -     - mkdir -p ~\/.ssh     - chmod 700 ~\/.ssh     - echo \"$KNOWN_HOSTS\" &gt; ~\/.ssh\/known_hosts     - chmod 644 ~\/.ssh\/known_hosts   script:     - ssh user@example.com \"cd \/var\/www &amp;&amp; git pull &amp;&amp; npm ci &amp;&amp; npm run build\"<\/code><\/pre>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0440 2: \u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430 \u0432 npm<\/h3>\n<p><strong>GitHub Actions:<\/strong><\/p>\n<pre><code class=\"yaml\">jobs:   publish:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - uses: actions\/setup-node@v3         with:           node-version: '16'           registry-url: 'https:\/\/registry.npmjs.org'       - run: npm ci       - run: npm publish         env:           NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}<\/code><\/pre>\n<p><strong>GitLab CI:<\/strong><\/p>\n<pre><code class=\"yaml\">publish:   stage: deploy   script:     - echo \"\/\/registry.npmjs.org\/:_authToken=${NPM_TOKEN}\" &gt; .npmrc     - npm ci     - npm publish<\/code><\/pre>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0440 3: \u0414\u0435\u043f\u043b\u043e\u0439 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 (AWS)<\/h3>\n<p><strong>GitHub Actions:<\/strong><\/p>\n<pre><code class=\"yaml\">jobs:   deploy:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3              - name: Configure AWS credentials         uses: aws-actions\/configure-aws-credentials@v1         with:           aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}           aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}           aws-region: us-east-1                  - name: Deploy to S3         run: aws s3 sync .\/dist s3:\/\/my-bucket\/<\/code><\/pre>\n<p><strong>GitLab CI:<\/strong><\/p>\n<pre><code class=\"yaml\">deploy:   stage: deploy   image: amazon\/aws-cli   script:     - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID     - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY     - aws configure set region us-east-1     - aws s3 sync .\/dist s3:\/\/my-bucket\/<\/code><\/pre>\n<h4>\u041b\u0443\u0447\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438<\/h4>\n<ol>\n<li>\n<p><strong>\u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u043e\u0441\u0442\u0443\u043f<\/strong> \u2014 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0440\u0430\u0432\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0439\u0442\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b<\/strong> \u2014 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u0435\u043d\u044f\u0439\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u0438 \u0438 \u0442\u043e\u043a\u0435\u043d\u044b, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0435\u0441\u043b\u0438 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0431\u044b\u043b\u0438 \u043a\u0430\u0434\u0440\u043e\u0432\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b<\/strong> \u2014 \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c \u0441\u0440\u043e\u043a\u043e\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435 \u043b\u043e\u0433\u0438<\/strong> \u2014 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432 \u043b\u043e\u0433\u0438. \u0414\u0430\u0436\u0435 \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043c\u0430\u0441\u043a\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u0442\u0435\u0447\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0435 \u0445\u0430\u0440\u0434\u043a\u043e\u0434\u044c\u0442\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b<\/strong> \u2014 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0442\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043a\u043e\u0434 \u0438\u043b\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439<\/strong> \u2014 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0438 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u044c\u0442\u0435 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u0438\u043b\u0438 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c \u0432\u0435\u0442\u043a\u0430\u043c.<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u0432 CI\/CD \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u043f\u0430\u0440\u043e\u043b\u0438 \u0438\u043b\u0438 \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0437\u0430\u0449\u0438\u0442\u044b \u0438 \u0438\u0437\u0431\u0435\u0433\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u0434. \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438 \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u043f\u0440\u043e\u0441 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430, \u044d\u0442\u043e \u0432\u043e\u043f\u0440\u043e\u0441 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0430\u0448\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<h2>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 \u044d\u0442\u0430\u043f\u044b (\u0441\u0442\u0435\u0439\u0434\u0436\u0438)<\/h2>\n<h3>\u041a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435<\/h3>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u0448\u0435\u0444-\u043f\u043e\u0432\u0430\u0440, \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043d\u043e\u0432\u043e\u0435 \u0431\u043b\u044e\u0434\u043e. \u0412\u044b \u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044f\u043c \u0440\u0435\u0441\u0442\u043e\u0440\u0430\u043d\u0430, \u0432\u0435\u0440\u043d\u043e? \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0435 \u043d\u0430 \u043a\u0443\u0445\u043d\u0435, \u0437\u0430\u0442\u0435\u043c \u0434\u0430\u0451\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c, \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0445 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043e\u043a \u0438 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0439 \u0431\u043b\u044e\u0434\u043e \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043c\u0435\u043d\u044e.<\/p>\n<p>\u0412 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f. <strong>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/strong> (environments) \u2014 \u044d\u0442\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u044b, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0432\u0430\u0448 \u043a\u043e\u0434 \u043d\u0430 \u043f\u0443\u0442\u0438 \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e:<\/p>\n<ul>\n<li>\n<p><strong>Development (\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430)<\/strong> \u2014 \u0437\u0434\u0435\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0442 \u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u043d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>Testing\/QA (\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435)<\/strong> \u2014 \u0437\u0434\u0435\u0441\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0438\u0449\u0443\u0442 \u043e\u0448\u0438\u0431\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><strong>Staging (\u043f\u0440\u0435\u0434\u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d)<\/strong> \u2014 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u0430\u044f \u043a \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0443 \u0441\u0440\u0435\u0434\u0430 \u0434\u043b\u044f \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a<\/p>\n<\/li>\n<li>\n<p><strong>Production (\u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d)<\/strong> \u2014 \u0440\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0440\u0435\u0434\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u0436\u0434\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0437\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0438\u043b\u0438 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u043d\u044b\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (\u0447\u0430\u0441\u0442\u043e \u0441 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 \u043d\u0435\u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445)<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u043d\u044b\u0435 \u0443\u0440\u043e\u0432\u043d\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u043d\u044b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 dev)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u042d\u0442\u0430\u043f\u044b<\/strong> (stages) \u2014 \u044d\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 CI\/CD, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435:<\/p>\n<ol>\n<li>\n<p><strong>Build (\u0441\u0431\u043e\u0440\u043a\u0430)<\/strong> \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u043a\u043e\u0434\u0430, \u0441\u0431\u043e\u0440\u043a\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>Test (\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435)<\/strong> \u2014 \u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>Deploy (\u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435)<\/strong> \u2014 \u0432\u044b\u043a\u043b\u0430\u0434\u043a\u0430 \u043a\u043e\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u044b<\/p>\n<\/li>\n<\/ol>\n<p>\u042d\u0442\u0430\u043f\u044b \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u044b: \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0434\u0435\u043f\u043b\u043e\u044f \u043a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u0432\u0451\u0440\u043d\u0443\u0442 \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u0439.<\/p>\n<p>\u0417\u0430\u0447\u0435\u043c \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e? \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0438 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0435. \u0427\u0442\u043e \u043b\u0443\u0447\u0448\u0435:<\/p>\n<ol>\n<li>\n<p>\u0418\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0451 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0440\u0438\u0441\u043a\u0443\u044f \u0432\u043d\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b?<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u0434\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438, \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c \u0432\u044b\u043a\u0430\u0442\u0438\u0442\u044c \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d?<\/p>\n<\/li>\n<\/ol>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0435\u0435. \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 \u044d\u0442\u0430\u043f\u044b \u0432 CI\/CD \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0438\u0441\u043a\u0438 \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u043f\u043b\u0430\u0432\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043a\u043e\u0434\u0430 \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u0432 GitHub Actions<\/h3>\n<p>GitHub Actions \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u043f\u043b\u043e\u0438, \u043d\u043e \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0449\u0438\u0442\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430.<\/p>\n<h4>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439<\/h4>\n<p>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 &#171;Settings&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0431\u043e\u043a\u043e\u0432\u043e\u043c \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 &#171;Environments&#187;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;New environment&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, &#171;production&#187;)<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0437\u0430\u0449\u0438\u0442\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 (\u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438)<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;Configure environment&#187;<\/p>\n<\/li>\n<\/ol>\n<h4>\u0417\u0430\u0449\u0438\u0442\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0434\u043b\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439<\/h4>\n<p>GitHub \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f\u043e\u0432 \u0437\u0430\u0449\u0438\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><strong>Required reviewers (\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0435)<\/strong> \u2014 \u043b\u044e\u0434\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0434\u043e\u0431\u0440\u0438\u0442\u044c \u0434\u0435\u043f\u043b\u043e\u0439<\/p>\n<\/li>\n<li>\n<p><strong>Wait timer (\u0442\u0430\u0439\u043c\u0435\u0440 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f)<\/strong> \u2014 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0435\u0440\u0435\u0434 \u0434\u0435\u043f\u043b\u043e\u0435\u043c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 10 \u043c\u0438\u043d\u0443\u0442)<\/p>\n<\/li>\n<li>\n<p><strong>Deployment branches (\u0432\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f)<\/strong> \u2014 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0432\u0435\u0442\u043e\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c<\/p>\n<\/li>\n<li>\n<p><strong>Environment secrets (\u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f)<\/strong> \u2014 \u0441\u0435\u043a\u0440\u0435\u0442\u044b, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u044d\u0442\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u0432 workflow<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0441\u0432\u043e\u0451\u043c workflow:<\/p>\n<pre><code class=\"yaml\">name: Deploy  on:   push:     branches: [ main ]  jobs:   deploy-to-staging:     runs-on: ubuntu-latest     environment:       name: staging       url: https:\/\/staging.example.com     steps:       - uses: actions\/checkout@v3       - name: Deploy to Staging         run: .\/deploy.sh staging    deploy-to-production:     needs: deploy-to-staging     runs-on: ubuntu-latest     environment:       name: production       url: https:\/\/example.com     steps:       - uses: actions\/checkout@v3       - name: Deploy to Production         run: .\/deploy.sh production <\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u0435\u043f\u043b\u043e\u0439 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0434\u0451\u0442 \u043d\u0430 staging, \u0430 \u0437\u0430\u0442\u0435\u043c \u043d\u0430 production (\u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f <code>needs: deploy-to-staging<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0443\u043a\u0430\u0437\u0430\u043d URL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 GitHub<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f production \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0437\u0430\u0449\u0438\u0442\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0435), workflow \u0431\u0443\u0434\u0435\u0442 \u0436\u0434\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u0434\u0435\u043f\u043b\u043e\u0435\u043c<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"yaml\">jobs:   deploy:     runs-on: ubuntu-latest     environment: production     env:       NODE_ENV: production       API_URL: https:\/\/api.example.com     steps:       - uses: actions\/checkout@v3       - name: Deploy         run: |           echo \"Deploying with NODE_ENV=$NODE_ENV\"           .\/deploy.sh<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 <code>env<\/code> \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u0441\u0435\u043c \u0448\u0430\u0433\u0430\u043c \u0432 job-\u0435 \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u0432 GitLab CI<\/h3>\n<p>GitLab CI \u0438\u043c\u0435\u0435\u0442 \u043c\u043e\u0449\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043a\u0430\u043a \u044d\u0442\u0430\u043f\u043e\u0432 (stages), \u0442\u0430\u043a \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 (environments).<\/p>\n<h3>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u044d\u0442\u0430\u043f\u043e\u0432<\/h3>\n<p>\u042d\u0442\u0430\u043f\u044b \u0432 GitLab CI \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0444\u0430\u0439\u043b\u0430 <code>.gitlab-ci.yml<\/code>:<\/p>\n<pre><code class=\"yaml\">stages:   - build   - test   - deploy<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0437\u0430\u0434\u0430\u0451\u0442 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0441\u0435 job-\u044b \u044d\u0442\u0430\u043f\u0430 build, \u0437\u0430\u0442\u0435\u043c test, \u0438 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 deploy.<\/p>\n<h4>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439<\/h4>\n<p>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 job-\u043e\u0432:<\/p>\n<pre><code class=\"yaml\">deploy-staging:   stage: deploy   script:     - .\/deploy.sh staging   environment:     name: staging     url: https:\/\/staging.example.com <\/code><\/pre>\n<p>\u041a\u043b\u044e\u0447 <code>environment<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 job \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u043c staging \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 URL \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043d\u0435\u043c\u0443.<\/p>\n<h4>\u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043c\u043e\u0449\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 GitLab CI \u2014 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0442\u043a\u0438 \u0438\u043b\u0438 merge request:<\/p>\n<pre><code class=\"yaml\">deploy-review:   stage: deploy   script:     - .\/deploy.sh review\/$CI_COMMIT_REF_SLUG   environment:     name: review\/$CI_COMMIT_REF_SLUG     url: https:\/\/$CI_COMMIT_REF_SLUG.review.example.com     on_stop: stop-review   only:     - branches   except:     - main  stop-review:   stage: deploy   script:     - .\/cleanup.sh review\/$CI_COMMIT_REF_SLUG   environment:     name: review\/$CI_COMMIT_REF_SLUG     action: stop   when: manual   only:     - branches   except:     - main<\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0442\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 <code>review\/\u0438\u043c\u044f-\u0432\u0435\u0442\u043a\u0438<\/code><\/p>\n<\/li>\n<li>\n<p>URL \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043c\u0435\u043d\u0438 \u0432\u0435\u0442\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d job <code>stop-review<\/code> \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e<\/p>\n<\/li>\n<\/ul>\n<h4>\u0417\u0430\u0449\u0438\u0442\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439<\/h4>\n<p>GitLab \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432, \u043a\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0432 \u043d\u0438\u0445:<\/p>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 GitLab<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 &#171;Settings&#187; \u2192 &#171;CI\/CD&#187;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0438\u0442\u0435 \u0441\u0435\u043a\u0446\u0438\u044e &#171;Protected environments&#187;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 &#171;Protect an environment&#187;<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0438 \u0443\u043a\u0430\u0436\u0438\u0442\u0435, \u043a\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0432 \u043d\u0435\u0433\u043e<\/p>\n<\/li>\n<\/ol>\n<h4>\u0420\u0443\u0447\u043d\u043e\u0435 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0414\u043b\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a production, \u0447\u0430\u0441\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0440\u0443\u0447\u043d\u043e\u0435 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"yaml\">deploy-production:   stage: deploy   script:     - .\/deploy.sh production   environment:     name: production     url: https:\/\/example.com   when: manual   only:     - main <\/code><\/pre>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>when: manual<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e job \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u2014 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0440\u0443\u0447\u043d\u043e\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 GitLab.<\/p>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043c\u043d\u043e\u0433\u043e\u044d\u0442\u0430\u043f\u043d\u043e\u0433\u043e pipeline<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u0430\u043f\u043e\u0432 \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h4>GitHub Actions<\/h4>\n<pre><code class=\"yaml\">name: CI\/CD Pipeline  on:   push:     branches: [ main, develop ]   pull_request:     branches: [ main, develop ]  jobs:   build:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Build         run: npm run build       - name: Upload build artifacts         uses: actions\/upload-artifact@v3         with:           name: build-files           path: dist\/    test:     needs: build     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Download build artifacts         uses: actions\/download-artifact@v3         with:           name: build-files           path: dist\/       - name: Run tests         run: npm test    deploy-dev:     if: github.ref == 'refs\/heads\/develop'     needs: test     runs-on: ubuntu-latest     environment:       name: development       url: https:\/\/dev.example.com     steps:       - uses: actions\/checkout@v3       - name: Download build artifacts         uses: actions\/download-artifact@v3         with:           name: build-files           path: dist\/       - name: Deploy to development         run: |           echo \"Deploying to development environment...\"           # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f    deploy-staging:     if: github.ref == 'refs\/heads\/main'     needs: test     runs-on: ubuntu-latest     environment:       name: staging       url: https:\/\/staging.example.com     steps:       - uses: actions\/checkout@v3       - name: Download build artifacts         uses: actions\/download-artifact@v3         with:           name: build-files           path: dist\/       - name: Deploy to staging         run: |           echo \"Deploying to staging environment...\"           # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f    deploy-production:     if: github.ref == 'refs\/heads\/main'     needs: deploy-staging     runs-on: ubuntu-latest     environment:       name: production       url: https:\/\/example.com     steps:       - uses: actions\/checkout@v3       - name: Download build artifacts         uses: actions\/download-artifact@v3         with:           name: build-files           path: dist\/       - name: Deploy to production         run: |           echo \"Deploying to production environment...\"           # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f <\/code><\/pre>\n<h4>GitLab CI<\/h4>\n<pre><code class=\"yaml\">stages:   - build   - test   - deploy-dev   - deploy-staging   - deploy-production  variables:   NODE_ENV: production  build:   stage: build   image: node:16   script:     - npm ci     - npm run build   artifacts:     paths:       - dist\/  test:   stage: test   image: node:16   script:     - npm ci     - npm test   dependencies:     - build  deploy-dev:   stage: deploy-dev   script:     - echo \"Deploying to development environment...\"     # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f   environment:     name: development     url: https:\/\/dev.example.com   only:     - develop  deploy-staging:   stage: deploy-staging   script:     - echo \"Deploying to staging environment...\"     # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f   environment:     name: staging     url: https:\/\/staging.example.com   only:     - main  deploy-production:   stage: deploy-production   script:     - echo \"Deploying to production environment...\"     # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f   environment:     name: production     url: https:\/\/example.com   when: manual   only:     - main<\/code><\/pre>\n<h3>\u0412\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u044d\u0442\u0430\u043f\u044b \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0438\u0445 \u043a\u0430\u043a \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043d\u0430 \u0444\u0430\u0431\u0440\u0438\u043a\u0435:<\/p>\n<ol>\n<li>\n<p><strong>\u0421\u0431\u043e\u0440\u043a\u0430 (Build)<\/strong> \u2014 \u0441\u044b\u0440\u044c\u0451 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u0443\u0444\u0430\u0431\u0440\u0438\u043a\u0430\u0442<\/p>\n<\/li>\n<li>\n<p><strong>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 (Test)<\/strong> \u2014 \u043f\u043e\u043b\u0443\u0444\u0430\u0431\u0440\u0438\u043a\u0430\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 Dev<\/strong> \u2014 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 &#171;\u043b\u0430\u0431\u043e\u0440\u0430\u0442\u043e\u0440\u043d\u044b\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445&#187;<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 Staging<\/strong> \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445, \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u044b\u0445 \u043a \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 Production<\/strong> \u2014 \u0432\u044b\u043f\u0443\u0441\u043a \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0435\u0439<\/p>\n<\/li>\n<\/ol>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u044d\u0442\u0430\u043f \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e. \u0415\u0441\u043b\u0438 \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u044f \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0435 \u0434\u0435\u0444\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u043d\u0430 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u044d\u0442\u0430\u043f\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430? \u0412 CI\/CD \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0439:<\/p>\n<ol>\n<li>\n<p><strong>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043e\u0442\u043a\u0430\u0442 (rollback)<\/strong> \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0443\u0447\u043d\u043e\u0435 \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e<\/strong> \u2014 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u0438 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435<\/strong> \u2014 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438)<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 GitHub Actions \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a:<\/p>\n<pre><code class=\"yaml\">deploy-with-rollback:   runs-on: ubuntu-latest   steps:     - uses: actions\/checkout@v3     - name: Deploy       id: deploy       continue-on-error: true       run: .\/deploy.sh     - name: Rollback if deploy failed       if: steps.deploy.outcome == 'failure'       run: .\/rollback.sh<\/code><\/pre>\n<p>\u0412 GitLab CI \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>when: on_failure<\/code>:<\/p>\n<pre><code class=\"yaml\">deploy:   stage: deploy   script:     - .\/deploy.sh  rollback:   stage: deploy   script:     - .\/rollback.sh   when: on_failure<\/code><\/pre>\n<p>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 \u044d\u0442\u0430\u043f\u044b \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u044b, \u044d\u0442\u043e \u0444\u0438\u043b\u043e\u0441\u043e\u0444\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0440\u0438\u0441\u043a\u0430\u043c\u0438. \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 CI\/CD \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0439 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0448\u043b\u044e\u0437\u043e\u0432 \u043d\u0430 \u0440\u0435\u043a\u0435: \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0442\u044c &#171;\u043d\u0430\u0432\u043e\u0434\u043d\u0435\u043d\u0438\u044f&#187; \u0432 \u0432\u0438\u0434\u0435 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0435.<\/p>\n<h2>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0438 \u0440\u0430\u0437\u0431\u043e\u0440 \u043e\u0448\u0438\u0431\u043e\u043a<\/h2>\n<h3>\u041e\u0431\u0449\u0438\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u043e\u0442\u043b\u0430\u0434\u043a\u0438 CI\/CD<\/h3>\n<p>\u0414\u0430\u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 CI\/CD-\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u0438\u043d\u043e\u0433\u0434\u0430 \u0434\u0430\u044e\u0442 \u0441\u0431\u043e\u0438. \u042d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u2014 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432, \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0435\u043b\u043e \u0441\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438, \u0433\u0434\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u0435. \u0412\u0430\u0436\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0438 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b.<\/p>\n<p>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 CI\/CD \u0432\u043e \u043c\u043d\u043e\u0433\u043e\u043c \u043f\u043e\u0445\u043e\u0436\u0430 \u043d\u0430 \u043e\u0442\u043b\u0430\u0434\u043a\u0443 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u043d\u043e \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438. \u0412\u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b:<\/p>\n<ol>\n<li>\n<p><strong>\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/strong> \u2014 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u0435, \u043d\u0430 \u043a\u0430\u043a\u043e\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0430\u043f\u0435 \u0438 \u0432 \u043a\u0430\u043a\u043e\u043c job-\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u043d\u0430\u043b\u0438\u0437 \u043b\u043e\u0433\u043e\u0432<\/strong> \u2014 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0437\u0443\u0447\u0438\u0442\u0435 \u0432\u044b\u0432\u043e\u0434 \u043a\u043e\u043c\u0430\u043d\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0438\u0441\u044c \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e<\/strong> \u2014 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0442\u0435 \u0436\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u0441\u0432\u043e\u0435\u0439 \u043c\u0430\u0448\u0438\u043d\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435<\/strong> \u2014 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f<\/strong> \u2014 \u0432\u043d\u043e\u0441\u0438\u0442\u0435 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u043e\u0448\u0438\u0431\u043e\u043a \u0432 CI\/CD:<\/p>\n<ul>\n<li>\n<p><strong>\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438<\/strong> \u0432 YAML-\u0444\u0430\u0439\u043b\u0430\u0445 (\u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043e\u0442\u0441\u0442\u0443\u043f\u044b, \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0435 \u043a\u0430\u0432\u044b\u0447\u043a\u0438)<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/strong> (\u043f\u0430\u043a\u0435\u0442\u044b, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b)<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430<\/strong> (\u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c, \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c, API)<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0439<\/strong> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0434 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 Node.js 16, \u0430 \u0432 CI \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Node.js 14)<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0441\u0435\u0442\u044c\u044e<\/strong> (\u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u044b)<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0430\u0437\u043b\u0438\u0447\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u043c\u0438<\/strong> (\u043a\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u043d\u043e \u043d\u0435 \u0432 CI)<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0432 GitHub Actions<\/h3>\n<p>GitHub Actions \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043b\u043e\u0433\u043e\u0432 \u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 workflow.<\/p>\n<h4>\u0413\u0434\u0435 \u0438\u0441\u043a\u0430\u0442\u044c \u043b\u043e\u0433\u0438<\/h4>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 &#171;Actions&#187; \u0432 \u0432\u0430\u0448\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a workflow (\u043e\u0431\u044b\u0447\u043d\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439)<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043b\u0435\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0441\u043f\u0438\u0441\u043e\u043a job-\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 job, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0435\u0433\u043e \u0448\u0430\u0433\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0448\u0430\u0433, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0435\u0433\u043e \u043b\u043e\u0433<\/p>\n<\/li>\n<\/ol>\n<p>GitHub Actions \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u0432\u043e\u0434 \u043f\u043e \u0448\u0430\u0433\u0430\u043c, \u0447\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u043e\u0438\u0441\u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0415\u0441\u043b\u0438 \u0448\u0430\u0433 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043c\u0435\u0447\u0435\u043d \u043a\u0440\u0430\u0441\u043d\u044b\u043c \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u043e\u043c.<\/p>\n<h4>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435:<\/p>\n<pre><code class=\"yaml\">jobs:   debug-job:     runs-on: ubuntu-latest     steps:       - name: Enable debug logging         run: echo \"ACTIONS_RUNNER_DEBUG=true\" &gt;&gt; $GITHUB_ENV       - name: Your step         run: your-command<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043a\u0443 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0432\u0441\u0435\u0433\u043e workflow, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0441\u0435\u043a\u0440\u0435\u0442 <code>ACTIONS_RUNNER_DEBUG<\/code> \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c <code>true<\/code> \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 debug-\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439<\/h4>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 actions \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438:<\/p>\n<pre><code class=\"yaml\">jobs:   debug:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Dump GitHub context         env:           GITHUB_CONTEXT: ${{ toJson(github) }}         run: echo \"$GITHUB_CONTEXT\"       - name: Dump job context         env:           JOB_CONTEXT: ${{ toJson(job) }}         run: echo \"$JOB_CONTEXT\"       - name: Dump steps context         env:           STEPS_CONTEXT: ${{ toJson(steps) }}         run: echo \"$STEPS_CONTEXT\"       - name: Dump runner context         env:           RUNNER_CONTEXT: ${{ toJson(runner) }}         run: echo \"$RUNNER_CONTEXT\"<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 job \u0432\u044b\u0432\u0435\u0434\u0435\u0442 \u0432 \u043b\u043e\u0433 \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u044b, \u0447\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438 \u043a\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u043d\u0438 \u0438\u043c\u0435\u044e\u0442.<\/p>\n<h4>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 act<\/h4>\n<p>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 <a href=\"https:\/\/github.com\/nektos\/act\" rel=\"noopener noreferrer nofollow\">act<\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c GitHub Actions \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"bash\"># \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430 macOS brew install act  # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430 Linux curl https:\/\/raw.githubusercontent.com\/nektos\/act\/master\/install.sh | sudo bash  # \u0417\u0430\u043f\u0443\u0441\u043a \u0432\u0441\u0435\u0445 workflow act  # \u0417\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e workflow act -W .github\/workflows\/specific-workflow.yml  # \u0417\u0430\u043f\u0443\u0441\u043a \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c act push<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 workflow, \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043c\u0438\u0442\u0438\u0442\u044c \u0438 \u043f\u0443\u0448\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0432 GitLab CI<\/h3>\n<p>GitLab CI \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 pipeline.<\/p>\n<h4>\u0413\u0434\u0435 \u0438\u0441\u043a\u0430\u0442\u044c \u043b\u043e\u0433\u0438<\/h4>\n<ol>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b &#171;CI\/CD&#187; \u2192 &#171;Pipelines&#187; \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 pipeline<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 job, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 &#171;Job log&#187; \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u0432\u044b\u0432\u043e\u0434\u043e\u043c \u043a\u043e\u043c\u0430\u043d\u0434<\/p>\n<\/li>\n<\/ol>\n<p>GitLab \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u044b\u0432\u043e\u0434 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 CI_DEBUG_TRACE<\/h4>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>CI_DEBUG_TRACE<\/code>:<\/p>\n<pre><code class=\"yaml\">job-name:   stage: test   variables:     CI_DEBUG_TRACE: \"true\"   script:     - your-command <\/code><\/pre>\n<p>\u042d\u0442\u043e \u0432\u044b\u0432\u0435\u0434\u0435\u0442 \u0432 \u043b\u043e\u0433 \u0432\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u0438\u0445 \u0432\u044b\u0432\u043e\u0434, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043a\u0440\u044b\u0442\u044b.<\/p>\n<h4>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 gitlab-runner<\/h4>\n<p>GitLab Runner \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\"># \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430 macOS brew install gitlab-runner  # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430 Ubuntu curl -L https:\/\/packages.gitlab.com\/install\/repositories\/runner\/gitlab-runner\/script.deb.sh | sudo bash sudo apt-get install gitlab-runner  # \u0417\u0430\u043f\u0443\u0441\u043a job-\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e gitlab-runner exec docker job-name <\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u0435\u0437 \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.<\/p>\n<h4>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c services<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u0448 pipeline \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445), \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0442\u043b\u0430\u0434\u0438\u0442\u044c \u0438\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435:<\/p>\n<pre><code class=\"yaml\">job:   services:     - name: postgres:13       alias: db   variables:     POSTGRES_PASSWORD: password   script:     - apt-get update &amp;&amp; apt-get install -y postgresql-client     - psql -h db -U postgres -c \"SELECT 1\"     - echo \"Database connection successful\" <\/code><\/pre>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"yaml\">script:   - apt-get update &amp;&amp; apt-get install -y postgresql-client iputils-ping net-tools   - ping -c 3 db   - netstat -tuln   - psql -h db -U postgres -c \"SELECT 1\" <\/code><\/pre>\n<h3>\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/h3>\n<h4>1. \u041e\u0448\u0438\u0431\u043a\u0438 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 YAML<\/h4>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/strong>: Workflow \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u0438\u0437-\u0437\u0430 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 YAML.<\/p>\n<p><strong>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043e\u043d\u043b\u0430\u0439\u043d-\u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u044b YAML (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"http:\/\/www.yamllint.com\/\" rel=\"noopener noreferrer nofollow\">YAML Lint<\/a>)<\/p>\n<\/li>\n<li>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 YAML<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043e\u0442\u0441\u0442\u0443\u043f\u044b (\u0432 YAML \u043e\u043d\u0438 \u0438\u043c\u0435\u044e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435)<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043a\u0430\u0432\u044b\u0447\u043a\u0438 \u0432\u043e\u043a\u0440\u0443\u0433 \u0441\u0442\u0440\u043e\u043a, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0448\u0438\u0431\u043a\u0438<\/strong>:<\/p>\n<pre><code class=\"yaml\"># \u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e job:   steps:   - name: Step with error     run: echo \"Hello     World\"  # \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e job:   steps:   - name: Step without error     run: echo \"Hello World\"<\/code><\/pre>\n<h4>2. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0438 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438<\/h4>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/strong>: \u0421\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0438\u043b\u0438 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c.<\/p>\n<p><strong>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043b\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\/\u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 (\u043d\u043e \u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0435 \u0441\u0430\u043c\u0438 \u0441\u0435\u043a\u0440\u0435\u0442\u044b!)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0442\u043b\u0430\u0434\u043a\u0438<\/strong>:<\/p>\n<pre><code class=\"yaml\"># GitHub Actions steps:   - name: Debug API key     run: |       if [ -n \"${{ secrets.API_KEY }}\" ]; then         echo \"API key is set\"       else         echo \"API key is NOT set\"       fi  # GitLab CI script:   - |     if [ -n \"$API_KEY\" ]; then       echo \"API key is set\"     else       echo \"API key is NOT set\"     fi<\/code><\/pre>\n<h4>3. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438<\/h4>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/strong>: \u0421\u0431\u043e\u0440\u043a\u0430 \u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u043f\u0430\u0434\u0430\u044e\u0442 \u0438\u0437-\u0437\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.<\/p>\n<p><strong>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u044b<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0439\u0442\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>npm ci<\/code> \u0432\u043c\u0435\u0441\u0442\u043e <code>npm install<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c<\/strong>:<\/p>\n<pre><code class=\"yaml\"># GitHub Actions steps:   - uses: actions\/checkout@v3   - uses: actions\/setup-node@v3     with:       node-version: '16'       cache: 'npm'   - run: npm ci   - run: npm test  # GitLab CI job:   cache:     key: ${CI_COMMIT_REF_SLUG}     paths:       - node_modules\/   script:     - npm ci     - npm test<\/code><\/pre>\n<h4>4. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0441\u0435\u0442\u0435\u0432\u044b\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c<\/h4>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/strong>: CI \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c.<\/p>\n<p><strong>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438\u0437 CI (\u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b ping, curl \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0443\u0447\u0451\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u043a\u043e\u0432 \u0438\u043b\u0438 \u0441\u0442\u0430\u0431\u043e\u0432 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438<\/strong>:<\/p>\n<pre><code class=\"yaml\">steps:   - name: Check connectivity     run: |       curl -Is https:\/\/api.example.com | head -1       ping -c 3 api.example.com<\/code><\/pre>\n<h4>5. \u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0438 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u044b<\/h4>\n<p><strong>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/strong>: Job \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p><strong>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u0435 job-\u044b \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u043d\u044c\u0448\u0438\u0445<\/p>\n<\/li>\n<li>\n<p>\u0423\u0432\u0435\u043b\u0438\u0447\u044c\u0442\u0435 \u0442\u0430\u0439\u043c\u0430\u0443\u0442, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430<\/strong>:<\/p>\n<pre><code class=\"yaml\"># GitHub Actions jobs:   long-job:     timeout-minutes: 120     runs-on: ubuntu-latest     steps:       - name: Long running task         run: .\/long-task.sh  # GitLab CI long-job:   script:     - .\/long-task.sh   timeout: 2h<\/code><\/pre>\n<h4>\u041b\u0443\u0447\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0438<\/h4>\n<ol>\n<li>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 <code>echo<\/code> \u0438\u043b\u0438 <code>printf<\/code> \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435<\/strong> \u2014 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>env<\/code> \u0438\u043b\u0438 <code>printenv<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0439\u0442\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b<\/strong> \u2014 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0444\u043b\u0430\u0433\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0433\u043e \u0432\u044b\u0432\u043e\u0434\u0430<\/strong> \u2014 \u043c\u043d\u043e\u0433\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u043c\u0435\u044e\u0442 \u0444\u043b\u0430\u0433\u0438 \u0432\u0440\u043e\u0434\u0435 <code>-v<\/code> \u0438\u043b\u0438 <code>--verbose<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0439\u0442\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b<\/strong> \u2014 \u0444\u0430\u0439\u043b\u044b \u043b\u043e\u0433\u043e\u0432, \u043e\u0442\u0447\u0451\u0442\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0432 \u043e\u0442\u043b\u0430\u0434\u043a\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0435<\/strong> \u2014 \u043d\u0435 \u043c\u0435\u043d\u044f\u0439\u0442\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/p>\n<\/li>\n<\/ol>\n<p>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 CI\/CD \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0439, \u043d\u043e \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0438 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041f\u043e\u043c\u043d\u0438\u0442\u0435: \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 CI \u043f\u0430\u0434\u0430\u0435\u0442 \u2014 \u0432\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u043b\u043e\u0433, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0435\u0451 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c. \u042d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0432\u0430 \u2014 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0441\u0435 \u0443\u043b\u0438\u043a\u0438, \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h2>\u0425\u043e\u0440\u043e\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD<\/h2>\n<h3>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 pipeline<\/h3>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 CI\/CD pipeline \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0445\u043e\u0440\u043e\u0448\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u2014 \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u043c. \u0412\u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0432\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<h4>\u041c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430<\/h4>\n<p>\u041a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0432 CI\/CD \u0441\u0442\u043e\u0438\u0442 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430. \u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0431\u043b\u043e\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.<\/p>\n<p><strong>\u0412 GitHub Actions<\/strong> \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f:<\/p>\n<p><strong>Composite actions<\/strong> \u2014 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:<\/p>\n<pre><code class=\"yaml\"># .github\/actions\/setup-project\/action.yml name: 'Setup Project' description: 'Sets up Node.js and installs dependencies' runs:   using: \"composite\"   steps:     - uses: actions\/setup-node@v3       with:         node-version: '16'         cache: 'npm'     - run: npm ci       shell: bash <\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435:<\/p>\n<pre><code class=\"yaml\">steps:   - uses: actions\/checkout@v3   - uses: .\/.github\/actions\/setup-project   - run: npm test<\/code><\/pre>\n<p><strong>Reusable workflows<\/strong> \u2014 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 workflow:<\/p>\n<pre><code class=\"yaml\"># .github\/workflows\/reusable-test.yml name: Reusable test workflow on:   workflow_call:     inputs:       node-version:         required: false         default: '16'         type: string  jobs:   test:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - uses: actions\/setup-node@v3         with:           node-version: ${{ inputs.node-version }}       - run: npm ci       - run: npm test<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435:<\/p>\n<pre><code class=\"yaml\">jobs:   call-test-workflow:     uses: .\/.github\/workflows\/reusable-test.yml     with:       node-version: '18'<\/code><\/pre>\n<p><strong>\u0412 GitLab CI<\/strong> \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f:<\/p>\n<p><strong>Includes<\/strong> \u2014 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432:<\/p>\n<pre><code class=\"yaml\">include:   - local: 'ci\/build.yml'   - local: 'ci\/test.yml'   - project: 'my-group\/my-project'     file: '\/templates\/deploy.yml'<\/code><\/pre>\n<p><strong>Extends<\/strong> \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"yaml\"># ci\/templates.yml .base-job:   image: node:16   before_script:     - npm ci  # .gitlab-ci.yml include:   - local: 'ci\/templates.yml'  test:   extends: .base-job   script:     - npm test<\/code><\/pre>\n<p><strong>Anchors<\/strong> \u2014 \u044f\u043a\u043e\u0440\u044f \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u0431\u043b\u043e\u043a\u043e\u0432:<\/p>\n<pre><code class=\"yaml\">.setup: &amp;setup   - npm ci   - npm run build  test:   script:     - *setup     - npm test  lint:   script:     - *setup     - npm run lint<\/code><\/pre>\n<h3>\u0418\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 job-\u043e\u0432 \u0438 \u0448\u0430\u0433\u043e\u0432<\/h3>\n<p>\u0425\u043e\u0440\u043e\u0448\u0438\u0435 \u0438\u043c\u0435\u043d\u0430 \u0434\u0435\u043b\u0430\u044e\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u043e\u0442\u043b\u0430\u0434\u043a\u0443:<\/p>\n<pre><code class=\"yaml\"># \u041f\u043b\u043e\u0445\u043e job1:   steps:     - run: npm ci     - run: npm test  # \u0425\u043e\u0440\u043e\u0448\u043e install-and-test:   steps:     - name: Install dependencies       run: npm ci     - name: Run unit tests       run: npm test<\/code><\/pre>\n<p>\u041f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0441\u0442\u0438\u043b\u044f \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0438\u043c\u0435\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0440\u0430\u0436\u0430\u044e\u0442 \u0441\u0443\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<h4>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p>\u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0432 YAML-\u0444\u0430\u0439\u043b\u0430\u0445 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/p>\n<pre><code class=\"yaml\">jobs:   deploy:     # \u042d\u0442\u043e\u0442 job \u0434\u0435\u043f\u043b\u043e\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 staging, \u0434\u043b\u044f production \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 deploy-prod     environment: staging     steps:       # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c --force, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u044b \u0441 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438       - name: Deploy to server         run: rsync --force -avz .\/dist\/ user@server:\/var\/www\/<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b <code>CONTRIBUTING.md<\/code> \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c CI\/CD-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0434\u043b\u044f \u043d\u043e\u0432\u044b\u0445 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<h4>\u0412\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 actions\/images<\/h4>\n<p>\u0412\u0441\u0435\u0433\u0434\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 actions \u0438 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432:<\/p>\n<pre><code class=\"yaml\"># \u041f\u043b\u043e\u0445\u043e - \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u043e\u043c\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 action - uses: actions\/checkout@master  # \u0425\u043e\u0440\u043e\u0448\u043e - \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f - uses: actions\/checkout@v3<\/code><\/pre>\n<pre><code class=\"yaml\"># \u041f\u043b\u043e\u0445\u043e - \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u043e\u043c\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043e\u0431\u0440\u0430\u0437\u0430 image: node  # \u0425\u043e\u0440\u043e\u0448\u043e - \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f image: node:16.14.2<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0430\u0448\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u043c\u0438 \u0438 \u0437\u0430\u0449\u0438\u0449\u0430\u0435\u0442 \u043e\u0442 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u0445.<\/p>\n<h3>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/h3>\n<p>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 CI\/CD \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e, \u044d\u0442\u043e \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u0412\u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0432\u0430\u0448\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b:<\/p>\n<h4>\u041a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432<\/h4>\n<p><strong>\u0412 GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   build:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3              - uses: actions\/setup-node@v3         with:           node-version: '16'           cache: 'npm'                  - name: Install dependencies         run: npm ci                - name: Build         run: npm run build                - name: Cache build output         uses: actions\/cache@v3         with:           path: dist           key: ${{ runner.os }}-build-${{ github.sha }}<\/code><\/pre>\n<p><strong>\u0412 GitLab CI<\/strong>:<\/p>\n<pre><code class=\"yaml\">build:   stage: build   script:     - npm ci     - npm run build   cache:     key: ${CI_COMMIT_REF_SLUG}     paths:       - node_modules\/   artifacts:     paths:       - dist\/<\/code><\/pre>\n<h4>\u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447<\/h4>\n<p>\u041d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e:<\/p>\n<p><strong>\u0412 GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   lint:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - run: npm ci       - run: npm run lint    test:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - run: npm ci       - run: npm test          # \u042d\u0442\u043e\u0442 job \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f lint \u0438 test   build:     needs: [lint, test]     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - run: npm ci       - run: npm run build<\/code><\/pre>\n<p><strong>\u0412 GitLab CI<\/strong>:<\/p>\n<pre><code class=\"yaml\">stages:   - validate   - build  lint:   stage: validate   script:     - npm ci     - npm run lint  test:   stage: validate   script:     - npm ci     - npm test  build:   stage: build   script:     - npm ci     - npm run build<\/code><\/pre>\n<h4>\u0423\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432<\/h4>\n<p>\u041d\u0435 \u0432\u0441\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043a\u043e\u043c\u043c\u0438\u0442\u0435:<\/p>\n<pre><code class=\"yaml\">jobs:   e2e-tests:     runs-on: ubuntu-latest     # \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c e2e-\u0442\u0435\u0441\u0442\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f PR \u0432 main \u0438\u043b\u0438 \u043f\u0440\u0438 \u043f\u0443\u0448\u0435 \u0432 main     if: github.event_name == 'pull_request' &amp;&amp; github.base_ref == 'main' || github.ref == 'refs\/heads\/main'     steps:       - uses: actions\/checkout@v3       - run: npm ci       - run: npm run test:e2e<\/code><\/pre>\n<h4>\u041c\u0430\u0442\u0440\u0438\u0446\u044b \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0430\u0445<\/h4>\n<p>\u041c\u0430\u0442\u0440\u0438\u0446\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 job \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438:<\/p>\n<p><strong>\u0412 GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   test:     runs-on: ${{ matrix.os }}     strategy:       matrix:         os: [ubuntu-latest, windows-latest, macos-latest]         node-version: [14, 16, 18]     steps:       - uses: actions\/checkout@v3       - uses: actions\/setup-node@v3         with:           node-version: ${{ matrix.node-version }}       - run: npm ci       - run: npm test<\/code><\/pre>\n<p><strong>\u0412 GitLab CI<\/strong>:<\/p>\n<pre><code class=\"yaml\">test:   parallel:     matrix:       - NODE_VERSION: [14, 16, 18]         OS: [linux, windows]   script:     - npm ci     - npm test<\/code><\/pre>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/h3>\n<p>CI\/CD \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0435\u0449\u0451 \u043f\u043e\u043b\u0435\u0437\u043d\u0435\u0435, \u043a\u043e\u0433\u0434\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<h4>\u0411\u0435\u0439\u0434\u0436\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0432 README<\/h4>\n<p>\u0411\u0435\u0439\u0434\u0436\u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<p><strong>GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"markdown\">![CI Status](https:\/\/github.com\/username\/repo\/actions\/workflows\/ci.yml\/badge.svg) <\/code><\/pre>\n<p><strong>GitLab CI<\/strong>:<\/p>\n<pre><code class=\"markdown\">[![pipeline status](https:\/\/gitlab.com\/username\/repo\/badges\/main\/pipeline.svg)](https:\/\/gitlab.com\/username\/repo\/-\/commits\/main) <\/code><\/pre>\n<h4>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447<\/h4>\n<p>CI\/CD \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u0434\u0430\u0447:<\/p>\n<p><strong>GitHub Actions \u0441 Jira<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   update-jira:     runs-on: ubuntu-latest     steps:       - name: Jira Login         uses: atlassian\/gajira-login@v3         env:           JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}           JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}           JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}                  - name: Update Jira issue         uses: atlassian\/gajira-transition@v3         with:           issue: ${{ github.event.pull_request.title | regex_match('^([A-Z]+-[0-9]+)') }}           transition: \"In Review\"<\/code><\/pre>\n<h4>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0432 PR\/MR<\/h4>\n<p>CI\/CD \u043c\u043e\u0436\u0435\u0442 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a:<\/p>\n<p><strong>GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   comment:     runs-on: ubuntu-latest     steps:       - name: Comment PR         uses: actions\/github-script@v6         with:           github-token: ${{ secrets.GITHUB_TOKEN }}           script: |             github.rest.issues.createComment({               issue_number: context.issue.number,               owner: context.repo.owner,               repo: context.repo.repo,               body: '\u2705 Tests passed successfully!'             })<\/code><\/pre>\n<h4>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b<\/h4>\n<p>CI\/CD \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \u0441\u0431\u043e\u0440\u043a\u0438:<\/p>\n<p><strong>GitHub Actions \u0441 Slack<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   notify:     runs-on: ubuntu-latest     steps:       - name: Slack Notification         uses: rtCamp\/action-slack-notify@v2         env:           SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}           SLACK_CHANNEL: ci-notifications           SLACK_TITLE: Build Result           SLACK_MESSAGE: 'Build ${{ job.status }}'           SLACK_COLOR: ${{ job.status == 'success' &amp;&amp; 'good' || 'danger' }}<\/code><\/pre>\n<h3>\u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430<\/h3>\n<p>\u0421 \u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0430\u0441\u0442\u0451\u0442 \u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c CI\/CD. \u0412\u043e\u0442 \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u043c:<\/p>\n<h4>\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447:<\/p>\n<p><strong>GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\"># .github\/workflow-templates\/node-test.yml name: Node.js Test on:   push:     branches: [ main ]   pull_request:     branches: [ main ] jobs:   test:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - uses: actions\/setup-node@v3         with:           node-version: '16'       - run: npm ci       - run: npm test<\/code><\/pre>\n<p><strong>GitLab CI<\/strong>:<\/p>\n<pre><code class=\"yaml\"># gitlab-ci-templates\/node-test.yml .node-test:   image: node:16   script:     - npm ci     - npm test<\/code><\/pre>\n<h4>\u0421\u0430\u043c\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 workflow<\/h4>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0433\u043e\u0432\u043e\u0440\u044f\u0449\u0438\u0435 \u0438\u043c\u0435\u043d\u0430 \u0438 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438:<\/p>\n<pre><code class=\"yaml\">name: Deploy to Production  # \u042d\u0442\u043e\u0442 workflow \u0434\u0435\u043f\u043b\u043e\u0438\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0441\u0435\u0440\u0432\u0435\u0440 # \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u0435\u0433\u0430 \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c 'v' # \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u044f \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b DevOps  on:   push:     tags:       - 'v*'  jobs:   # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442   test:     runs-on: ubuntu-latest     steps:       # ...    # \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0430   build:     needs: test     runs-on: ubuntu-latest     steps:       # ...    # \u0414\u0435\u043f\u043b\u043e\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0435)   deploy:     needs: build     environment:       name: production       url: https:\/\/example.com     runs-on: ubuntu-latest     steps:       # ... <\/code><\/pre>\n<h4>\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 CI\/CD<\/h4>\n<p>\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0443\u0437\u043a\u0438\u0435 \u043c\u0435\u0441\u0442\u0430:<\/p>\n<p><strong>GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   benchmark:     runs-on: ubuntu-latest     steps:       - name: Start timer         run: echo \"start_time=$(date +%s)\" &gt;&gt; $GITHUB_ENV                - name: Run your task         run: npm run build                - name: Calculate duration         run: |           end_time=$(date +%s)           duration=$((end_time - ${{ env.start_time }}))           echo \"Task took $duration seconds\"<\/code><\/pre>\n<p><strong>GitLab CI<\/strong> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e \u043c\u0435\u0442\u0440\u0438\u043a\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e job-\u0430.<\/p>\n<h4>\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439<\/h4>\n<p>\u041f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 CI\/CD-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0442\u043a\u0443 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u044d\u0442\u043e\u0439 \u0432\u0435\u0442\u043a\u0435<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 PR\/MR \u0434\u043b\u044f \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043b\u0438\u044f\u043d\u0438\u044f \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043b\u0435\u0434\u0438\u0442\u0435 \u0437\u0430 \u043f\u0435\u0440\u0432\u044b\u043c\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ol>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 CI\/CD \u2014 \u044d\u0442\u043e \u0438\u043d\u0432\u0435\u0441\u0442\u0438\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u043a\u0443\u043f\u0430\u0435\u0442\u0441\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0435\u0439 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u0435\u043c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430. \u041a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u043b \u0410\u0432\u0440\u0430\u0430\u043c \u041b\u0438\u043d\u043a\u043e\u043b\u044c\u043d: &#171;\u0414\u0430\u0439\u0442\u0435 \u043c\u043d\u0435 \u0448\u0435\u0441\u0442\u044c \u0447\u0430\u0441\u043e\u0432 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0440\u0443\u0431\u0438\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e, \u0438 \u044f \u043f\u043e\u0442\u0440\u0430\u0447\u0443 \u043f\u0435\u0440\u0432\u044b\u0435 \u0447\u0435\u0442\u044b\u0440\u0435 \u043d\u0430 \u0437\u0430\u0442\u043e\u0447\u043a\u0443 \u0442\u043e\u043f\u043e\u0440\u0430&#187;. \u0412\u0440\u0435\u043c\u044f, \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 CI\/CD, \u2014 \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0437\u0430\u0442\u043e\u0447\u043a\u0430 \u0432\u0430\u0448\u0435\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<h2>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438<\/h2>\n<h3>\u041c\u0430\u0442\u0440\u0438\u0446\u044b \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445: \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445, \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0431\u044b\u043b\u043e \u0431\u044b \u043a\u0440\u0430\u0439\u043d\u0435 \u0443\u0442\u043e\u043c\u0438\u0442\u0435\u043b\u044c\u043d\u043e. \u0417\u0434\u0435\u0441\u044c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 <strong>\u043c\u0430\u0442\u0440\u0438\u0446\u044b<\/strong> \u2014 \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 CI\/CD \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445.<\/p>\n<h4>\u041a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446 \u0432 CI\/CD<\/h4>\n<p>\u041c\u0430\u0442\u0440\u0438\u0446\u0430 \u2014 \u044d\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u0446\u0438\u0439 \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 job-\u0430 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 job \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0435 \u043e\u0434\u043d\u0443 \u043c\u0430\u0442\u0440\u0438\u0446\u0443, \u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 CI\/CD \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u043c\u0430\u0442\u0440\u0438\u0446:<\/p>\n<ul>\n<li>\n<p>\u0412\u0435\u0440\u0441\u0438\u0438 \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (Node.js 14, 16, 18)<\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (Linux, Windows, macOS)<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u0441\u0438\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 (Chrome, Firefox, Safari)<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (React 16, 17, 18)<\/p>\n<\/li>\n<\/ul>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0442\u0440\u0438\u0446 \u0432 GitHub Actions<\/h4>\n<p>\u0412 GitHub Actions \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043b\u044e\u0447\u0430 <code>strategy.matrix<\/code>:<\/p>\n<pre><code class=\"yaml\">jobs:   test:     runs-on: ${{ matrix.os }}     strategy:       matrix:         os: [ubuntu-latest, windows-latest, macos-latest]         node-version: [14, 16, 18]         # \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f         exclude:           # \u041d\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c Node.js 14 \u043d\u0430 macOS           - os: macos-latest             node-version: 14         # \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438         include:           # \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c Node.js 12 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 Ubuntu           - os: ubuntu-latest             node-version: 12     steps:       - uses: actions\/checkout@v3       - name: Use Node.js ${{ matrix.node-version }}         uses: actions\/setup-node@v3         with:           node-version: ${{ matrix.node-version }}       - run: npm ci       - run: npm test<\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043e 8 job-\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>Ubuntu + Node.js 14<\/p>\n<\/li>\n<li>\n<p>Ubuntu + Node.js 16<\/p>\n<\/li>\n<li>\n<p>Ubuntu + Node.js 18<\/p>\n<\/li>\n<li>\n<p>Ubuntu + Node.js 12 (\u0438\u0437 include)<\/p>\n<\/li>\n<li>\n<p>Windows + Node.js 14<\/p>\n<\/li>\n<li>\n<p>Windows + Node.js 16<\/p>\n<\/li>\n<li>\n<p>Windows + Node.js 18<\/p>\n<\/li>\n<li>\n<p>macOS + Node.js 16<\/p>\n<\/li>\n<li>\n<p>macOS + Node.js 18<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f macOS + Node.js 14 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>exclude<\/code>.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0442\u0440\u0438\u0446 \u0432 GitLab CI<\/h3>\n<p>\u0412 GitLab CI \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043b\u044e\u0447\u0430 <code>parallel.matrix<\/code>:<\/p>\n<pre><code class=\"yaml\">test:   parallel:     matrix:       - OS: [ubuntu, windows]         NODE_VERSION: [14, 16, 18]   script:     - echo \"Testing on $OS with Node.js $NODE_VERSION\"     - npm ci     - npm test<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 6 job-\u043e\u0432 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0439 OS \u0438 NODE_VERSION.<\/p>\n<h4>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0447\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a<\/h4>\n<p>\u041c\u0430\u0442\u0440\u0438\u0446\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e job-\u043e\u0432, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u0412\u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0432\u0435\u0442\u043e\u0432 \u043f\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ol>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/strong> \u0434\u043b\u044f \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0445 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f<\/strong> \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u043f\u0430\u0434\u0430\u044e\u0442 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u041e\u0421, \u043d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0445<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0435\u0448\u0438\u0440\u0443\u0439\u0442\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/strong> \u0434\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b<\/strong> \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e LTS-\u0432\u0435\u0440\u0441\u0438\u0438 Node.js \u043d\u0430 \u0432\u0441\u0435\u0445 \u041e\u0421, \u0430 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u041e\u0421<\/p>\n<\/li>\n<\/ol>\n<h3>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u043c\u0438<\/h3>\n<p>\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 CI\/CD \u0447\u0430\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f: \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434, \u043e\u0442\u0447\u0451\u0442\u044b \u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0442.\u0434. \u0422\u0430\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f <strong>\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u043c\u0438<\/strong>.<\/p>\n<h4>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b<\/h4>\n<p>\u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u2014 \u044d\u0442\u043e \u0444\u0430\u0439\u043b\u044b, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f pipeline, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f job-\u0430. \u041e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0441\u0431\u043e\u0440\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 job-\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0442\u0447\u0451\u0442\u044b \u043e \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0438 \u043a\u043e\u0434\u0430)<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b)<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0430\u0440\u0445\u0438\u0432\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043b\u043e\u0433\u0438 \u0438\u043b\u0438 \u0441\u043d\u0438\u043c\u043a\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u0440\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432)<\/p>\n<\/li>\n<\/ul>\n<h4>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 job-\u0430\u043c\u0438<\/h4>\n<p><strong>\u0412 GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   build:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Build         run: npm run build       - name: Upload build artifacts         uses: actions\/upload-artifact@v3         with:           name: build-files           path: dist\/           retention-days: 7  # \u0425\u0440\u0430\u043d\u0438\u0442\u044c 7 \u0434\u043d\u0435\u0439    deploy:     needs: build     runs-on: ubuntu-latest     steps:       - name: Download build artifacts         uses: actions\/download-artifact@v3         with:           name: build-files           path: dist\/       - name: Deploy         run: .\/deploy.sh<\/code><\/pre>\n<p><strong>\u0412 GitLab CI<\/strong>:<\/p>\n<pre><code class=\"yaml\">build:   stage: build   script:     - npm run build   artifacts:     paths:       - dist\/     expire_in: 1 week  # \u0425\u0440\u0430\u043d\u0438\u0442\u044c 1 \u043d\u0435\u0434\u0435\u043b\u044e  deploy:   stage: deploy   script:     - .\/deploy.sh   dependencies:     - build  # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0438\u0437 job-\u0430 build<\/code><\/pre>\n<h4>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f<\/h4>\n<p>\u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 GitHub \u0438\u043b\u0438 GitLab \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f workflow\/pipeline. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0438\u043b\u0438 \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0434\u0435\u043f\u043b\u043e\u044f.<\/p>\n<p><strong>\u0412 GitHub Actions<\/strong> \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 workflow.<\/p>\n<p><strong>\u0412 GitLab CI<\/strong> \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 job-\u0430 \u0438\u043b\u0438 pipeline.<\/p>\n<h4>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432<\/h4>\n<p>\u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442 \u043c\u0435\u0441\u0442\u043e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0430\u0436\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c:<\/p>\n<ol>\n<li>\n<p><strong>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u0441\u0440\u043e\u043a \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f<\/strong> \u2014 \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0434\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u043d\u0443\u0436\u043d\u043e<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u043c\u0435\u0440<\/strong> \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0439\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/strong> \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0439\u0442\u0435 node_modules<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"yaml\"># GitHub Actions - uses: actions\/upload-artifact@v3   with:     name: build-files     path: |       dist\/       !dist\/**\/*.map  # \u0418\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c source maps     retention-days: 3  # GitLab CI artifacts:   paths:     - dist\/   exclude:     - dist\/**\/*.map  # \u0418\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c source maps   expire_in: 3 days<\/code><\/pre>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u043c\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c\u0438<\/h3>\n<p>\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a AWS, Azure \u0438\u043b\u0438 Google Cloud. CI\/CD \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441.<\/p>\n<h4>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 AWS, Azure, GCP<\/h4>\n<p><strong>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 AWS \u0441 GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   deploy:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3              - name: Configure AWS credentials         uses: aws-actions\/configure-aws-credentials@v1         with:           aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}           aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}           aws-region: us-east-1                  - name: Deploy to S3         run: aws s3 sync .\/dist s3:\/\/my-bucket\/ --delete                - name: Invalidate CloudFront cache         run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CF_DISTRIBUTION_ID }} --paths \"\/*\" <\/code><\/pre>\n<p><strong>\u0414\u0435\u043f\u043b\u043e\u0439 \u0432 Azure \u0441 GitLab CI<\/strong>:<\/p>\n<pre><code class=\"yaml\">deploy:   stage: deploy   image: mcr.microsoft.com\/azure-cli   script:     - az login --service-principal -u $AZURE_SP_CLIENT_ID -p $AZURE_SP_CLIENT_SECRET --tenant $AZURE_TENANT_ID     - az webapp deployment source config-zip --resource-group myResourceGroup --name myWebApp --src dist.zip<\/code><\/pre>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 CLI \u0438 SDK<\/h4>\n<p>\u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 CLI-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 SDK, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 CI\/CD:<\/p>\n<ul>\n<li>\n<p>AWS: aws-cli, AWS SDK<\/p>\n<\/li>\n<li>\n<p>Azure: azure-cli, Azure SDK<\/p>\n<\/li>\n<li>\n<p>Google Cloud: gcloud, Google Cloud SDK<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u0445 \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 actions\/images.<\/p>\n<h4>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 CI\/CD<\/h4>\n<p>CI\/CD \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 Infrastructure as Code (IaC):<\/p>\n<p><strong>Terraform \u0441 GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   terraform:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3              - name: Setup Terraform         uses: hashicorp\/setup-terraform@v2                - name: Terraform Init         run: terraform init                - name: Terraform Plan         run: terraform plan -out=tfplan                - name: Terraform Apply         if: github.ref == 'refs\/heads\/main'         run: terraform apply -auto-approve tfplan<\/code><\/pre>\n<h4>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u043c\u0438 \u0443\u0447\u0435\u0442\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438<\/h4>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u043c\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0443\u0447\u0451\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<ol>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b<\/strong> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0439 \u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0430\u0432\u0430<\/strong> \u2014 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0440\u0430\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0443\u0447\u0451\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/strong> \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, AWS STS \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0440\u043e\u0442\u0430\u0446\u0438\u044e \u043a\u043b\u044e\u0447\u0435\u0439<\/strong> \u2014 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0439\u0442\u0435 \u043a\u043b\u044e\u0447\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430<\/p>\n<\/li>\n<\/ol>\n<h2>\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0438 CI\/CD<\/h2>\n<p>\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0441\u0442\u0430\u043b\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u043c \u0434\u043b\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. CI\/CD \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438.<\/p>\n<h3>\u0421\u0431\u043e\u0440\u043a\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432<\/h3>\n<p><strong>GitHub Actions<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   build-and-push:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3              - name: Set up Docker Buildx         uses: docker\/setup-buildx-action@v2                - name: Login to DockerHub         uses: docker\/login-action@v2         with:           username: ${{ secrets.DOCKERHUB_USERNAME }}           password: ${{ secrets.DOCKERHUB_TOKEN }}                  - name: Build and push         uses: docker\/build-push-action@v3         with:           context: .           push: true           tags: username\/app:latest,username\/app:${{ github.sha }}           cache-from: type=registry,ref=username\/app:buildcache           cache-to: type=registry,ref=username\/app:buildcache,mode=max<\/code><\/pre>\n<p><strong>GitLab CI<\/strong>:<\/p>\n<pre><code class=\"yaml\">build:   image: docker:20.10.16   services:     - docker:20.10.16-dind   variables:     DOCKER_TLS_CERTDIR: \"\/certs\"   script:     - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY     - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .     - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA     - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest     - docker push $CI_REGISTRY_IMAGE:latest<\/code><\/pre>\n<h4>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u0445<\/h4>\n<p>\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u0443\u044e \u0441\u0440\u0435\u0434\u0443 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"yaml\"># GitHub Actions jobs:   test:     runs-on: ubuntu-latest     container:       image: node:16     services:       postgres:         image: postgres:13         env:           POSTGRES_PASSWORD: postgres         options: &gt;-           --health-cmd pg_isready           --health-interval 10s           --health-timeout 5s           --health-retries 5     steps:       - uses: actions\/checkout@v3       - run: npm ci       - run: npm test<\/code><\/pre>\n<pre><code class=\"yaml\"># GitLab CI test:   image: node:16   services:     - postgres:13   variables:     POSTGRES_PASSWORD: postgres   script:     - npm ci     - npm test<\/code><\/pre>\n<h4>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u0440\u0435\u0435\u0441\u0442\u0440\u0430\u043c\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432<\/h4>\n<p>CI\/CD \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u044b \u0432 \u0440\u0435\u0435\u0441\u0442\u0440\u044b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>Docker Hub<\/p>\n<\/li>\n<li>\n<p>GitHub Container Registry<\/p>\n<\/li>\n<li>\n<p>GitLab Container Registry<\/p>\n<\/li>\n<li>\n<p>AWS ECR<\/p>\n<\/li>\n<li>\n<p>Google Container Registry<\/p>\n<\/li>\n<li>\n<p>Azure Container Registry<\/p>\n<\/li>\n<\/ul>\n<h4>\u041e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 CI\/CD<\/h4>\n<p>CI\/CD \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a Kubernetes:<\/p>\n<p><strong>GitHub Actions \u0441 Kubernetes<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   deploy:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3              - name: Set up kubeconfig         uses: azure\/k8s-set-context@v3         with:           kubeconfig: ${{ secrets.KUBE_CONFIG }}                  - name: Deploy to Kubernetes         run: |           kubectl apply -f k8s\/deployment.yaml           kubectl rollout status deployment\/my-app<\/code><\/pre>\n<p><strong>GitLab CI \u0441 Kubernetes<\/strong>:<\/p>\n<pre><code class=\"yaml\">deploy:   image: bitnami\/kubectl:latest   script:     - kubectl config set-cluster k8s --server=\"$KUBE_URL\" --insecure-skip-tls-verify=true     - kubectl config set-credentials admin --token=\"$KUBE_TOKEN\"     - kubectl config set-context default --cluster=k8s --user=admin     - kubectl config use-context default     - kubectl apply -f k8s\/deployment.yaml     - kubectl rollout status deployment\/my-app<\/code><\/pre>\n<p>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 CI\/CD \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u043e\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u042d\u0442\u043e \u043a\u0430\u043a \u0448\u0432\u0435\u0439\u0446\u0430\u0440\u0441\u043a\u0438\u0439 \u043d\u043e\u0436 \u0434\u043b\u044f DevOps-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430 \u2014 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435.<\/p>\n<h2>\u0422\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u044f \u0438 \u0433\u043b\u043e\u0441\u0441\u0430\u0440\u0438\u0439<\/h2>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u043c\u0438\u0440\u0443 CI\/CD, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0442\u044c \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u0425\u043e\u0440\u043e\u0448\u0435\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043e\u0441\u0432\u043e\u0438\u0442\u044c\u0441\u044f \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0435\u0435 \u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u0441 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438.<\/p>\n<h3>Branch (\u0432\u0435\u0442\u043a\u0430)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043a\u043e\u0434\u0430 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 Git, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0412 CI\/CD \u0432\u0435\u0442\u043a\u0438 \u0447\u0430\u0441\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442, \u043a\u0430\u043a\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0443\u0448 \u0432 \u0432\u0435\u0442\u043a\u0443 <code>main<\/code> \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0434\u0435\u043f\u043b\u043e\u044f, \u0430 \u043f\u0443\u0448 \u0432 \u0432\u0435\u0442\u043a\u0443 <code>feature\/*<\/code> \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">on:   push:     branches: [ main, develop ]<\/code><\/pre>\n<h3>Tag (\u043c\u0435\u0442\u043a\u0430)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u0432 Git, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u043d\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0438\u0442, \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0440\u0435\u043b\u0438\u0437\u043e\u0432.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0422\u0435\u0433\u0438 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0434\u0435\u043f\u043b\u043e\u044f \u0438\u043b\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0440\u0435\u043b\u0438\u0437\u043e\u0432.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">on:   push:     tags:       - 'v*'  # \u041b\u044e\u0431\u043e\u0439 \u0442\u0435\u0433, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u0441 'v'<\/code><\/pre>\n<h3>Environment (\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0421\u0440\u0435\u0434\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0434 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0420\u0430\u0437\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">deploy:   environment:     name: production     url: https:\/\/example.com<\/code><\/pre>\n<h3>Secret (\u0441\u0435\u043a\u0440\u0435\u0442)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0417\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043f\u0430\u0440\u043e\u043b\u0438, \u0442\u043e\u043a\u0435\u043d\u044b API \u0438\u043b\u0438 \u043a\u043b\u044e\u0447\u0438 SSH.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0421\u0435\u043a\u0440\u0435\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 CI\/CD-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u0445.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">steps:   - name: Deploy     env:       API_TOKEN: ${{ secrets.API_TOKEN }}<\/code><\/pre>\n<h3>Artifact (\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0424\u0430\u0439\u043b \u0438\u043b\u0438 \u043d\u0430\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f CI\/CD-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 job-\u0430\u043c\u0438 \u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0430.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">- name: Upload artifact   uses: actions\/upload-artifact@v3   with:     name: build-files     path: dist\/<\/code><\/pre>\n<h3>Cache (\u043a\u0435\u0448)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0412\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043c\u0438 CI\/CD \u0434\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u041a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (node_modules, vendor \u0438 \u0442.\u0434.), \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0438\u0445 \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">- name: Cache dependencies   uses: actions\/cache@v3   with:     path: ~\/.npm     key: ${{ runner.os }}-node-${{ hashFiles('**\/package-lock.json') }}<\/code><\/pre>\n<h3>Matrix (\u043c\u0430\u0442\u0440\u0438\u0446\u0430)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f \u0432 CI\/CD, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 job \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u041e\u0421 \u0438\u043b\u0438 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u044f\u0437\u044b\u043a\u0430).<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u041c\u0430\u0442\u0440\u0438\u0446\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445 \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">strategy:   matrix:     os: [ubuntu-latest, windows-latest]     node-version: [14, 16, 18]<\/code><\/pre>\n<h3>Manual job (\u0440\u0443\u0447\u043d\u043e\u0439 \u0437\u0430\u043f\u0443\u0441\u043a)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: Job, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 CI\/CD-\u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0420\u0443\u0447\u043d\u044b\u0435 job-\u044b \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u0438\u043b\u0438 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u0445 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\"># GitHub Actions jobs:   deploy:     environment:       name: production     # \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 GitHub  # GitLab CI deploy:   when: manual<\/code><\/pre>\n<h3>Runner (\u0440\u0430\u043d\u043d\u0435\u0440)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0421\u0435\u0440\u0432\u0435\u0440 \u0438\u043b\u0438 \u0430\u0433\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 CI\/CD.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0420\u0430\u043d\u043d\u0435\u0440\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0449\u0438\u043c\u0438 (\u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u043c\u0438 GitHub\/GitLab) \u0438\u043b\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0451\u043d\u043d\u044b\u043c\u0438 (self-hosted).<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   build:     runs-on: ubuntu-latest  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u0440\u0430\u043d\u043d\u0435\u0440\u0430 GitHub <\/code><\/pre>\n<h3>Workflow (\u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0412 GitHub Actions \u2014 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0434\u043d\u0443 \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0434\u0430\u0447.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: Workflow \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 YAML \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">name: CI on: [push, pull_request] jobs:   # ...<\/code><\/pre>\n<h3>Pipeline (\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0412 GitLab CI \u2014 \u043d\u0430\u0431\u043e\u0440 job-\u043e\u0432, \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0441\u0442\u0430\u0434\u0438\u044f\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: Pipeline \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 <code>.gitlab-ci.yml<\/code> \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">stages:   - build   - test   - deploy<\/code><\/pre>\n<h3>Job (\u0437\u0430\u0434\u0430\u0447\u0430)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u041d\u0430\u0431\u043e\u0440 \u0448\u0430\u0433\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0440\u0430\u043d\u043d\u0435\u0440\u0435.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: Job-\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   build:     # ...   test:     # ...<\/code><\/pre>\n<h3>Step (\u0448\u0430\u0433)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0412 GitHub Actions \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0438\u043b\u0438 action \u0432\u043d\u0443\u0442\u0440\u0438 job-\u0430.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0428\u0430\u0433\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0448\u0430\u0433\u043e\u0432.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">steps:   - name: Checkout code     uses: actions\/checkout@v3   - name: Build     run: npm run build<\/code><\/pre>\n<h3>Action (\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0412 GitHub Actions \u2014 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: Actions \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c\u0438 (\u043e\u0442 GitHub), \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u043c\u0438 \u0438\u043b\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">- uses: actions\/setup-node@v3   with:     node-version: '16'<\/code><\/pre>\n<h3>Stage (\u0441\u0442\u0430\u0434\u0438\u044f)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0412 GitLab CI \u2014 \u0433\u0440\u0443\u043f\u043f\u0430 job-\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0421\u0442\u0430\u0434\u0438\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c pipeline \u0432 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u044d\u0442\u0430\u043f\u044b.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">stages:   - build   - test   - deploy  build-job:   stage: build   # ...<\/code><\/pre>\n<h3>Trigger (\u0442\u0440\u0438\u0433\u0433\u0435\u0440)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0421\u043e\u0431\u044b\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 workflow \u0438\u043b\u0438 pipeline.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0422\u0440\u0438\u0433\u0433\u0435\u0440\u0430\u043c\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0448\u0438, pull request-\u044b, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0435\u0433\u043e\u0432, \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u0442.\u0434.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">on:   push:     branches: [ main ]   pull_request:     branches: [ main ]   schedule:     - cron: '0 0 * * *'  # \u0415\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e \u0432 \u043f\u043e\u043b\u043d\u043e\u0447\u044c<\/code><\/pre>\n<h3>Self-hosted runner (\u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0451\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u043d\u0435\u0440)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0420\u0430\u043d\u043d\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0435 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 GitHub\/GitLab.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: Self-hosted runner-\u044b \u043f\u043e\u043b\u0435\u0437\u043d\u044b, \u043a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u044e \u0438\u043b\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\">jobs:   build:     runs-on: self-hosted<\/code><\/pre>\n<h3>Dependency (\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c)<\/h3>\n<p><strong>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 CI\/CD \u2014 job, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0434\u0440\u0443\u0433\u043e\u0433\u043e job-\u0430.<\/p>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435<\/strong>: \u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 job-\u043e\u0432.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>:<\/p>\n<pre><code class=\"yaml\"># GitHub Actions jobs:   test:     # ...   deploy:     needs: test     # ...  # GitLab CI deploy:   dependencies:     - test<\/code><\/pre>\n<p>\u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u0432 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u043b\u0443\u0447\u0448\u0435 \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f\u0445, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 CI\/CD. \u041d\u0435 \u0441\u0442\u0435\u0441\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u0433\u043b\u043e\u0441\u0441\u0430\u0440\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0435 \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u0442\u0435\u0440\u043c\u0438\u043d \u2014 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0432\u0441\u044f \u044d\u0442\u0430 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u044f \u0441\u0442\u0430\u043d\u0435\u0442 \u0434\u043b\u044f \u0432\u0430\u0441 \u0432\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u0442\u0443\u0440\u043e\u0439.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412\u043e\u0442 \u043c\u044b \u0438 \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u043a\u043e\u043d\u0446\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u044f \u043f\u043e \u043c\u0438\u0440\u0443 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0433\u043e CI\/CD. \u041c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u0441 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439, \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0443\u043c\u0435\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u0441 \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435\u043c, \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438, \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u0432\u0435\u0434\u0451\u043c \u0438\u0442\u043e\u0433\u0438 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u0443\u0437\u043d\u0430\u043b\u0438.<\/p>\n<h3>\u0427\u0442\u043e \u043c\u044b \u0438\u0437\u0443\u0447\u0438\u043b\u0438<\/h3>\n<p>\u041c\u044b \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c:<\/p>\n<ul>\n<li>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/strong> \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0435\u0442\u043a\u0438 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u2014 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0430\u0448 CI\/CD \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0443\u043c\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0438 \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438<\/strong> \u2014 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043f\u0430\u0440\u043e\u043b\u0435\u0439 \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0432\u0438\u0434\u0435 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u043c\u0438<\/strong> \u2014 \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u043e \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0430, \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0443\u0440\u043e\u0432\u043d\u044f\u043c\u0438 \u0437\u0430\u0449\u0438\u0442\u044b \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0438 \u0440\u0435\u0448\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/strong> \u0432 CI\/CD \u2014 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435, \u0433\u0434\u0435 \u0438\u0441\u043a\u0430\u0442\u044c \u043b\u043e\u0433\u0438 \u0438 \u043a\u0430\u043a \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043b\u0443\u0447\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438<\/strong> \u0434\u043b\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438<\/strong> \u2014 \u043c\u0430\u0442\u0440\u0438\u0446\u044b, \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u043c\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0451 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0430\u0448 CI\/CD \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u0430 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e.<\/p>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044e<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c CI\/CD \u0438\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b, \u0432\u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439:<\/p>\n<ol>\n<li>\n<p><strong>\u041d\u0430\u0447\u0438\u043d\u0430\u0439\u0442\u0435 \u0441 \u043c\u0430\u043b\u043e\u0433\u043e<\/strong> \u2014 \u043d\u0435 \u043f\u044b\u0442\u0430\u0439\u0442\u0435\u0441\u044c \u0441\u0440\u0430\u0437\u0443 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438. \u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0441 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0440\u0443\u0442\u0438\u043d\u0443 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/strong> \u2014 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u0435, \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043e\u0442\u043d\u0438\u043c\u0430\u044e\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0432\u0435\u0441\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0432 \u0442\u0435\u0441\u0442\u044b<\/strong> \u2014 CI\/CD \u0431\u0435\u0437 \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u2014 \u044d\u0442\u043e \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0431\u0430\u0433\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c. \u0427\u0435\u043c \u043b\u0443\u0447\u0448\u0435 \u0432\u0430\u0448\u0438 \u0442\u0435\u0441\u0442\u044b, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u043b\u044c\u0437\u044b \u043e\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b<\/strong> \u2014 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0447\u043b\u0435\u043d\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u0430\u0448 CI\/CD \u0438 \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e<\/strong> \u2014 CI\/CD \u043d\u0435 \u0432\u044b\u0441\u0435\u0447\u0435\u043d \u0432 \u043a\u0430\u043c\u043d\u0435. \u041f\u043e \u043c\u0435\u0440\u0435 \u0440\u043e\u0441\u0442\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0435\u0440\u0435\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0439\u0442\u0435 \u0438 \u0443\u043b\u0443\u0447\u0448\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b.<\/p>\n<\/li>\n<\/ol>\n<h3>\u041f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u044b \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f \u043d\u0430\u0432\u044b\u043a\u043e\u0432 CI\/CD<\/h3>\n<p>\u041c\u0438\u0440 CI\/CD \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0438 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><strong>GitOps<\/strong> \u2014 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 Git<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u044b\u0439 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433<\/strong> \u2014 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0438 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0439 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 CI\/CD<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u043d\u0430\u0440\u0435\u0435\u0447\u043d\u044b\u0435 \u0440\u0435\u043b\u0438\u0437\u044b<\/strong> \u2014 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u0434\u043b\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438<\/strong> \u2014 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d<\/p>\n<\/li>\n<li>\n<p><strong>\u041c\u0430\u0448\u0438\u043d\u043d\u043e\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u0432 CI\/CD<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ML \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u0438\u0437\u044b\u0432 \u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044e<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0437\u043d\u0430\u043d\u0438\u044f \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0445 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435. \u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0441\u0432\u043e\u0438\u0445 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 workflow \u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0441 \u043d\u0443\u043b\u044f. \u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0439\u0442\u0435, \u043d\u0435 \u0431\u043e\u0439\u0442\u0435\u0441\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u2014 CI\/CD \u043a\u0430\u043a \u0440\u0430\u0437 \u0438 \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043b\u043e\u0432\u0438\u0442\u044c \u0438\u0445 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043e\u043d\u0438 \u043f\u043e\u043f\u0430\u0434\u0443\u0442 \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c.<\/p>\n<p>\u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 CI\/CD \u2014 \u044d\u0442\u043e \u043d\u0435 \u0446\u0435\u043b\u044c, \u0430 \u043f\u0443\u0442\u044c. \u041e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0432\u0430\u0448\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439. \u0422\u043e, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0435\u0433\u043e\u0434\u043d\u044f, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0437\u0430\u0432\u0442\u0440\u0430, \u0438 \u044d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<p>\u0418 \u043d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a: \u043f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u0435\u043c, \u0432\u044b \u043f\u0440\u043e\u043a\u0430\u0447\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 CI\/CD \u0434\u043e \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f! \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0430\u0448 \u043a\u043e\u0434 \u0441\u0430\u043c \u0441\u0435\u0431\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0438 \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u2014 \u0430 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u0438\u0442\u044c\u0441\u044f \u0438 \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c\u0438 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438. \u041d\u0443, \u043f\u043e\u0447\u0442\u0438 \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u0438\u0442\u044c\u0441\u044f \u2014 \u0440\u043e\u0431\u043e\u0442\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u0430\u0445\u0432\u0430\u0442\u0438\u043b\u0438 \u043c\u0438\u0440, \u0438 \u043a\u0442\u043e-\u0442\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0430\u043c \u043a\u043e\u0434 \ud83d\ude09<\/p>\n<p>\u0423\u0434\u0430\u0447\u0438 \u0432 \u0432\u0430\u0448\u0438\u0445 CI\/CD-\u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u0445!<\/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\/915370\/\"> https:\/\/habr.com\/ru\/articles\/915370\/<\/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<h4>\u0427\u0430\u0441\u0442\u044c3: CI\/CD \u2013 \u0432\u0435\u0442\u043a\u0438, \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h4>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0434\u043e\u0448\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0432 \u0441\u0435\u0440\u0438\u0438, \u0442\u043e \u0432\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c\u0438 CI\/CD \u0438 \u0434\u0430\u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d. \u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u044e! \u0412\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u0430\u0436\u043d\u044b\u0439 \u0448\u0430\u0433 \u0432 \u043c\u0438\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041d\u043e \u043a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0433\u0434\u0435 \u043f\u043e\u0441\u043b\u0435 &#171;Hello World&#187; \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435, \u0432 CI\/CD \u043f\u043e\u0441\u043b\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u044b\u0439 \u043c\u0438\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439.<\/p>\n<blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043f\u0430\u043b\u0438 \u0441\u044e\u0434\u0430 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e, \u0438\u043b\u0438 \u043d\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0432\u0443\u0445 \u0447\u0430\u0441\u0442\u0435\u0439, \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f:<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/914560\/\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0430\u0441\u0442\u044c 1: \u041e\u0441\u043d\u043e\u0432\u044b CI\/CD \u2013 \u0447\u0442\u043e \u044d\u0442\u043e \u0438 \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u043e; GitHub Actions \u0438 GitLab CI<\/strong><\/a><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/914614\/\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0430\u0441\u0442\u044c 2: \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 GitHub Actions \u0438 GitLab CI \u2013 \u043f\u0435\u0440\u0432\u044b\u0439 workflow \u0438 \u0434\u0435\u043f\u043b\u043e\u0439<\/strong><\/a><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/915370\/\" rel=\"noopener noreferrer nofollow\"><strong>\u0427\u0430\u0441\u0442\u044c3: CI\/CD \u2013 \u0432\u0435\u0442\u043a\u0438, \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/strong><\/a><\/p>\n<p><strong>^ \u0412\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0437\u0434\u0435\u0441\u044c ^<\/strong><\/p>\n<\/blockquote>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0430\u0448 CI\/CD \u043f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0433\u0438\u0431\u043a\u0438\u043c \u0438 \u043c\u043e\u0449\u043d\u044b\u043c. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c:<\/p>\n<ul>\n<li>\n<p><strong>\u0412\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/strong> \u2014 \u043a\u0430\u043a \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0432\u0435\u0441\u0442\u0438 \u0441\u0435\u0431\u044f \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0435\u0442\u043a\u0438 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/strong> \u2014 \u043a\u0430\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 \u044d\u0442\u0430\u043f\u044b<\/strong> \u2014 \u043a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0443\u043f\u0435\u043d\u0447\u0430\u0442\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0430\u043c\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0442\u043b\u0430\u0434\u043a\u0443 \u0438 \u0440\u0430\u0437\u0431\u043e\u0440 \u043e\u0448\u0438\u0431\u043e\u043a<\/strong> \u2014 \u043a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a, \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u0438 \u0442\u0435\u043c\u044b \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u044b \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0421\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0438, \u0430 \u043d\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0438\u0442. \u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043f\u0430\u0440\u043e\u043b\u0438 \u0438 \u0442\u043e\u043a\u0435\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043b\u044c\u0437\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0432\u0438\u0434\u0435. \u0410 \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u2014 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d.<\/p>\n<p>\u041d\u0435 \u0432\u043e\u043b\u043d\u0443\u0439\u0442\u0435\u0441\u044c, \u0435\u0441\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u043a\u0430\u0436\u0443\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438. \u041c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0432\u0441\u0451 \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e, \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c\u0438. \u041a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 CI\/CD-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0438\u0441\u0442\u0435\u0433\u043d\u0438\u0442\u0435 \u0440\u0435\u043c\u043d\u0438 \u2014 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u0432 \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u0435 \u043f\u043e \u043c\u0438\u0440\u0443 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0433\u043e CI\/CD, \u0433\u0434\u0435 \u0432\u0430\u0448 \u043a\u043e\u0434 \u0441\u0430\u043c \u0441\u0435\u0431\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u0442 \u0438 \u0434\u0435\u043f\u043b\u043e\u0438\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a, \u043a\u0430\u043a \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e. \u0418 \u043f\u043e\u043c\u043d\u0438\u0442\u0435: \u043c\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430\u0448 &#171;Hello World&#187; workflow \u0432\u043e \u0432\u0437\u0440\u043e\u0441\u043b\u0443\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445. <\/p>\n<h2>\u0412\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432 workflow<\/h2>\n<h3>\u041a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u044f \u0432 Git \u0438 CI\/CD<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043a\u043e\u0433\u0434\u0430-\u043d\u0438\u0431\u0443\u0434\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441 Git, \u0442\u043e \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0432\u0435\u0442\u043a\u0438 \u2014 \u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u0435\u0433\u043e \u0441\u0430\u043c\u044b\u0445 \u043c\u043e\u0449\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439. \u041e\u043d\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0434 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438, \u043d\u0435 \u043c\u0435\u0448\u0430\u044f \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443. \u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0432\u0435\u0442\u043e\u043a \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><code>main<\/code> (\u0438\u043b\u0438 <code>master<\/code>) \u2014 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f, \u0433\u043e\u0442\u043e\u0432\u0430\u044f \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e<\/p>\n<\/li>\n<li>\n<p><code>develop<\/code> \u2014 \u0432\u0435\u0442\u043a\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u0443\u0434\u0430 \u0441\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>feature\/*<\/code> \u2014 \u0432\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><code>hotfix\/*<\/code> \u2014 \u0441\u0440\u043e\u0447\u043d\u044b\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a<\/p>\n<\/li>\n<li>\n<p><code>release\/*<\/code> \u2014 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u0432\u044b\u043f\u0443\u0441\u043a\u0443 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u043e \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u0434\u043b\u044f CI\/CD? \u0410 \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0432\u0435\u0442\u043a\u0438 \u0440\u0430\u0432\u043d\u044b! \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u0430\u0433\u0430\u0437\u0438\u043d \u043e\u0434\u0435\u0436\u0434\u044b. \u0412\u044b \u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u0436\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u043d\u0435\u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0439 \u044d\u0441\u043a\u0438\u0437 \u043e\u0442 \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u0430? \u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043c\u0438\u0442 \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0442\u043a\u0438.<\/p>\n<p>\u0412\u043e\u0442 \u0433\u0434\u0435 \u043d\u0430 \u0441\u0446\u0435\u043d\u0443 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 <strong>\u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/strong> \u0432 CI\/CD. \u041e\u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0435\u0442\u043a\u0438 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u0439:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043e\u043a <code>feature\/*<\/code> \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>develop<\/code> \u2014 \u043f\u043e\u043b\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>main<\/code> \u2014 \u043f\u043e\u043b\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u043e \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0443 \u0432\u0430\u0441 \u0431\u044b\u043b \u0443\u043c\u043d\u044b\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043d\u0430 \u0444\u0430\u0431\u0440\u0438\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u0437\u0434\u0435\u043b\u0438\u0435\u043c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0435\u0433\u043e \u043c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u043a\u0438.<\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 GitHub Actions<\/h3>\n<p>\u0412 GitHub Actions \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430 \u0434\u0432\u0443\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445:<\/p>\n<ol>\n<li>\n<p><strong>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 workflow<\/strong> \u2014 \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 job \u0438\u043b\u0438 step<\/strong> \u2014 \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430<\/p>\n<\/li>\n<\/ol>\n<h4>\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 workflow<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c workflow \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0432\u0435\u0442\u043e\u043a, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0435\u043a\u0446\u0438\u044e <code>on<\/code>:<\/p>\n<pre><code class=\"yaml\">name: CI Pipeline  on:   push:     branches: [ main, develop, 'feature\/**' ]   pull_request:     branches: [ main, develop ]<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0433\u043e\u0432\u043e\u0440\u0438\u0442: &#171;\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043f\u0440\u0438 \u043f\u0443\u0448\u0435 \u0432 \u0432\u0435\u0442\u043a\u0438 main, develop \u0438\u043b\u0438 \u043b\u044e\u0431\u0443\u044e \u0432\u0435\u0442\u043a\u0443, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0443\u044e\u0441\u044f \u0441 feature\/, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 PR \u0432 main \u0438\u043b\u0438 develop&#187;.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 <code>'feature\/**'<\/code> \u2014 \u044d\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d (pattern), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0441\u0435\u043c \u0432\u0435\u0442\u043a\u0430\u043c, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u043c\u0441\u044f \u0441 <code>feature\/<\/code>. \u0417\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u0438 \u0437\u0434\u0435\u0441\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u0430\u043a \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0437\u043d\u0430\u043a\u0438.<\/p>\n<h4>\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 workflow<\/h4>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 <code>if<\/code> \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 job \u0438\u043b\u0438 step:<\/p>\n<pre><code class=\"yaml\">jobs:   test:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Run tests         run: npm test    deploy-to-staging:     runs-on: ubuntu-latest     needs: test     if: github.ref == 'refs\/heads\/develop'     steps:       - uses: actions\/checkout@v3       - name: Deploy to staging         run: .\/deploy.sh staging    deploy-to-production:     runs-on: ubuntu-latest     needs: test     if: github.ref == 'refs\/heads\/main'     steps:       - uses: actions\/checkout@v3       - name: Deploy to production         run: .\/deploy.sh production <\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0442\u0435\u0441\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u0435\u0442\u043e\u043a, \u043d\u043e \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 staging \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>develop<\/code>, \u0430 \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 production \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>main<\/code>.<\/p>\n<p>\u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <code>github.ref == 'refs\/heads\/main'<\/code> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0432\u0435\u0442\u043a\u0430 main. GitHub Actions \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445:<\/p>\n<ul>\n<li>\n<p><code>github.ref<\/code> \u2014 \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f \u0441\u0441\u044b\u043b\u043a\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>refs\/heads\/main<\/code> \u0438\u043b\u0438 <code>refs\/tags\/v1.0.0<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>github.event_name<\/code> \u2014 \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>push<\/code>, <code>pull_request<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>github.actor<\/code> \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0432\u0448\u0438\u0439 \u0441\u043e\u0431\u044b\u0442\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0438 \u043c\u043d\u043e\u0433\u0438\u0435 <a href=\"https:\/\/docs.github.com\/en\/actions\/writing-workflows\/choosing-what-your-workflow-does\/accessing-contextual-information-about-workflow-runs#github-context\" rel=\"noopener noreferrer nofollow\">\u0434\u0440\u0443\u0433\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 <code>&amp;&amp;<\/code> (\u0418) \u0438 <code>||<\/code> (\u0418\u041b\u0418):<\/p>\n<pre><code class=\"yaml\">if: github.ref == 'refs\/heads\/main' &amp;&amp; github.event_name == 'push'<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u0442\u0438\u043d\u043d\u044b\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u0443\u0448\u0435\u0439 \u0432 \u0432\u0435\u0442\u043a\u0443 main.<\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 GitLab CI<\/h3>\n<p>GitLab CI \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u0435, \u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0434\u043b\u044f \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<h4>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: only\/except<\/h4>\n<p>\u0422\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 GitLab CI \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432 <code>only<\/code> \u0438 <code>except<\/code>:<\/p>\n<pre><code class=\"yaml\">stages:   - test   - deploy  test:   stage: test   script:     - npm test  deploy-staging:   stage: deploy   script:     - .\/deploy.sh staging   only:     - develop  deploy-production:   stage: deploy   script:     - .\/deploy.sh production   only:     - main<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c <code>only: - develop<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 &#171;\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u0435\u0442\u043a\u0438 develop&#187;. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, <code>except<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0434\u043b\u044f \u043a\u0430\u043a\u0438\u0445 \u0432\u0435\u0442\u043e\u043a \u0437\u0430\u0434\u0430\u0447\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u041d\u0415 \u043d\u0443\u0436\u043d\u043e.<\/p>\n<h4>\u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: rules<\/h4>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u044b\u0439 \u0438 \u0433\u0438\u0431\u043a\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>rules<\/code>:<\/p>\n<pre><code class=\"yaml\">deploy-staging:   stage: deploy   script:     - .\/deploy.sh staging   rules:     - if: $CI_COMMIT_BRANCH == \"develop\"       when: on_success     - when: never<\/code><\/pre>\n<p>\u0421\u0435\u043a\u0446\u0438\u044f <code>rules<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0430\u0432\u0438\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u041f\u0435\u0440\u0432\u043e\u0435 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0435\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u0431\u0443\u0434\u0435\u0442 \u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u0432\u0435\u0442\u043a\u0430 \u2014 <code>develop<\/code> \u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0448\u0430\u0433\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u044b. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u043e <code>when: never<\/code>, \u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0430.<\/p>\n<p>GitLab CI \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p><code>$CI_COMMIT_BRANCH<\/code> \u2014 \u0438\u043c\u044f \u0432\u0435\u0442\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code>$CI_PIPELINE_SOURCE<\/code> \u2014 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>push<\/code>, <code>merge_request_event<\/code>)<\/p>\n<\/li>\n<li>\n<p><code>$CI_COMMIT_TAG<\/code> \u2014 \u0438\u043c\u044f \u0442\u0435\u0433\u0430 (\u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c)<\/p>\n<\/li>\n<li>\n<p>\u0438 \u043c\u043d\u043e\u0433\u0438\u0435 <a href=\"https:\/\/docs.gitlab.com\/ci\/variables\/predefined_variables\/\" rel=\"noopener noreferrer nofollow\">\u0434\u0440\u0443\u0433\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u0443\u044f \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"yaml\">rules:   - if: $CI_COMMIT_BRANCH == \"main\" &amp;&amp; $CI_PIPELINE_SOURCE == \"push\"     when: on_success   - if: $CI_COMMIT_BRANCH =~ \/^feature\\\/.*\/     when: manual   - when: never<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442: &#171;\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043b\u044f \u043f\u0443\u0448\u0435\u0439 \u0432 main, \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043b\u044f \u0432\u0435\u0442\u043e\u043a <code>feature\/*<\/code>, \u0438 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432&#187;.<\/p>\n<h4>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u043d\u043e\u0433\u043e workflow<\/h4>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043c\u043e\u0449\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u0435\u0442\u043e\u043a \u2014 \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043e\u043a <code>feature\/*<\/code> \u2014 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u0438\u043d\u0442\u0438\u043d\u0433 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0438\u043f\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>develop<\/code> \u2014 \u0432\u0441\u0451 \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 + e2e-\u0442\u0435\u0441\u0442\u044b + \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0432\u0435\u0442\u043a\u0438 <code>main<\/code> \u2014 \u0432\u0441\u0451 \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 + \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d (\u0441 \u0440\u0443\u0447\u043d\u044b\u043c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c)<\/p>\n<\/li>\n<\/ol>\n<h4>GitHub Actions<\/h4>\n<pre><code class=\"yaml\">name: CI\/CD Pipeline  on:   push:     branches: [ main, develop, 'feature\/**' ]   pull_request:     branches: [ main, develop ]  jobs:   build:     runs-on: ubuntu-latest     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Build         run: npm run build       - name: Run basic tests         run: npm test    lint-and-typecheck:     runs-on: ubuntu-latest     if: startsWith(github.ref, 'refs\/heads\/feature\/')     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Lint         run: npm run lint       - name: Type check         run: npm run typecheck    e2e-tests:     runs-on: ubuntu-latest     needs: [build]     if: github.ref == 'refs\/heads\/develop' || github.ref == 'refs\/heads\/main'     steps:       - uses: actions\/checkout@v3       - name: Set up Node.js         uses: actions\/setup-node@v3         with:           node-version: '16'       - name: Install dependencies         run: npm ci       - name: Run E2E tests         run: npm run test:e2e    deploy-staging:     runs-on: ubuntu-latest     needs: [build, e2e-tests]     if: github.ref == 'refs\/heads\/develop'     steps:       - uses: actions\/checkout@v3       - name: Deploy to staging         run: |           echo \"Deploying to staging environment...\"           # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440    deploy-production:     runs-on: ubuntu-latest     needs: [build, e2e-tests]     if: github.ref == 'refs\/heads\/main'     environment:       name: production       url: https:\/\/example.com     steps:       - uses: actions\/checkout@v3       - name: Deploy to production         run: |           echo \"Deploying to production environment...\"           # \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d<\/code><\/pre>\n<h4>GitLab CI<\/h4>\n<pre><code class=\"yaml\">stages:   - build   - test   - deploy  build:   stage: build   script:     - npm ci     - npm run build<\/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-462020","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/462020","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=462020"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/462020\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=462020"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=462020"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=462020"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}