{"id":466089,"date":"2025-07-04T21:00:21","date_gmt":"2025-07-04T21:00:21","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=466089"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=466089","title":{"rendered":"<span>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c CI\/CD Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0430\u0441\u0442\u044c 3. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432\u0435\u0440\u0441\u0438\u0439 \u0432 Play Store<\/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<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/68a\/77d\/c82\/68a77dc8268406a7c8ff5e6715f4ca19.png\" width=\"2816\" height=\"1536\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/68a\/77d\/c82\/68a77dc8268406a7c8ff5e6715f4ca19.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/68a\/77d\/c82\/68a77dc8268406a7c8ff5e6715f4ca19.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h2>\u041e \u0447\u0451\u043c \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f?<\/h2>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041a\u0438\u0440\u0438\u043b\u043b \u0438 \u044f Android-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 Scanny. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u0442\u043e, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043d\u0430\u0448 CI\/CD, \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c Android (<a href=\"https:\/\/github.com\/MarathonLabs\/marathon\" rel=\"noopener noreferrer nofollow\">Marathon Labs<\/a> \u0438 <a href=\"https:\/\/firebase.google.com\/docs\/test-lab\" rel=\"noopener noreferrer nofollow\">Firebase Test Lab<\/a>) \u0438 Unit-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 Build Flavors \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0432 \u043d\u0430\u0448\u0443 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0441\u0432\u0435\u0436\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u0432 Play Market \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher\" rel=\"noopener noreferrer nofollow\">Gradle Play Publisher<\/a> \u0438 <a href=\"https:\/\/github.com\/fastlane\/fastlane\" rel=\"noopener noreferrer nofollow\">Fastlane<\/a>, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u0432 Gitlab Tag \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0448\u043b\u0438 \u0432 \u043d\u0430\u0448\u0443 \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043c\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u043c \u043d\u0430\u0448 CI\/CD, \u0441\u043e\u0431\u0440\u0430\u0432 \u0441\u0432\u043e\u0439 Docker-\u043e\u0431\u0440\u0430\u0437 \u0441\u043e \u0432\u0441\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u043c. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b (Python, awscli \u0438 \u0434\u0440\u0443\u0433\u0438\u0435), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u043d\u0430\u0448 pipeline.<\/p>\n<p>\u0426\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u0440\u043e CI\/CD \u0434\u043b\u044f Android \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437:<\/p>\n<ol>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/918364\/\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c CI\/CD Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0430\u0441\u0442\u044c 1. \u041d\u0430\u0447\u0430\u043b\u043e.<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/922066\/\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c CI\/CD Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0430\u0441\u0442\u044c 2. \u0417\u0430\u043f\u0443\u0441\u043a Android-\u0442\u0435\u0441\u0442\u043e\u0432.<\/a><\/p>\n<\/li>\n<li>\n<p>\u0412\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0435\u0441\u044c \u0437\u0434\u0435\u0441\u044c.<\/p>\n<\/li>\n<\/ol>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Play Console<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Play Console \u0438 Google Services, \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432 <a href=\"https:\/\/play.google.com\/console\/\" rel=\"noopener noreferrer nofollow\">Play Console<\/a>. \u0422\u0430\u043a \u0436\u0435 \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Play Store, \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0434\u0435\u043b\u0443, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c Google Services \u0441 \u043d\u0430\u0448\u0435\u0439 Play Console, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 <a href=\"https:\/\/console.cloud.google.com\/iam-admin\/serviceaccounts?hl=en\" rel=\"noopener noreferrer nofollow\">Service Accounts<\/a>, \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 <code>Create service account<\/code>. \u0412 \u043d\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u0430 <code>Basic - Viewer<\/code>. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 \u043c\u044b \u0443\u0436\u0435 \u0434\u0435\u043b\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/922066\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e CI\/CD<\/a>, \u043a\u043e\u0433\u0434\u0430 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043b\u0438 Google Services \u0441 Firebase, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443. \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a Service Account \u0441\u043e\u0437\u0434\u0430\u043d, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c JSON-\u043a\u043b\u044e\u0447 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4ae\/dbc\/8a1\/4aedbc8a152ba791b53a69b01fa79a07.png\" width=\"679\" height=\"694\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4ae\/dbc\/8a1\/4aedbc8a152ba791b53a69b01fa79a07.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4ae\/dbc\/8a1\/4aedbc8a152ba791b53a69b01fa79a07.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043d\u0430\u0448 <a href=\"https:\/\/play.google.com\/console\/?hl=en\" rel=\"noopener noreferrer nofollow\">Play Console<\/a>, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 <code>Users and Permissions<\/code> \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 <code>Invite new users<\/code> \u0432 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c \u043c\u0435\u043d\u044e.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0f5\/52f\/e31\/0f552fe315c869f15a93fa7a408a9b29.png\" width=\"1889\" height=\"443\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0f5\/52f\/e31\/0f552fe315c869f15a93fa7a408a9b29.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0f5\/52f\/e31\/0f552fe315c869f15a93fa7a408a9b29.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u043f\u043e\u043b\u0435 <code>Email address<\/code> \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u0447\u0442\u0443 \u043d\u0430\u0448\u0435\u0433\u043e Service Account. \u0412 <code>Account permissions<\/code> \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u0430:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0430 <code>App access<\/code> &#8212; \u043b\u0438\u0431\u043e <code>Admin<\/code>, \u043b\u0438\u0431\u043e <code>View app information and download bulk reports<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0434\u0435\u043b <code>Releases<\/code> &#8212; \u0441\u0442\u0430\u0432\u0438\u043c <code>Release to production, exclude devices, and use Play App Signing<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430 \u0432\u0430\u0448\u0435 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0443 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <code>Invite User<\/code>.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c4\/5b3\/07c\/0c45b307c16d3349b79615c6d20841f8.png\" width=\"1243\" height=\"753\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0c4\/5b3\/07c\/0c45b307c16d3349b79615c6d20841f8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c4\/5b3\/07c\/0c45b307c16d3349b79615c6d20841f8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0421 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c Google Services \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Gradle Play Publisher<\/h2>\n<p>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 2 \u044d\u0442\u0430\u043f\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u0421\u0431\u043e\u0440\u043a\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Play Market, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Gitlab Tag \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher\" rel=\"noopener noreferrer nofollow\">Gradle Play Publisher<\/a> &#8212; \u044d\u0442\u043e gradle-\u043f\u043b\u0430\u0433\u0438\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \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\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0442.\u043a. <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher\" rel=\"noopener noreferrer nofollow\">\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432 \u0441\u0430\u043c\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>, \u0430 \u0432\u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c. \u041f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u0445\u043e\u0447\u0443 \u043d\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432 Play Market. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>RuStore<\/code>, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/cianru\/rustore-publish-gradle-plugin\" rel=\"noopener noreferrer nofollow\">\u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e<\/a>. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0435\u0441\u0442\u044c \u0438 \u0434\u043b\u044f <a href=\"https:\/\/github.com\/cianru\/huawei-appgallery-publish-gradle-plugin\" rel=\"noopener noreferrer nofollow\">Huawei AppGallery<\/a>.<\/p>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a Gradle Play Publisher, \u043f\u043b\u0430\u0433\u0438\u043d \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0431\u043e\u0440\u043a\u0438, \u0434\u0435\u0442\u0430\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0438\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439, <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher?tab=readme-ov-file#uploading-release-notes\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0443\u0442<\/a>.<\/p>\n<p>\u041f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 <code>production<\/code>, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f) &#8212; <code>app\/src\/main\/play\/release-names\/production.txt<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 &#8212; <code>app\/src\/main\/play\/release-notes\/ru-RU\/production.txt<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0430 \u043d\u0438\u0436\u0435.<\/p>\n<pre><code>{root} |-- app   |-- src     |-- main       |-- play         |-- release-names           |-- production.txt         |-- release-notes           |-- ru-RU             |-- production.txt<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u043b\u0435\u0437\u0442\u044c \u0432 <code>Gradle<\/code>, \u0447\u0442\u043e\u0431\u044b \u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0432\u0435\u0440\u0441\u0438\u044e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0442\u043e\u043c\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0437\u0430\u043d\u044f\u0442\u0438\u0435\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0436\u0438\u0437\u043d\u044c \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c <code>versionName<\/code> \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438.  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>getVersionName()<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043b\u044f Play Console. \u0410 \u0432\u043e\u0442 <code>versionCode<\/code> \u043c\u043e\u0436\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432 \u0435\u0434\u0438\u043d\u0438\u0446\u0443 (\u0438\u043b\u0438 \u043b\u044e\u0431\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435), \u0442.\u043a. \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448 \u043f\u043b\u0430\u0433\u0438\u043d.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c <code>app\/build.gradle<\/code>.<\/p>\n<pre><code class=\"kotlin\">internal fun getVersionName(): String {       val file = file(\"src\/main\/play\/release-names\/production.txt\")       val versionName = file.readText()       return versionName.ifEmpty { \"Test Version\" }   }      play {       \/** \u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c GPP \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u0431\u043e\u0440\u043e\u043a, \u043c\u044b \u0432\u0435\u0434\u044c \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 build \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 Play Market? **\/     enabled.set(false)          \/** \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b: internal, alpha, beta, production.      \u041e\u0434\u043d\u0430\u043a\u043e, \u043c\u044b \u0436\u0435 \u0445\u043e\u0442\u0438\u043c \u0441\u0440\u0430\u0437\u0443 \u0432 production! **\/     track.set(\"production\")      \/** \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435.      \u0413\u0434\u0435, 0.6 = 60%. \u0422\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f IN_PROGRESS \u0438 HALTED. **\/     userFraction.set(0.6)      \/** \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e GPP \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 APK, \u043d\u043e \u043d\u0430\u043c \u0436\u0435 \u043d\u0443\u0436\u0435\u043d Bundle?      \u0413\u0434\u0435 true - \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c bundle, false - APK. **\/     defaultToAppBundles.set(true)      \/** \u0422\u0443\u0442 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0430 \u0441 \u0442\u0430\u043a\u0438\u043c versionCode \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.      AUTO_OFFSET \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 versionCode \u0432 Play Console \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443. **\/     resolutionStrategy.set(ResolutionStrategy.AUTO_OFFSET)      \/** \u0417\u0434\u0435\u0441\u044c: COMPLETED - \u043f\u043e\u043b\u043d\u0430\u044f \u0440\u0430\u0441\u043a\u0430\u0442\u043a\u0430 \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439;      DRAFT - \u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a, \u0441\u0431\u043e\u0440\u043a\u0430 \u0435\u0449\u0435 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u0430 \u043a \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438;     HALTED - \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430;     IN_PROGRESS - \u0440\u0435\u043b\u0438\u0437 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u0443\u044e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 60% **\/     releaseStatus.set(ReleaseStatus.IN_PROGRESS) }      android {       ...     playConfigs {           register(\"productionRelease\") {             \/** \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c GPP \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e build flavor.              \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0443\u0441\u0442\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 production release. **\/             enabled.set(true)         }       }            defaultConfig {           ...         versionCode = 1           versionName = getVersionName()           ...      } }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/developers.google.com\/android-publisher\/api-ref\/rest\/v3\/edits.tracks#status\" rel=\"noopener noreferrer nofollow\">Release Statuses \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a>. \u0420\u0430\u043d\u0435\u0435 \u043c\u044b \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043b\u0438 Google Services \u0441 Play Console, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0447\u0435\u0433\u043e \u0443 \u043d\u0430\u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0441\u044f JSON-\u043a\u043b\u044e\u0447, \u043e\u043d \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b GPP \u0441\u043c\u043e\u0433 \u0441\u0432\u044f\u0437\u0430\u0442\u044c\u0441\u044f \u0441 \u043d\u0430\u0448\u0435\u0439 Play Console.<\/p>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c 2 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043a\u043b\u044e\u0447:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <code>ANDROID_PUBLISHER_CREDENTIALS<\/code>, \u0447\u0442\u043e\u0431\u044b GPP \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0440\u0430\u043b \u0435\u0433\u043e \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043c\u044b \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c!<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0438 \u0437\u0430\u0442\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">play {     serviceAccountCredentials.set(file(\"your-key.json\")) }<\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430 \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a CI\/CD pipeline&#8217;\u0443.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 CI\/CD<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u043c\u0438 \u0441\u0442\u043e\u0438\u0442 2 \u0437\u0430\u0434\u0430\u0447\u0438, \u044d\u0442\u043e &#8212; \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 Play Market \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0439\u0434\u0443\u0442 \u0432 \u044d\u0442\u043e\u0442 \u0440\u0435\u043b\u0438\u0437, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Gitlab Tag&#8217;\u0430\u043c\u0438. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0435\u0449\u0435 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u0432 \u043d\u0430\u0448\u0435\u0439 Telegram-\u0433\u0440\u0443\u043f\u043f\u0435. <a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/918364\/\" rel=\"noopener noreferrer nofollow\">\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0443\u0436\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u044d\u0442\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <code>stages<\/code> 2 \u043d\u043e\u0432\u044b\u0445: <code>deploy_release<\/code> \u0438 <code>create_git_tag<\/code>.<\/p>\n<pre><code class=\"yaml\">stages:     - lint     - tests     - build_flavors     - deploy_release     - create_git_tag<\/code><\/pre>\n<h2>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GPP<\/h2>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u044e, \u0447\u0442\u043e \u0440\u0430\u043d\u0435\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 2 \u0444\u0430\u0439\u043b\u0430: <code>app\/src\/main\/play\/release-names\/production.txt<\/code> \u0434\u043b\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 <code>app\/src\/main\/play\/release-notes\/ru-RU\/production.txt<\/code> \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0439\u0434\u0443\u0442 \u0432 \u044d\u0442\u0443 \u0441\u0431\u043e\u0440\u043a\u0443. \u041f\u0435\u0440\u0435\u0434 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u043c\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 \u043d\u0438\u0445 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0442\u0435\u043c \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 Play Store.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 Job&#8217;\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Play Market, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443.<\/p>\n<pre><code class=\"yaml\">deployRelease:     stage: deploy_release     before_script:     - apt update       - apt install python3-pip --yes          - pip3 install awscli --upgrade   script:          - .\/gradlew publishProductionReleaseBundle       - .\/gradlew assembleProductionRelease      - export VERSION_NAME=\"#PRODUCTION_RELEASE  $(cat app\/src\/main\/play\/release-names\/production.txt)\\n\"     - export CHANGELOG=\"$(cat app\/src\/main\/play\/release-notes\/ru-RU\/production.txt)\\n\"              - aws s3 cp app\/build\/outputs\/apk\/production\/release\/app-production-release.apk s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk --endpoint https:\/\/storage.yandexcloud.net       - chmod a+x .\/upload_telegram_link.sh         - aws s3 presign s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk --endpoint-url \"https:\/\/storage.yandexcloud.net\/\" --expires-in 604800|source upload_telegram_link.sh     artifacts:       paths:         - app\/build\/outputs\/apk\/       expire_in: 10 days     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"master\"'<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432 <code>before_script<\/code> \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <code>Python3<\/code> \u0438 <code>pip<\/code> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 awscli. \u0427\u0442\u043e\u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b 2 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code>AWS_ACCESS_KEY_ID<\/code> (ID \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430) \u0438 <code>AWS_SECRET_ACCESS_KEY<\/code> (\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u043b\u044e\u0447\u0430). <a href=\"https:\/\/yandex.cloud\/ru\/docs\/storage\/tools\/aws-cli#before-you-begin\" rel=\"noopener noreferrer nofollow\">\u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0438\u0445 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<pre><code class=\"yaml\">before_script:     - apt update       - apt install python3-pip --yes          - pip3 install awscli --upgrade<\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430\u0448\u0443 \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Play Console. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c Bundle. \u0415\u0441\u043b\u0438 \u0436\u0435 \u043c\u044b \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u0445\u043e\u0442\u0438\u043c \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c APK, \u0442\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>publishProductionReleaseApk<\/code>. \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: <code>publish{Build flavor}{Bundle\/Apk}<\/code>.<\/p>\n<pre><code class=\"yaml\">.\/gradlew publishProductionReleaseBundle  <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Play Console \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0435 \u043e \u043d\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c APK.<\/p>\n<pre><code class=\"yaml\">.\/gradlew assembleProductionRelease  <\/code><\/pre>\n<p>\u041a\u0430\u043a \u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b \u0440\u0430\u043d\u0435\u0435, \u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445 \u043c\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043d\u0435\u0435 \u0432\u0445\u043e\u0434\u044f\u0442. \u042d\u0442\u0443 \u0436\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u043e \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435.<\/p>\n<pre><code class=\"yaml\">export VERSION_NAME=\"#PRODUCTION_RELEASE  $(cat app\/src\/main\/play\/release-names\/production.txt)\\n\" export CHANGELOG=\"$(cat app\/src\/main\/play\/release-notes\/ru-RU\/production.txt)\\n\"   <\/code><\/pre>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/918364\/\" rel=\"noopener noreferrer nofollow\">\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0443\u0436\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/a>, \u043d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u043c \u0435\u0449\u0435 \u0440\u0430\u0437. \u0414\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c APK \u0432 \u043d\u0430\u0448\u0435 s3-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 (<a href=\"https:\/\/yandex.cloud\/ru\/docs\/storage\/\" rel=\"noopener noreferrer nofollow\">Yandex Object Storage<\/a>), \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443, \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0434\u0430\u0435\u043c s3-bucket \u0438 \u043f\u0443\u0442\u044c \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0444\u0430\u0439\u043b. <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/operations\/objects\/upload\" rel=\"noopener noreferrer nofollow\">\u0417\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u044e\u0434\u0430<\/a>.<\/p>\n<pre><code class=\"yaml\">aws s3 cp app\/build\/outputs\/apk\/production\/release\/app-production-release.apk s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk --endpoint https:\/\/storage.yandexcloud.net  <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0435\u043b\u0430\u0435\u043c <code>upload_telegram_<\/code><a href=\"http:\/\/link.sh\" rel=\"noopener noreferrer nofollow\"><code>link.sh<\/code><\/a> \u0441\u043a\u0440\u0438\u043f\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u043c. \u041e\u043d \u0436\u0435 \u0443 \u043d\u0430\u0441 \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443. <a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/918364\/\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u044d\u0442\u043e\u0442 \u0441\u043a\u0440\u0438\u043f\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/a>.<\/p>\n<pre><code class=\"yaml\">chmod a+x .\/upload_telegram_link.sh  <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/concepts\/pre-signed-urls\" rel=\"noopener noreferrer nofollow\">Pre-signed Url<\/a>, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u0448 APK. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/operations\/objects\/link-for-download\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0442\u0443\u0442<\/a>. \u0412 <code>--expires-in 604800<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 (7 \u0434\u043d\u0435\u0439). \u0427\u0435\u0440\u0435\u0437 pipe <code>|<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u0432 <code>source upload_telegram_<\/code><a href=\"http:\/\/link.sh\" rel=\"noopener noreferrer nofollow\"><code>link.sh<\/code><\/a> \u0441\u043a\u0440\u0438\u043f\u0442.<\/p>\n<pre><code class=\"yaml\">aws s3 presign s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk --endpoint-url \"https:\/\/storage.yandexcloud.net\/\" --expires-in 604800|source upload_telegram_link.sh  <\/code><\/pre>\n<p>\u0412 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u0445 \u0442\u0430\u043a \u0436\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u0430\u0448\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Gitlab-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u0445.<\/p>\n<pre><code class=\"yaml\">artifacts:       paths:         - app\/build\/outputs\/apk\/       expire_in: 10 days  <\/code><\/pre>\n<p>\u0410 \u0432 <code>rules<\/code> \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0430 Job&#8217;\u0430. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, Job&#8217;\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 merge request&#8217;\u0435 \u0432 master. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0432\u0430\u0448\u0438\u0445 \u0437\u0430\u0434\u0430\u0447, <a href=\"https:\/\/docs.gitlab.com\/ci\/jobs\/job_rules\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<pre><code class=\"yaml\">rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"master\"'<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">AWS_ACCESS_KEY_ID<\/p>\n<\/td>\n<td>\n<p align=\"left\">ID \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0432 \u043d\u0430\u0448\u0435 s3-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">AWS_SECRET_ACCESS_KEY<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CHANGELOG<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 release-\u0441\u0431\u043e\u0440\u043a\u0435. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c upload_telegram_<a href=\"http:\/\/link.sh\" rel=\"noopener noreferrer nofollow\">link.sh<\/a> \u0441\u043a\u0440\u0438\u043f\u0442\u0435.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">VERSION_NAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0439 \u0441\u0431\u043e\u0440\u043a\u0438. \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 upload_telegram_<a href=\"http:\/\/link.sh\" rel=\"noopener noreferrer nofollow\">link.sh<\/a> \u0441\u043a\u0440\u0438\u043f\u0442\u0435.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">ANDROID_PUBLISHER_CREDENTIALS<\/p>\n<\/td>\n<td>\n<p align=\"left\">JSON-\u043a\u043b\u044e\u0447 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Play Console. \u0414\u0430\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 GPP.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h2>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0440\u0435\u043b\u0438\u0437\u0435 \u0432 Gitlab Tag<\/h2>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043d\u0430 <code>Gitlab &gt; Code &gt; Tags<\/code>, \u043d\u043e \u0442\u0430\u043a \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e CI\/CD. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u044f \u0431\u044b \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u043b \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f Play Market \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0444\u0430\u0439\u043b <code>changelog.txt<\/code>, \u043b\u0438\u0431\u043e \u0432 \u043b\u044e\u0431\u043e\u043c \u0434\u0440\u0443\u0433\u043e\u043c \u0443\u0434\u043e\u0431\u043d\u043e\u043c \u0434\u043b\u044f \u043d\u0430\u0441 \u043c\u0435\u0441\u0442\u0435. \u0421\u044e\u0434\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u043d\u043e\u0441\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<pre><code class=\"yaml\">createGitTag:     stage: create_git_tag     script:       - export GIT_TAG=$(cat app\/src\/main\/play\/release-names\/production.txt)       - export GIT_TAG_MESSAGE=$(cat changelog.txt)          - git remote set-url origin https:\/\/oauth2:$CI_BOT_TOKEN@$CI_PROJECT_URL       - git config --global user.email $CI_BOT_EMAIL       - git config --global user.name $CI_BOT_USERNAME         - git tag -a -f $GIT_TAG -m $CI_BOT_USERNAME       - git push -f origin $GIT_TAG     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"master\"'<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c 2 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435: <code>GIT_TAG<\/code> \u0434\u043b\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0442\u044d\u0433\u0430 \u0438 <code>GIT_TAG_MESSAGE<\/code> \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f <code>GIT_TAG<\/code> \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Play Market. \u0410 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e <code>changelog.txt<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435.<\/p>\n<pre><code class=\"yaml\">export GIT_TAG=$(cat app\/src\/main\/play\/release-names\/production.txt)   export GIT_TAG_MESSAGE=$(cat changelog.txt) <\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c URL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0432 Gitlab. \u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>CI_BOT_TOKEN<\/code> \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u0442\u0430 (\u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430, \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0442\u044d\u0433\u0430\u043c\u0438), \u0430 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>CI_PROJECT_URL<\/code> \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <code>gitlab.ru\/{\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443}.git<\/code>.<\/p>\n<p>\u0418\u0442\u043e\u0433\u043e\u0432\u044b\u0439 URL \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430: <a href=\"https:\/\/oauth2:%7B%D0%A2%D0%BE%D0%BA%D0%B5%D0%BD\" rel=\"noopener noreferrer nofollow\"><code>https:\/\/oauth2:{\u0422\u043e\u043a\u0435\u043d<\/code><\/a><code> <\/code><a href=\"mailto:%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B0%7D@gitlab.ru\" rel=\"noopener noreferrer nofollow\"><code>\u0434\u043e\u0441\u0442\u0443\u043f\u0430}@gitlab.ru<\/code><\/a><code>\/{\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443}.git<\/code><\/p>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e, \u043a\u0430\u043a \u0438\u0445 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u043e\u0437\u0436\u0435.<\/p>\n<pre><code class=\"yaml\">git remote set-url origin https:\/\/oauth2:$CI_BOT_TOKEN@$CI_PROJECT_URL<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u043e\u0447\u0442\u0443 \u0438 \u0438\u043c\u044f \u0431\u043e\u0442\u0430 \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0442\u044d\u0433\u043e\u0432. \u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"yaml\">git config --global user.email $CI_BOT_EMAIL   git config --global user.name $CI_BOT_USERNAME <\/code><\/pre>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u044d\u0433 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>-f<\/code>, \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 tag.<\/p>\n<pre><code class=\"yaml\">git tag -a -f $GIT_TAG -m $GIT_TAG_MESSAGE<\/code><\/pre>\n<p>\u041d\u0443 \u0432\u043e\u0442 \u0438 \u0432\u0441\u0435, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c <code>push<\/code> \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.<\/p>\n<pre><code class=\"yaml\">git push -f origin $GIT_TAG<\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0440\u0438 merge request \u0432 master.<\/p>\n<pre><code class=\"yaml\">rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"master\"'<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">GIT_TAG<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u044d\u0433\u0430. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0435\u0433\u043e \u043a\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Play Market. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u043a\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u044d\u0433\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>v.3.2.12<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">GIT_TAG_MESSAGE<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0445\u043e\u0434\u044f\u0442 \u0432 \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_BOT_TOKEN<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Gitlab tags.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_PROJECT_URL<\/p>\n<\/td>\n<td>\n<p align=\"left\">URL \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <code>gitlab.ru\/{\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443}.git<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_BOT_EMAIL<\/p>\n<\/td>\n<td>\n<p align=\"left\">Email \u0431\u043e\u0442\u0430 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_BOT_USERNAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">Username \u0431\u043e\u0442\u0430 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0427\u0442\u043e\u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Gitlab tags \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0430\u043a\u043a\u0430\u0443\u043d\u0442, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 Gitlab-\u043f\u0440\u043e\u0435\u043a\u0442\u0443. \u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442, \u043b\u0438\u0431\u043e \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e &#8212; \u043a\u0430\u043a \u0432\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c <code>CI_BOT_TOKEN<\/code> \u0442\u043e\u043a\u0435\u043d, \u0437\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u043d\u0430\u0436\u0430\u0432 \u043d\u0430 <code>Edit profile<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fe3\/285\/41d\/fe328541d9f31d4f5ece3b3965d0ea79.png\" width=\"284\" height=\"283\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fe3\/285\/41d\/fe328541d9f31d4f5ece3b3965d0ea79.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fe3\/285\/41d\/fe328541d9f31d4f5ece3b3965d0ea79.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c <code>Access tokens<\/code> \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 <code>Add new token<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e07\/68b\/5a4\/e0768b5a470d6df98d066e1ca3993514.png\" width=\"293\" height=\"590\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e07\/68b\/5a4\/e0768b5a470d6df98d066e1ca3993514.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e07\/68b\/5a4\/e0768b5a470d6df98d066e1ca3993514.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u0444\u043e\u0440\u043c\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0435\u0440\u0438\u043e\u0434 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438 \u0434\u0430\u0435\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f: <code>api<\/code>, <code>read_user<\/code>, <code>read_repository<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u0442\u043e\u043a\u0435\u043d \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/294\/9bd\/1fe\/2949bd1feda7e06a7393f2c7e3c58ac1.png\" width=\"1398\" height=\"748\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/294\/9bd\/1fe\/2949bd1feda7e06a7393f2c7e3c58ac1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/294\/9bd\/1fe\/2949bd1feda7e06a7393f2c7e3c58ac1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0421 <code>CI_BOT_USERNAME<\/code> \u0438 <code>CI_BOT_EMAIL<\/code> \u044f \u0434\u0443\u043c\u0430\u044e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e username \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u0438 \u043f\u043e\u0447\u0442\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435. \u0427\u0442\u043e\u0431\u044b, \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0430\u0448 \u0442\u044d\u0433 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a CI\/CD \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 <code>Code &gt; Tags<\/code> \u0438 \u0432\u0438\u0434\u0438\u043c \u043d\u0430\u0448\u0443 \u043a\u0440\u0430\u0441\u043e\u0442\u0443. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u043b \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c. \u0422\u0430\u043a \u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0448 release \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 tag&#8217;\u0430.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0a9\/517\/0c1\/0a95170c16c90c1fa19cc434a087e1a0.png\" width=\"1413\" height=\"117\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0a9\/517\/0c1\/0a95170c16c90c1fa19cc434a087e1a0.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0a9\/517\/0c1\/0a95170c16c90c1fa19cc434a087e1a0.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043d\u043e \u0443\u0436\u0435 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c.<\/p>\n<h2>Fastlane<\/h2>\n<p><a href=\"https:\/\/github.com\/fastlane\/fastlane\" rel=\"noopener noreferrer nofollow\">Fastlane<\/a> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \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 \u0440\u0443\u0442\u0438\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0448\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u043d \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0443\u044e CI\/CD-\u0441\u0438\u0441\u0442\u0435\u043c\u0443. Fastlane \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c CI\/CD-\u0441\u0438\u0441\u0442\u0435\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<p>\u0418\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e, \u0447\u0442\u043e \u043e\u043d \u0443\u043c\u0435\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ol>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 IOS \u0438 Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 Play Store \u0438 App Store;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a;<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 CI\/CD-\u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 Fastlane \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0442.\u043a. \u044d\u0442\u043e <a href=\"https:\/\/docs.fastlane.tools\/getting-started\/android\/setup\/\" rel=\"noopener noreferrer nofollow\">\u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>. \u0412\u044b\u0434\u0435\u043b\u044e \u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>Fastlane \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <a href=\"https:\/\/www.ruby-lang.org\/en\/\" rel=\"noopener noreferrer nofollow\">Ruby<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443 \u0432\u0430\u0441 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0435\u0433\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/bundler.io\/\" rel=\"noopener noreferrer nofollow\">Bundler<\/a>, \u0437\u043d\u0430\u0447\u0438\u0442 \u0435\u0433\u043e \u0442\u043e\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Fastlane \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0443 \u043d\u0430\u0441 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432 \u043d\u0438\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:<\/p>\n<pre><code>{root} |-- Gemfile |-- Gemfile.lock |-- fastlane   |-- Appfile   |-- Fastfile<\/code><\/pre>\n<p>\u0413\u0434\u0435:<\/p>\n<ol>\n<li>\n<p><code>Appfile<\/code> &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043e\u0431\u0449\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p><code>Fastfile<\/code> \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043d\u0430\u0448\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b;<\/p>\n<\/li>\n<li>\n<p><code>Gemfile<\/code> \u0438 <code>Gemfile.lock<\/code> \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 <code>Appfile<\/code> \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u043a\u0435\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443\u043a\u0430\u0436\u0435\u043c \u0435\u0433\u043e.<\/p>\n<pre><code class=\"ruby\">package_name(\"com.example.package\")<\/code><\/pre>\n<p>\u041a <code>Fastfile<\/code> \u043f\u0440\u0438\u0434\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0437\u0436\u0435. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043f\u0440\u044f\u043c\u043e \u0432 \u043d\u0435\u043c, \u043d\u043e \u0442\u043e\u0433\u0434\u0430 \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0437\u0434\u0443\u0442\u044c\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0438\u0445 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 Fast-\u0444\u0430\u0439\u043b\u044b.<\/p>\n<h3>Fastlane. \u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Play Store, \u0440\u0430\u043d\u0435\u0435 \u043c\u044b \u0443\u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u043b\u0438 \u0432\u0441\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u044d\u0442\u0430\u043f\u044b \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430\u0448 \u0441\u043a\u0440\u0438\u043f\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Fastlane. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>DeployRelease<\/code> \u043f\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u043f\u0443\u0442\u0438: <code>fastlane\/lanes\/DeployRelease<\/code>. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0438 \u0435\u0433\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435, \u043a\u0430\u043a \u0432\u0430\u043c \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<p>\u0418\u0442\u043e\u0433\u043e\u043c \u0438\u043c\u0435\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<pre><code>{root} |-- Gemfile |-- Gemfile.lock |-- fastlane   |-- Appfile   |-- Fastfile   |-- lanes     |-- DeployRelease<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e <code>DeployRelease<\/code> \u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code class=\"ruby\">platform :android do          lane :incrementVersionCode do           previous_version_code = google_play_track_version_codes(             package_name: \"com.example.package\",             track: \"production\", # \u0421\u0442\u043e\u0438\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e             json_key_data: ENV[\"PLAY_CONSOLE_CREDENTIALS\"]           )[0]              new_version_code = previous_version_code + 1           new_version_code       end          lane :buildProductionReleaseBundle do           gradle(             task: \"bundle\",             flavor: \"Production\",             build_type: \"Release\",             properties: {                 \"android.injected.version.code\" =&gt; incrementVersionCode               }           )       end          lane :buildProductionReleaseApk do           gradle(             task: \"assemble\",             flavor: \"Production\",             build_type: \"Release\",             properties: {                 \"android.injected.version.code\" =&gt; incrementVersionCode               }           )       end           lane :deployProductionRelease do           buildProductionReleaseBundle              supply(             package_name: \"com.example.package\",             track: \"production\",             aab: lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH],             json_key_data: ENV[\"PLAY_CONSOLE_CREDENTIALS\"],             release_status: \"inProgress\",             rollout: \"0.6\",             skip_upload_metadata: true,             skip_upload_images: true,             skip_upload_screenshots: true           )       end   end<\/code><\/pre>\n<p>\u0412 \u043e\u0442\u0440\u044b\u0432\u043a\u0435 \u043a\u043e\u0434\u0430 \u043d\u0438\u0436\u0435, \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0430\u0448\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b.<\/p>\n<pre><code class=\"ruby\">platform :{android\/ios} do ... end<\/code><\/pre>\n<p>\u0421\u0430\u043c\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a <code>lane<\/code>, \u0438\u0445 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 <code>lanes<\/code> \u0438\u043b\u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0448\u0443 \u043b\u043e\u0433\u0438\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430, \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u043d\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<pre><code class=\"ruby\">lane :{\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438} do   ... end<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 Gradle Play Publisher \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u0430 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u043e\u043f\u0446\u0438\u044f: \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u044b \u0441 <code>versionCode<\/code>, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442 \u043d\u0430 1 \u043e\u0442 <code>versionCode<\/code> \u0432 Play Store. \u0412 Fastlane \u0442\u0430\u043a\u043e\u0439 \u043e\u043f\u0446\u0438\u0438 \u043d\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u0441\u0430\u043c\u0438\u043c \u043d\u0430\u0434\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 <code>incrementVersionCode<\/code> \u0434\u043b\u044f \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u0441\u0438\u0438 \u043d\u0430 +1 \u043e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432 Play Console.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c, \u0432\u0432\u0435\u0434\u0443 2 \u0442\u0435\u0440\u043c\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c: <code>action<\/code> &#8212; \u044d\u0442\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0434\u0443\u0442 \u0438\u0437 \u043f\u043e\u0434 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0432 Fastlane, \u0430 <code>plugin<\/code> &#8212; \u044d\u0442\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u0437 \u0432\u043d\u0435, \u0442\u0430\u043a \u0436\u0435 \u0432\u044b \u0441\u0430\u043c\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c\u0438. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/docs.fastlane.tools\/advanced\/actions\/\" rel=\"noopener noreferrer nofollow\">actions \u0447\u0438\u0442\u0430\u0435\u043c \u0442\u0443\u0442<\/a>, \u0430 \u043f\u0440\u043e <a href=\"https:\/\/docs.fastlane.tools\/plugins\/using-plugins\/\" rel=\"noopener noreferrer nofollow\">\u0440\u0430\u0431\u043e\u0442\u0443 \u0441 plugins \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f, <a href=\"https:\/\/docs.fastlane.tools\/actions\/google_play_track_version_codes\/\" rel=\"noopener noreferrer nofollow\">google_play_track_version_codes<\/a> action \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0435\u0440\u0441\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0432 Play Console, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0435\u0440\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e (\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e). \u041f\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c \u0442\u0443\u0442 \u0432\u0441\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e: <code>package_name<\/code> \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, <code>track<\/code> &#8212; internal, alpha, beta, production (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0435\u0440\u0435\u0442\u0441\u044f production, \u043d\u043e \u043c\u044b \u0435\u0433\u043e \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c), <code>json_key_data<\/code> &#8212; JSON-\u043a\u043b\u044e\u0447, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438. \u041d\u0443 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 +1 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<pre><code class=\"ruby\">lane :incrementVersionCode do       previous_version_code = google_play_track_version_codes(         package_name: \"com.example.package\",         track: \"production\", # \u0421\u0442\u043e\u0438\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e         json_key_data: ENV[\"PLAY_CONSOLE_CREDENTIALS\"]       )[0]        new_version_code = previous_version_code + 1       new_version_code   end <\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c <code>buildProductionReleaseBundle<\/code> \u0438 <code>buildProductionReleaseApk<\/code> \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 build flavors \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0441 \u044d\u0442\u0438\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 <a href=\"https:\/\/docs.fastlane.tools\/actions\/gradle\/#gradle\" rel=\"noopener noreferrer nofollow\">gradle<\/a> action. \u0412 <code>properties<\/code> \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>versionCode<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432 <code>lane_context<\/code> \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u043a \u0441\u0431\u043e\u0440\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u043e\u0437\u0436\u0435 \u0441\u043c\u043e\u0436\u0435\u043c \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f. \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/docs.fastlane.tools\/actions\/gradle\/#gradle\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e gradle action<\/a> \u0438 <a href=\"https:\/\/docs.fastlane.tools\/advanced\/lanes\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e lanes<\/a>.<\/p>\n<pre><code class=\"ruby\">lane :buildProductionReleaseBundle do       gradle(         task: \"bundle\",         flavor: \"Production\",         build_type: \"Release\",         properties: {             \"android.injected.version.code\" =&gt; incrementVersionCode           }       )   end      lane :buildProductionReleaseApk do       gradle(         task: \"assemble\",         flavor: \"Production\",         build_type: \"Release\",         properties: {             \"android.injected.version.code\" =&gt; incrementVersionCode           }       )   end<\/code><\/pre>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Play Console, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0431\u0435\u0440\u0435\u043c bundle \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043d\u0430\u0448 <code>buildProductionReleaseBundle<\/code> \u0441\u043a\u0440\u0438\u043f\u0442. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Play Console \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f <a href=\"https:\/\/docs.fastlane.tools\/actions\/supply\/#supply\" rel=\"noopener noreferrer nofollow\">supply<\/a> action, \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0433\u0438\u0431\u043a\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430.<\/p>\n<pre><code class=\"ruby\">lane :deployProductionRelease do       buildProductionReleaseBundle        supply(         package_name: \"com.example.package\",         track: \"production\",         aab: lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH],         json_key_data: ENV[\"PLAY_CONSOLE_CREDENTIALS\"],         release_status: \"inProgress\",         rollout: \"0.6\",         skip_upload_metadata: true,         skip_upload_images: true,         skip_upload_screenshots: true       )   end <\/code><\/pre>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Play Console \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u0432\u0430\u0448\u0435\u0433\u043e <code>versionName<\/code> \u0432 <code>build.gradle<\/code>. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>version_name.txt<\/code> \u0444\u0430\u0439\u043b \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0431\u0440\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438, \u0430 \u0434\u0430\u043b\u044c\u0448\u0435 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448\u0435\u043c <code>build.gradle<\/code>. \u0410 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0443\u0436\u0435 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u0432 <code>fastlane\/metadata\/android\/ru-RU\/changelogs\/{versionCode \u0432\u0430\u0448\u0435\u0439 \u0431\u0443\u0434\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438}.txt<\/code> \u0438 \u0432 \u043d\u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u043d\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435. \u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<pre><code class=\"typescript\">{root} |-- version_name.txt |-- fastlane   |-- Appfile   |-- Fastfile   |-- metadata     |-- android       |-- ru-RU         |-- changelogs           |-- 1.txt           |-- 2.txt           |-- {versionCode \u0432\u0430\u0448\u0435\u0439 \u0431\u0443\u0434\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438}.txt<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">PLAY_CONSOLE_CREDENTIALS<\/p>\n<\/td>\n<td>\n<p align=\"left\">JSON-\u043a\u043b\u044e\u0447 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Play Console.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h3>Fastlane. \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 s3<\/h3>\n<p>\u0421 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u0435\u0449\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 \u043d\u0430\u0448\u0443 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u044d\u0442\u0438\u043c \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c. \u041d\u0430\u0447\u043d\u0435\u043c \u0441 Aws, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>fastlane\/lanes\/Aws<\/code>.<\/p>\n<pre><code>{root} |-- Gemfile |-- Gemfile.lock |-- fastlane   |-- Appfile   |-- Fastfile   |-- lanes     |-- DeployRelease     |-- Aws<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0430\u0448 <code>uploadApkToS3<\/code> \u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u043d\u0435\u0433\u043e.<\/p>\n<pre><code class=\"ruby\">lane :uploadApkToS3 do |options|       apk_path = options[:apk_path] || lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]          if apk_path.nil?           UI.user_error!(\"The 'apk_path' parameter must not be null\")       end          s3_path = \"s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk\"      endpoint = \"https:\/\/storage.yandexcloud.net\"          sh(\"aws\", \"s3\", \"cp\", apk_path, s3_path, \"--endpoint-url\", endpoint)          presigned_url = sh(\"aws\", \"s3\", \"presign\", s3_path, \"--endpoint-url\", endpoint, \"--expires-in\", \"604800\", log: false).strip       Actions.lane_context[\"APK_DOWNLOAD_URL\"] = presigned_url          presigned_url   end<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043d\u0430\u0448 <code>lane<\/code> <a href=\"https:\/\/docs.fastlane.tools\/advanced\/lanes\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0443\u0436\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430 \u0432\u0445\u043e\u0434\u0435<\/a>, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043f\u0443\u0442\u044c \u043a APK-\u0444\u0430\u0439\u043b\u0443. \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f <code>||<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0439 \u0443\u0437\u043d\u0430\u0442\u044c \u043f\u0440\u043e <a href=\"https:\/\/docs.fastlane.tools\/actions\/build_android_app\/\" rel=\"noopener noreferrer nofollow\">GRADLE_APK_OUTPUT_PATH \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<pre><code class=\"ruby\">lane :uploadApkToS3 do |options|       apk_path = options[:apk_path] || lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]  <\/code><\/pre>\n<p>\u041d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>apk_path<\/code> \u043d\u0430 null \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439. <a href=\"https:\/\/docs.fastlane.tools\/advanced\/actions\/\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0442\u0443\u0442<\/a>.<\/p>\n<pre><code class=\"ruby\">if apk_path.nil?       UI.user_error!(\"The 'apk_path' parameter must not be null\")   end <\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>s3_path<\/code> \u043f\u0443\u0442\u044c, \u043a\u0443\u0434\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0430\u0448 \u0444\u0430\u0439\u043b \u0432 s3 \u0438 <code>endpoint<\/code> \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<pre><code class=\"ruby\">s3_path = \"s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk\"  endpoint = \"https:\/\/storage.yandexcloud.net\"  <\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>sh<\/code> action <a href=\"https:\/\/docs.fastlane.tools\/actions\/sh\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Shell \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\u0438<\/a>.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <a href=\"https:\/\/github.com\/fastlane-community\/fastlane-plugin-s3\" rel=\"noopener noreferrer nofollow\">s3 \u0435\u0441\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 plugin<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u043d\u0435 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f, \u043d\u043e \u043f\u043e\u0447\u0435\u043c\u0443? \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0438\u0437 \u043f\u043e\u0434 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 plugin \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 <a href=\"https:\/\/yandex.cloud\/ru\/docs\/storage\/\" rel=\"noopener noreferrer nofollow\">Yandex Object Storage<\/a> \u0438 \u0441 <a href=\"https:\/\/yandex.cloud\/ru\/docs\/storage\/concepts\/pre-signed-urls\" rel=\"noopener noreferrer nofollow\">pre-signed urls<\/a>. \u041f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 \u044f \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u044d\u0442\u043e\u043c, \u043e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0443\u0436\u0435 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0442\u043e \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0430\u0448 \u043e\u0442\u0432\u0435\u0442 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f\u0441\u044c \u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435, \u0434\u043b\u044f \u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <code>sh<\/code> action \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Yandex Object Storage \u0438\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<pre><code class=\"ruby\">sh(\"aws\", \"s3\", \"cp\", apk_path, s3_path, \"--endpoint-url\", endpoint)      presigned_url = sh(\"aws\", \"s3\", \"presign\", s3_path, \"--endpoint-url\", endpoint, \"--expires-in\", \"604800\", log: false).strip<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043f\u0440\u043e\u0448\u0443 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 <code>sh<\/code> action \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0432\u0438\u0434\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e <a href=\"https:\/\/docs.fastlane.tools\/advanced\/actions\/\" rel=\"noopener noreferrer nofollow\">\u043e\u0431\u0449\u0430\u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f<\/a> \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 <code>system<\/code> \u0438  <code>sh<\/code> actions, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0434\u0438\u043a\u0442\u043e\u0432\u0430\u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 Shell. \u041e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u0432\u0441\u0435 \u0435\u0449\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043d\u0430\u0448\u0443 shell-\u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<pre><code class=\"ruby\">sh(\"aws s3 cp #{apk_path.shellescape} #{s3_path.shellescape} --endpoint-url #{endpoint.shellescape}\")<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0448 <code>presigned_url<\/code> \u0432 <code>lane_context<\/code> \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445, \u044d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u044f \u043b\u0438\u0448\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e.<\/p>\n<pre><code class=\"ruby\">Actions.lane_context[\"APK_DOWNLOAD_URL\"] = presigned_url  <\/code><\/pre>\n<h3>Fastlane. \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 Telegram<\/h3>\n<p>\u041c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0438 \u043d\u0430\u0448 APK \u0432 s3, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Telegram, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 \u043d\u0430\u0448\u0443 \u0433\u0440\u0443\u043f\u043f\u0443. \u0423\u043f\u0440\u043e\u0441\u0442\u0438\u043c \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u044c \u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u043c <a href=\"https:\/\/github.com\/sergpetrov\/fastlane-plugin-telegram\" rel=\"noopener noreferrer nofollow\">Telegram plugin<\/a>.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code>fastlane add_plugin telegram<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0443 \u0432\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b <code>Pluginfile<\/code>, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u0431\u043d\u043e\u0432\u044f\u0442\u0441\u044f <code>Gemfile<\/code> \u0438 <code>Gemfile.lock<\/code>. \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0432 \u0432\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0432\u0435\u0440\u0441\u0438\u0439.<\/p>\n<pre><code>{root} |-- Gemfile |-- Gemfile.lock |-- fastlane   |-- Appfile   |-- Fastfile   |-- Pluginfile   |-- lanes     |-- DeployRelease     |-- Aws<\/code><\/pre>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432 <code>Gemfile<\/code> \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<pre><code class=\"ruby\">plugins_path = File.join(File.dirname(__FILE__), \"fastlane\", \"Pluginfile\")   eval_gemfile(plugins_path) if File.exist?(plugins_path)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b <code>fastlane\/lanes\/Telegram<\/code>, \u043a\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0430\u0448 <code>sendMessageToTelegram<\/code> \u0441\u043a\u0440\u0438\u043f\u0442. \u0417\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u0443\u0436\u0435 \u0432\u0441\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u043e, \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430 null. \u0410 \u0432\u043e\u0442 \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>formatted_message<\/code> \u0443\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f <a href=\"https:\/\/docs.ruby-lang.org\/en\/master\/syntax\/literals_rdoc.html#label-Here+Document+Literals\" rel=\"noopener noreferrer nofollow\">Ruby Heredoc<\/a> \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u044b \u0443\u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043d\u0430\u0448\u0443 \u0433\u0440\u0443\u043f\u043f\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>telegram<\/code> \u043f\u043b\u0430\u0433\u0438\u043d.<\/p>\n<pre><code class=\"ruby\">lane :sendMessageToTelegram do |options|       title = options[:title]       changelog = options[:changelog]       download_url = options[:download_url]          if title.nil?           UI.user_error!(\"The 'title' parameter must not be null\")       end          if changelog.nil?           UI.user_error!(\"The 'changelog' parameter must not be null\")       end          if download_url.nil?           UI.user_error!(\"The 'download_url' parameter must not be null\")       end          formatted_message = &amp;lt;&amp;lt;~MSG           #{title}              #{changelog}              #{download_url}       MSG          telegram(         token: ENV[\"TELEGRAM_BOT_TOKEN\"],         chat_id: ENV[\"TELEGRAM_CHAT_ID\"],         text: formatted_message       )   end<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">TELEGRAM_BOT_TOKEN<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u043e\u043a\u0435\u043d Telegram-\u0431\u043e\u0442\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">TELEGRAM_CHAT_ID<\/p>\n<\/td>\n<td>\n<p align=\"left\">Id Telegram \u0447\u0430\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h3>Fastlane. \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 Git<\/h3>\n<p>Release-\u0441\u0431\u043e\u0440\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0432 Play Console \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u0432 Telegram \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u043d\u0430\u0448\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u0432 Gitlab tags. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b <code>fastlane\/lanes\/Git<\/code>, \u0433\u0434\u0435 \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0430\u0448 <code>createGitTag<\/code> \u0441\u043a\u0440\u0438\u043f\u0442. \u0422\u0443\u0442 \u044f \u0443\u0436\u0435 \u0434\u0443\u043c\u0430\u044e \u0434\u043b\u044f \u0432\u0430\u0441 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043d\u0435\u0442, \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c \u043d\u0430\u0448\u0438\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c.<\/p>\n<pre><code class=\"ruby\">lane :createGitTag do |options|       tag_name = options[:tag_name]       message = options[:message]          if tag_name.nil?           UI.user_error!(\"The 'tag_name' parameter must not be null\")       end          if message.nil?           UI.user_error!(\"The 'message' parameter must not be null\")       end          bot_token = ENV[\"CI_BOT_TOKEN\"]     project_url = ENV[\"CI_PROJECT_URL\"]     remote_url = \"https:\/\/oauth2:#{bot_token}@#{project_url}\"          sh(\"git\", \"remote\", \"set-url\", \"origin\", remote_url)       sh(\"git\", \"config\", \"--global\", \"user.email\", ENV[\"CI_BOT_EMAIL\"])       sh(\"git\", \"config\", \"--global\", \"user.name\", ENV[\"CI_BOT_USERNAME\"])          sh(\"git\", \"tag\", \"-a\", \"-f\", tag_name, \"-m\", message)       sh(\"git\", \"push\", \"-f\", \"origin\", tag_name) end<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_BOT_TOKEN<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0434\u043b\u044f \u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Gitlab tags.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_PROJECT_URL<\/p>\n<\/td>\n<td>\n<p align=\"left\">URL \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <code>gitlab.ru\/{\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443}.git<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_BOT_EMAIL<\/p>\n<\/td>\n<td>\n<p align=\"left\">Email \u0431\u043e\u0442\u0430 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_BOT_USERNAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">Username \u0431\u043e\u0442\u0430 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h3>Fastlane. \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c CI\/CD<\/h3>\n<p>\u041c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f release-\u0441\u0431\u043e\u0440\u043e\u043a, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Telegram, \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435. \u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 <code>Fastfile<\/code>, \u0432 \u043d\u0435\u043c \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043d\u0430\u0448\u0438 Fast-\u0444\u0430\u0439\u043b\u044b \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043e\u0434\u0438\u043d \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u043a\u0440\u0438\u043f\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c APK \u0438 \u0437\u0430\u0442\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448\u0443 \u0433\u0440\u0443\u043f\u043f\u0443.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 <code>Fastfile<\/code>.<\/p>\n<pre><code class=\"ruby\">import(\".\/lanes\/DeployRelease\")   import(\".\/lanes\/Git\")   import(\".\/lanes\/Aws\")   import(\".\/lanes\/Telegram\")<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043d\u043e\u0432\u044b\u0439 <code>notifyReleaseToTelegram<\/code> \u0441\u043a\u0440\u0438\u043f\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u043c \u0441\u0431\u043e\u0440\u043a\u0443 APK, \u0430 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u043d\u0430\u0448\u0435\u043c \u0440\u0435\u043b\u0438\u0437\u0435. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0430\u043d\u0435\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438.<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0431\u0435\u0440\u0435\u043c APK \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>buildProductionReleaseApk<\/code> \u0441\u043a\u0440\u0438\u043f\u0442, \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0435\u0433\u043e \u0432 s3  \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>uploadApkToS3<\/code>. \u0412 \u043a\u043e\u043d\u0446\u0435, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448\u0443 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f <code>sendMessageToTelegram<\/code> \u0441\u043a\u0440\u0438\u043f\u0442\u0443.<\/p>\n<pre><code class=\"ruby\">platform :android do          lane :notifyReleaseToTelegram do |options|           version = options[:version]           changelog = options[:changelog]              if version.nil?               UI.user_error!(\"The 'version' parameter must not be null\")           end              if changelog.nil?               UI.user_error!(\"The 'changelog' parameter must not be null\")           end              buildProductionReleaseApk           download_url = uploadApkToS3              sendMessageToTelegram(               title: \"#PRODUCTION_RELEASE #{version}\",               changelog: changelog,               download_url: download_url           )       end   end<\/code><\/pre>\n<p>\u041d\u0443 \u0432\u043e\u0442 \u0438 \u0432\u0441\u0435, \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0432 \u043d\u0430\u0448\u0435\u0439 Job&#8217;\u0435 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432 \u043d\u0435\u0439 Fastlane-\u0441\u043a\u0440\u0438\u043f\u0442\u044b. \u041f\u043e\u043b\u043d\u044b\u0439 Job-\u0441\u043a\u0440\u0438\u043f\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<pre><code class=\"yaml\">deployReleaseUsingFastlane:     stage: deploy_release     variables:       LC_ALL: \"en_US.UTF-8\"       LANG: \"en_US.UTF-8\"     script:       - curl -sSL https:\/\/get.rvm.io | bash -s stable       - source \/usr\/local\/rvm\/scripts\/rvm       - rvm install 3.2.2          - bundle install       - bundle exec fastlane install_plugins          - export VERSION_NAME=\"#PRODUCTION_RELEASE  $(cat version_name.txt)\"       - export CHANGELOG=\"$(cat changelog.txt)\"          - bundle exec fastlane deployRelease       - bundle exec fastlane notifyReleaseToTelegram version:${VERSION_NAME} changelog:${CHANGELOG}       - bundle exec fastlane createGitTag tag_name:${VERSION_NAME} message:${CHANGELOG}    rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"master\"'<\/code><\/pre>\n<p>Fastlane \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0435\u0441\u043b\u0438 \u0432 <code>shell<\/code> \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0435 <code>locale<\/code> \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d <code>UTF-8<\/code>, \u0442\u043e \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e. <a href=\"https:\/\/docs.fastlane.tools\/getting-started\/android\/setup\/\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<pre><code class=\"yaml\">variables:       LC_ALL: \"en_US.UTF-8\"       LANG: \"en_US.UTF-8\" <\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c RVM (<a href=\"https:\/\/rvm.io\/\" rel=\"noopener noreferrer nofollow\">Ruby Version Manager<\/a>), \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Ruby.<\/p>\n<pre><code class=\"yaml\">curl -sSL https:\/\/get.rvm.io | bash -s stable<\/code><\/pre>\n<p>\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c RVM \u0432 \u043d\u0430\u0448 <code>PATH<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c \u0438\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. (\u0412 Linux, \u0437\u0434\u0435\u0441\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438\u0449\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u043d\u0438\u043c\u0438 \u0438\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438).<\/p>\n<pre><code class=\"yaml\">source \/usr\/local\/rvm\/scripts\/rvm<\/code><\/pre>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Ruby \u043d\u0443\u0436\u043d\u043e\u0439 \u043d\u0430\u043c \u0432\u0435\u0440\u0441\u0438\u0438, \u043d\u043e \u043f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 3.2.2? \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0443\u044e \u0432\u0430\u043c \u0432\u0435\u0440\u0441\u0438\u044e. C\u043a\u0430\u0436\u0443 \u043b\u0438\u0448\u044c, \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c Ruby \u0432\u0435\u0440\u0441\u0438\u0438 3+, \u0442.\u043a. \u0432 \u043d\u0438\u0445 \u0438\u0437 \u043f\u043e\u0434 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d <code>bundler<\/code> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u041d\u043e \u043d\u0430 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 Fastlane \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e.<\/p>\n<pre><code class=\"yaml\">rvm install 3.2.2<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0432\u0441\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0432 \u043d\u0430\u0448\u0438\u0445 <code>Gemfile<\/code> \u0438 <code>Gemfile.lock<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>bundler<\/code>.<\/p>\n<pre><code class=\"yaml\">bundle install<\/code><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0432 \u043d\u0430\u0448\u0435\u043c <code>Pluginfile<\/code>.<\/p>\n<pre><code class=\"yaml\">bundle exec fastlane install_plugins<\/code><\/pre>\n<p>\u0420\u0430\u043d\u0435\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 <code>version_name.txt<\/code> \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 <code>changelog.txt<\/code> \u0434\u043b\u044f Gitlab tags. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u043d\u0438\u0445 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"yaml\">export VERSION_NAME=\"#PRODUCTION_RELEASE  $(cat version_name.txt)\"   export CHANGELOG=\"$(cat changelog.txt)\"  <\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u0430\u0448\u0438 Fastlane-\u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Play Console, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0435\u043c \u043e \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<pre><code class=\"yaml\">bundle exec fastlane deployRelease   bundle exec fastlane notifyReleaseToTelegram version:${VERSION_NAME} changelog:${CHANGELOG} bundle exec fastlane createGitTag tag_name:${VERSION_NAME} message:${CHANGELOG}<\/code><\/pre>\n<p>\u0421 Fastlane \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438, \u0438, \u043c\u043d\u0435 \u0431\u044b \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e Fastlane &#8212; \u044d\u0442\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Store&#8217;\u0430\u0445. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432, \u0440\u0430\u0441\u043a\u0430\u0442\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u0438 \u0442.\u0434., \u0442.\u0435. \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0433\u0438\u0431\u043a\u0438\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e CI\/CD.<\/p>\n<h2>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0432\u043e\u0439 Docker-\u043e\u0431\u0440\u0430\u0437<\/h2>\n<p>\u0414\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043c\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c docker-\u043e\u0431\u0440\u0430\u0437\u043e\u043c <code>jangrewe\/gitlab-ci-android:33<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e Android SDK \u0438 Java 11. \u041f\u043e\u0447\u0442\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 Job&#8217;\u0435 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043c\u044b \u0437\u0430\u043d\u043e\u0432\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u043b\u0438 \u043d\u043e\u0432\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0435\u0433\u043e pipeline, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 python, awscli, ruby \u0438 \u0442.\u0434. \u042d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0442.\u043a. \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0438\u0437 Job&#8217;\u044b \u043a Job&#8217;\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a \u044d\u0442\u043e\u043c\u0443, \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e CI\/CD pipeline \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043e \u0437\u0430 \u0441\u0447\u0435\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0441 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u043c, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0432\u043e\u0439 Docker-\u043e\u0431\u0440\u0430\u0437. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0433\u043e \u043c\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043d\u0430\u0448\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448\u0435\u043c CI\/CD.<\/p>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u043c <code>Dockerfile<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. \u041d\u0438\u0436\u0435 \u043f\u043e\u043b\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0430\u0448\u0435\u0433\u043e <code>Dockerfile<\/code>.<\/p>\n<pre><code class=\"bash\">FROM jangrewe\/gitlab-ci-android:33      ENV LC_ALL=\"en_US.UTF-8\" \\       LANG=\"en_US.UTF-8\" \\       MARATHON_VERSION=\"1.0.46\"      RUN apt-get update &amp;&amp; \\       apt-get install -y --no-install-recommends \\           openjdk-17-jdk \\           curl \\           gnupg2 \\           python3-pip \\           tar \\           bash &amp;&amp; \\           gpg2 --keyserver hkp:\/\/keyserver.ubuntu.com --recv-keys \\               409B6B1796C275462A1703113804BB82D39DC0E3 \\               7D2BAF1CF37B13E2069D6956105BD0E739499BDB &amp;&amp; \\           rm -rf \/var\/lib\/apt\/lists\/*    RUN curl -sSL https:\/\/get.rvm.io | bash -s stable &amp;&amp; \\       \/bin\/bash -lc \"rvm requirements\" &amp;&amp; \\       \/bin\/bash -lc \"rvm install 3.2.2\"    ENV PATH=\"\/usr\/local\/rvm\/gems\/ruby-3.2.2\/bin:\/usr\/local\/rvm\/rubies\/ruby-3.2.2\/bin:\/usr\/local\/rvm\/bin:$PATH\"    RUN pip3 install awscli==1.36.0      RUN curl https:\/\/dl.google.com\/dl\/cloudsdk\/channels\/rapid\/google-cloud-sdk.tar.gz --output \/tmp\/google-cloud-sdk.tar.gz &amp;&amp; \\       mkdir -p \/google &amp;&amp; \\       tar zxf \/tmp\/google-cloud-sdk.tar.gz --directory \/google &amp;&amp; \\       \/google\/google-cloud-sdk\/install.sh --quiet      ENV PATH=\"\/google\/google-cloud-sdk\/bin:$PATH\"      RUN curl -L https:\/\/github.com\/MarathonLabs\/marathon-cloud-cli\/releases\/download\/${MARATHON_VERSION}\/marathon-cloud-v${MARATHON_VERSION}-{\u0410\u0440\u0445\u0438\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d} -o \/tmp\/marathon-cloud &amp;&amp; \\       mkdir -p \/marathon &amp;&amp; \\       tar -xzf \/tmp\/marathon-cloud --directory \/marathon &amp;&amp; \\       mv \/marathon\/marathon-cloud-v${MARATHON_VERSION}-{\u0410\u0440\u0445\u0438\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d}\/marathon-cloud \/usr\/local\/bin\/ &amp;&amp; \\       chmod +x \/usr\/local\/bin\/marathon-cloud    WORKDIR \/app      CMD [\"bash\"]<\/code><\/pre>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e Docker-\u043e\u0431\u0440\u0430\u0437\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 <code>FROM<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u0434\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437, \u043f\u043e\u0432\u0435\u0440\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439.<\/p>\n<pre><code class=\"bash\">FROM jangrewe\/gitlab-ci-android:33<\/code><\/pre>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"bash\">ENV LC_ALL=\"en_US.UTF-8\" \\       LANG=\"en_US.UTF-8\" \\       MARATHON_VERSION=\"1.0.46\" <\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 <code>apt<\/code> (Advanced Packaging Tool).<\/p>\n<p>\u0413\u0434\u0435:<\/p>\n<ul>\n<li>\n<p><code>openjdk-17-jdk<\/code> \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u043c, \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c 17 \u0432\u0435\u0440\u0441\u0438\u044e Java, \u043b\u0438\u0431\u043e \u043b\u044e\u0431\u0443\u044e \u0434\u0440\u0443\u0433\u0443\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0443 \u0432\u0430\u0441 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435;<\/p>\n<\/li>\n<li>\n<p><code>curl<\/code> \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 <code>Marathon<\/code> \u0438\u043b\u0438 <code>Google Cloud SDK<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>gnupg2<\/code> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 <code>RVM<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>python3-pip<\/code> \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 <code>awscli<\/code> \u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>google cloud<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>tar<\/code>, <code>bash<\/code> \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0430\u0440\u0445\u0438\u0432\u043e\u0432 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <code>GPG-\u043a\u043b\u044e\u0447\u0438<\/code> \u0434\u043b\u044f \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 <code>RVM<\/code>, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d\u0438 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 <code>RVM<\/code>. \u0418 \u043f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0433\u043e, \u0447\u0438\u0441\u0442\u0438\u043c \u043a\u044d\u0448 <code>apt<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>rm -rf \/var\/lib\/apt\/lists\/*<\/code>, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u043e\u0431\u0440\u0430\u0437\u0430.<\/p>\n<pre><code class=\"bash\">RUN apt-get update &amp;&amp; \\       apt-get install -y --no-install-recommends \\           openjdk-17-jdk \\           curl \\           gnupg2 \\           python3-pip \\           tar \\           bash &amp;&amp; \\           gpg2 --keyserver hkp:\/\/keyserver.ubuntu.com --recv-keys \\               409B6B1796C275462A1703113804BB82D39DC0E3 \\               7D2BAF1CF37B13E2069D6956105BD0E739499BDB &amp;&amp; \\           rm -rf \/var\/lib\/apt\/lists\/*<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <code>RVM<\/code> \u0438 <code>Ruby<\/code>. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 <code>Ruby<\/code>, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 <code>PATH<\/code>, \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u044f \u0443\u0436\u0435 \u043f\u0438\u0441\u0430\u043b \u0432\u044b\u0448\u0435.<\/p>\n<pre><code class=\"bash\">RUN curl -sSL https:\/\/get.rvm.io | bash -s stable &amp;&amp; \\       \/bin\/bash -lc \"rvm requirements\" &amp;&amp; \\       \/bin\/bash -lc \"rvm install 3.2.2\"      ENV PATH=\"\/usr\/local\/rvm\/gems\/ruby-3.2.2\/bin:\/usr\/local\/rvm\/rubies\/ruby-3.2.2\/bin:\/usr\/local\/rvm\/bin:$PATH\"  <\/code><\/pre>\n<p>\u0421\u0442\u0430\u0432\u0438\u043c <code>awscli<\/code>.<\/p>\n<pre><code class=\"bash\">RUN pip3 install awscli==1.36.0 <\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u0442\u0430\u0432\u0438\u043c <code>Google Cloud SDK<\/code> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>Firebase Test Lab<\/code>, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448\u0438 Android-\u0442\u0435\u0441\u0442\u044b \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e.<\/p>\n<pre><code class=\"bash\">RUN curl https:\/\/dl.google.com\/dl\/cloudsdk\/channels\/rapid\/google-cloud-sdk.tar.gz --output \/tmp\/google-cloud-sdk.tar.gz &amp;&amp; \\       mkdir -p \/google &amp;&amp; \\       tar zxf \/tmp\/google-cloud-sdk.tar.gz --directory \/google &amp;&amp; \\       \/google\/google-cloud-sdk\/install.sh --quiet   ENV PATH=\"\/google\/google-cloud-sdk\/bin:$PATH\" <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Android-\u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 <code>Marathon<\/code>, \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c <code>Marathon Cloud CLI<\/code>.<\/p>\n<pre><code class=\"bash\">RUN curl -L https:\/\/github.com\/MarathonLabs\/marathon-cloud-cli\/releases\/download\/${MARATHON_VERSION}\/marathon-cloud-v${MARATHON_VERSION}-{\u0410\u0440\u0445\u0438\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d} -o \/tmp\/marathon-cloud &amp;&amp; \\       mkdir -p \/marathon &amp;&amp; \\       tar -xzf \/tmp\/marathon-cloud --directory \/marathon &amp;&amp; \\       mv \/marathon\/marathon-cloud-v${MARATHON_VERSION}-{\u0410\u0440\u0445\u0438\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d}\/marathon-cloud \/usr\/local\/bin\/ &amp;&amp; \\       chmod +x \/usr\/local\/bin\/marathon-cloud  <\/code><\/pre>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0437\u0430\u0434\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e, \u0433\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0448\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 CI\/CD.<\/p>\n<pre><code class=\"bash\">WORKDIR \/app<\/code><\/pre>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>CMD<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0437\u0430\u043f\u0443\u0449\u0435\u043d.<\/p>\n<pre><code class=\"bash\">CMD [\"bash\"]<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0437 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0430 Docker Hub. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u043d\u0430 <a href=\"http:\/\/Docker.com\" rel=\"noopener noreferrer nofollow\">Docker.com<\/a>, \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0441\u043a\u0430\u0447\u0430\u0435\u043c <a href=\"https:\/\/www.docker.com\/products\/docker-desktop\/\" rel=\"noopener noreferrer nofollow\">Docker Desktop<\/a> \u043d\u0430 \u043d\u0430\u0448 \u041f\u041a. \u0414\u0430\u043b\u0435\u0435, \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c <a href=\"https:\/\/www.jetbrains.com\/help\/idea\/docker.html\" rel=\"noopener noreferrer nofollow\">Docker Plugin \u0434\u043b\u044f IntelliJ\u00a0IDEA<\/a> \u0438 \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e.<\/p>\n<p>\u0414\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0430, \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 <code>Build Image for...<\/code> \u0438 \u0436\u0434\u0435\u043c, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u0440\u0430\u0437 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0440\u0430\u043d.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a76\/b29\/060\/a76b290609f58fb5157774e1b2da3620.png\" width=\"597\" height=\"262\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a76\/b29\/060\/a76b290609f58fb5157774e1b2da3620.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a76\/b29\/060\/a76b290609f58fb5157774e1b2da3620.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u0440\u0430\u0437 \u0441\u043e\u0431\u0440\u0430\u043d, \u0432 \u0441\u0440\u0435\u0434\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 <code>Services &gt; {\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0437} &gt; Dashboard<\/code>, \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 <code>Tags Add...<\/code> \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0438 \u0432\u0435\u0440\u0441\u0438\u044e \u043e\u0431\u0440\u0430\u0437\u0430.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2dc\/1f3\/2dc\/2dc1f32dc128933caa8cf05042ba6852.png\" width=\"1256\" height=\"415\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/2dc\/1f3\/2dc\/2dc1f32dc128933caa8cf05042ba6852.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2dc\/1f3\/2dc\/2dc1f32dc128933caa8cf05042ba6852.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0437 \u0432 Docker Hub, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 Docker Desktop, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u0440\u0430\u043d\u0435\u0435. \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 <code>Images<\/code>, \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0437 \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <code>Push to Docker Hub<\/code>. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0437 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u043b\u0438\u0447\u043d\u043e\u043c \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435 Docker Hub, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448\u0435\u043c CI\/CD.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e88\/56f\/6f2\/e8856f6f2219449c5d8e9ba862ad54aa.png\" width=\"1574\" height=\"229\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e88\/56f\/6f2\/e8856f6f2219449c5d8e9ba862ad54aa.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e88\/56f\/6f2\/e8856f6f2219449c5d8e9ba862ad54aa.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043d\u0430\u0448 Docker-\u043e\u0431\u0440\u0430\u0437 \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c CI\/CD \u0443\u0431\u0440\u0430\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043d\u0438\u0436\u0435 \u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Fastlane, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0431\u0440\u0430\u0432 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b.<\/p>\n<pre><code class=\"yaml\">deployReleaseUsingFastlane:     stage: deploy_release     image: {\u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0448 Docker-\u043e\u0431\u0440\u0430\u0437 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438}   script:       - bundle install       - bundle exec fastlane install_plugins      - export VERSION_NAME=\"#PRODUCTION_RELEASE  $(cat version_name.txt)\"       - export CHANGELOG=\"$(cat changelog.txt)\"          - bundle exec fastlane deployRelease       - bundle exec fastlane notifyReleaseToTelegram version:${VERSION_NAME} changelog:${CHANGELOG}       - bundle exec fastlane createGitTag tag_name:${VERSION_NAME} message:${CHANGELOG}    rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"master\"'<\/code><\/pre>\n<blockquote>\n<p>\u0412\u0410\u0416\u041d\u041e<br \/>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 Docker-\u043e\u0431\u0440\u0430\u0437\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u043c. \u0412 \u043d\u0435\u043c \u044f \u043f\u0440\u0438\u0432\u0435\u043b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u0441\u0435\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0445 3-\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u0440\u043e CI\/CD. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0430\u0448 Docker-\u043e\u0431\u0440\u0430\u0437 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u043c, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u0442\u0443\u0434\u0430 \u0432\u0441\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0442.\u043a. \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b \u0432\u0440\u044f\u0434-\u043b\u0438 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u0435 \u0432\u0430\u0448 pipeline \u0432\u0432\u0438\u0434\u0443 \u0442\u044f\u0436\u0435\u043b\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0430.<\/p>\n<p>\u041b\u0443\u0447\u0448\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u043f\u043e\u0434 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f Android-\u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 Marathon \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0437, \u043a\u0443\u0434\u0430 \u0432\u043e\u0439\u0434\u0435\u0442 Marathon Cloud CLI \u0438 Android SDK, \u0430 \u0434\u043b\u044f Firebase Test Lab \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0437. \u0422\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0432\u044b \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u0435 \u0440\u0430\u0437\u043c\u0435\u0440 \u0432\u0430\u0448\u0438\u0445 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432.<\/p>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u0430\u0448\u0435\u0433\u043e Gitlab CI\/CD, <a href=\"https:\/\/habr.com\/ru\/companies\/gitlab\/articles\/646579\/\" rel=\"noopener noreferrer nofollow\">\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u044d\u0442\u043e\u0439 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>.<\/p>\n<\/blockquote>\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\u0439 \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u0440\u043e Gitlab CI\/CD \u0434\u043b\u044f Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 CI\/CD, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0441\u0431\u043e\u0440\u043a\u0435, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Android-\u0442\u0435\u0441\u0442\u043e\u0432, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Play Store. \u0418 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0441\u043d\u0443\u043b\u0438\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e CI\/CD.<\/p>\n<p>\u0422\u0435\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u043b\u0438, \u0431\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0431\u0448\u0438\u0440\u043d\u044b\u043c\u0438, \u043d\u043e \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e, \u043f\u0443\u0441\u0442\u044c \u0438 \u043f\u043e \u0432\u0435\u0440\u0445\u0430\u043c, \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u043a\u043e\u043c\u0443-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0435\u0440\u0438\u044f \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e CI\/CD.<\/p>\n<p>\u0415\u0449\u0435 \u0443\u0432\u0438\u0434\u0438\u043c\u0441\u044f!<\/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\/925092\/\"> https:\/\/habr.com\/ru\/articles\/925092\/<\/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<figure class=\"full-width\"><\/figure>\n<h2>\u041e \u0447\u0451\u043c \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f?<\/h2>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041a\u0438\u0440\u0438\u043b\u043b \u0438 \u044f Android-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 Scanny. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u0442\u043e, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043d\u0430\u0448 CI\/CD, \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c Android (<a href=\"https:\/\/github.com\/MarathonLabs\/marathon\" rel=\"noopener noreferrer nofollow\">Marathon Labs<\/a> \u0438 <a href=\"https:\/\/firebase.google.com\/docs\/test-lab\" rel=\"noopener noreferrer nofollow\">Firebase Test Lab<\/a>) \u0438 Unit-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 Build Flavors \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0432 \u043d\u0430\u0448\u0443 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0441\u0432\u0435\u0436\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u0432 Play Market \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher\" rel=\"noopener noreferrer nofollow\">Gradle Play Publisher<\/a> \u0438 <a href=\"https:\/\/github.com\/fastlane\/fastlane\" rel=\"noopener noreferrer nofollow\">Fastlane<\/a>, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u0432 Gitlab Tag \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0448\u043b\u0438 \u0432 \u043d\u0430\u0448\u0443 \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043c\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u043c \u043d\u0430\u0448 CI\/CD, \u0441\u043e\u0431\u0440\u0430\u0432 \u0441\u0432\u043e\u0439 Docker-\u043e\u0431\u0440\u0430\u0437 \u0441\u043e \u0432\u0441\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u043c. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b (Python, awscli \u0438 \u0434\u0440\u0443\u0433\u0438\u0435), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u043d\u0430\u0448 pipeline.<\/p>\n<p>\u0426\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u0440\u043e CI\/CD \u0434\u043b\u044f Android \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437:<\/p>\n<ol>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/918364\/\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c CI\/CD Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0430\u0441\u0442\u044c 1. \u041d\u0430\u0447\u0430\u043b\u043e.<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/922066\/\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c CI\/CD Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0430\u0441\u0442\u044c 2. \u0417\u0430\u043f\u0443\u0441\u043a Android-\u0442\u0435\u0441\u0442\u043e\u0432.<\/a><\/p>\n<\/li>\n<li>\n<p>\u0412\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0435\u0441\u044c \u0437\u0434\u0435\u0441\u044c.<\/p>\n<\/li>\n<\/ol>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Play Console<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Play Console \u0438 Google Services, \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432 <a href=\"https:\/\/play.google.com\/console\/\" rel=\"noopener noreferrer nofollow\">Play Console<\/a>. \u0422\u0430\u043a \u0436\u0435 \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Play Store, \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0434\u0435\u043b\u0443, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c Google Services \u0441 \u043d\u0430\u0448\u0435\u0439 Play Console, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 <a href=\"https:\/\/console.cloud.google.com\/iam-admin\/serviceaccounts?hl=en\" rel=\"noopener noreferrer nofollow\">Service Accounts<\/a>, \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 <code>Create service account<\/code>. \u0412 \u043d\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u0430 <code>Basic - Viewer<\/code>. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 \u043c\u044b \u0443\u0436\u0435 \u0434\u0435\u043b\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/922066\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e CI\/CD<\/a>, \u043a\u043e\u0433\u0434\u0430 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043b\u0438 Google Services \u0441 Firebase, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443. \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a Service Account \u0441\u043e\u0437\u0434\u0430\u043d, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c JSON-\u043a\u043b\u044e\u0447 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043d\u0430\u0448 <a href=\"https:\/\/play.google.com\/console\/?hl=en\" rel=\"noopener noreferrer nofollow\">Play Console<\/a>, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 <code>Users and Permissions<\/code> \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 <code>Invite new users<\/code> \u0432 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c \u043c\u0435\u043d\u044e.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u043f\u043e\u043b\u0435 <code>Email address<\/code> \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u0447\u0442\u0443 \u043d\u0430\u0448\u0435\u0433\u043e Service Account. \u0412 <code>Account permissions<\/code> \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u0430:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0430 <code>App access<\/code> &#8212; \u043b\u0438\u0431\u043e <code>Admin<\/code>, \u043b\u0438\u0431\u043e <code>View app information and download bulk reports<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0434\u0435\u043b <code>Releases<\/code> &#8212; \u0441\u0442\u0430\u0432\u0438\u043c <code>Release to production, exclude devices, and use Play App Signing<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430 \u0432\u0430\u0448\u0435 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0443 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <code>Invite User<\/code>.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0421 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c Google Services \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Gradle Play Publisher<\/h2>\n<p>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 2 \u044d\u0442\u0430\u043f\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u0421\u0431\u043e\u0440\u043a\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Play Market, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Gitlab Tag \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher\" rel=\"noopener noreferrer nofollow\">Gradle Play Publisher<\/a> &#8212; \u044d\u0442\u043e gradle-\u043f\u043b\u0430\u0433\u0438\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \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\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e Android-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041f\u0440\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0442.\u043a. <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher\" rel=\"noopener noreferrer nofollow\">\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432 \u0441\u0430\u043c\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>, \u0430 \u0432\u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c. \u041f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u0445\u043e\u0447\u0443 \u043d\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432 Play Market. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>RuStore<\/code>, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/cianru\/rustore-publish-gradle-plugin\" rel=\"noopener noreferrer nofollow\">\u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e<\/a>. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0435\u0441\u0442\u044c \u0438 \u0434\u043b\u044f <a href=\"https:\/\/github.com\/cianru\/huawei-appgallery-publish-gradle-plugin\" rel=\"noopener noreferrer nofollow\">Huawei AppGallery<\/a>.<\/p>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a Gradle Play Publisher, \u043f\u043b\u0430\u0433\u0438\u043d \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0431\u043e\u0440\u043a\u0438, \u0434\u0435\u0442\u0430\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0438\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439, <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher?tab=readme-ov-file#uploading-release-notes\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0443\u0442<\/a>.<\/p>\n<p>\u041f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 <code>production<\/code>, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f) &#8212; <code>app\/src\/main\/play\/release-names\/production.txt<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 &#8212; <code>app\/src\/main\/play\/release-notes\/ru-RU\/production.txt<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0430 \u043d\u0438\u0436\u0435.<\/p>\n<pre><code>{root} |-- app   |-- src     |-- main       |-- play         |-- release-names           |-- production.txt         |-- release-notes           |-- ru-RU             |-- production.txt<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u043b\u0435\u0437\u0442\u044c \u0432 <code>Gradle<\/code>, \u0447\u0442\u043e\u0431\u044b \u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0432\u0435\u0440\u0441\u0438\u044e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0442\u043e\u043c\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0437\u0430\u043d\u044f\u0442\u0438\u0435\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0436\u0438\u0437\u043d\u044c \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c <code>versionName<\/code> \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438.  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>getVersionName()<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043b\u044f Play Console. \u0410 \u0432\u043e\u0442 <code>versionCode<\/code> \u043c\u043e\u0436\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432 \u0435\u0434\u0438\u043d\u0438\u0446\u0443 (\u0438\u043b\u0438 \u043b\u044e\u0431\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435), \u0442.\u043a. \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448 \u043f\u043b\u0430\u0433\u0438\u043d.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c <code>app\/build.gradle<\/code>.<\/p>\n<pre><code class=\"kotlin\">internal fun getVersionName(): String {       val file = file(\"src\/main\/play\/release-names\/production.txt\")       val versionName = file.readText()       return versionName.ifEmpty { \"Test Version\" }   }      play {       \/** \u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c GPP \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u0431\u043e\u0440\u043e\u043a, \u043c\u044b \u0432\u0435\u0434\u044c \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 build \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 Play Market? **\/     enabled.set(false)          \/** \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b: internal, alpha, beta, production.      \u041e\u0434\u043d\u0430\u043a\u043e, \u043c\u044b \u0436\u0435 \u0445\u043e\u0442\u0438\u043c \u0441\u0440\u0430\u0437\u0443 \u0432 production! **\/     track.set(\"production\")      \/** \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435.      \u0413\u0434\u0435, 0.6 = 60%. \u0422\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f IN_PROGRESS \u0438 HALTED. **\/     userFraction.set(0.6)      \/** \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e GPP \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 APK, \u043d\u043e \u043d\u0430\u043c \u0436\u0435 \u043d\u0443\u0436\u0435\u043d Bundle?      \u0413\u0434\u0435 true - \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c bundle, false - APK. **\/     defaultToAppBundles.set(true)      \/** \u0422\u0443\u0442 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0430 \u0441 \u0442\u0430\u043a\u0438\u043c versionCode \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.      AUTO_OFFSET \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 versionCode \u0432 Play Console \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443. **\/     resolutionStrategy.set(ResolutionStrategy.AUTO_OFFSET)      \/** \u0417\u0434\u0435\u0441\u044c: COMPLETED - \u043f\u043e\u043b\u043d\u0430\u044f \u0440\u0430\u0441\u043a\u0430\u0442\u043a\u0430 \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439;      DRAFT - \u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a, \u0441\u0431\u043e\u0440\u043a\u0430 \u0435\u0449\u0435 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u0430 \u043a \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438;     HALTED - \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430;     IN_PROGRESS - \u0440\u0435\u043b\u0438\u0437 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u0443\u044e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 60% **\/     releaseStatus.set(ReleaseStatus.IN_PROGRESS) }      android {       ...     playConfigs {           register(\"productionRelease\") {             \/** \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c GPP \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e build flavor.              \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0443\u0441\u0442\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 production release. **\/             enabled.set(true)         }       }            defaultConfig {           ...         versionCode = 1           versionName = getVersionName()           ...      } }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/developers.google.com\/android-publisher\/api-ref\/rest\/v3\/edits.tracks#status\" rel=\"noopener noreferrer nofollow\">Release Statuses \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a>. \u0420\u0430\u043d\u0435\u0435 \u043c\u044b \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043b\u0438 Google Services \u0441 Play Console, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0447\u0435\u0433\u043e \u0443 \u043d\u0430\u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0441\u044f JSON-\u043a\u043b\u044e\u0447, \u043e\u043d \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b GPP \u0441\u043c\u043e\u0433 \u0441\u0432\u044f\u0437\u0430\u0442\u044c\u0441\u044f \u0441 \u043d\u0430\u0448\u0435\u0439 Play Console.<\/p>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c 2 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043a\u043b\u044e\u0447:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <code>ANDROID_PUBLISHER_CREDENTIALS<\/code>, \u0447\u0442\u043e\u0431\u044b GPP \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0440\u0430\u043b \u0435\u0433\u043e \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043c\u044b \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c!<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0438 \u0437\u0430\u0442\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">play {     serviceAccountCredentials.set(file(\"your-key.json\")) }<\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430 \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a CI\/CD pipeline&#8217;\u0443.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 CI\/CD<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u043c\u0438 \u0441\u0442\u043e\u0438\u0442 2 \u0437\u0430\u0434\u0430\u0447\u0438, \u044d\u0442\u043e &#8212; \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 Play Market \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0439\u0434\u0443\u0442 \u0432 \u044d\u0442\u043e\u0442 \u0440\u0435\u043b\u0438\u0437, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Gitlab Tag&#8217;\u0430\u043c\u0438. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0435\u0449\u0435 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u0432 \u043d\u0430\u0448\u0435\u0439 Telegram-\u0433\u0440\u0443\u043f\u043f\u0435. <a href=\"https:\/\/habr.com\/ru\/companies\/scanny\/articles\/918364\/\" rel=\"noopener noreferrer nofollow\">\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0443\u0436\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u044d\u0442\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <code>stages<\/code> 2 \u043d\u043e\u0432\u044b\u0445: <code>deploy_release<\/code> \u0438 <code>create_git_tag<\/code>.<\/p>\n<pre><code class=\"yaml\">stages:     - lint     - tests     - build_flavors     - deploy_release     - create_git_tag<\/code><\/pre>\n<h2>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GPP<\/h2>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u044e, \u0447\u0442\u043e \u0440\u0430\u043d\u0435\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 2 \u0444\u0430\u0439\u043b\u0430: <code>app\/src\/main\/play\/release-names\/production.txt<\/code> \u0434\u043b\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 <code>app\/src\/main\/play\/release-notes\/ru-RU\/production.txt<\/code> \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0439\u0434\u0443\u0442 \u0432 \u044d\u0442\u0443 \u0441\u0431\u043e\u0440\u043a\u0443. \u041f\u0435\u0440\u0435\u0434 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u043c\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 \u043d\u0438\u0445 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0442\u0435\u043c \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 Play Store.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 Job&#8217;\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Play Market, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0443.<\/p>\n<pre><code class=\"yaml\">deployRelease:     stage: deploy_release     before_script:     - apt update       - apt install python3-pip --yes          - pip3 install awscli --upgrade   script:          - .\/gradlew publishProductionReleaseBundle       - .\/gradlew assembleProductionRelease      - export VERSION_NAME=\"#PRODUCTION_RELEASE  $(cat app\/src\/main\/play\/release-names\/production.txt)\\n\"     - export CHANGELOG=\"$(cat app\/src\/main\/play\/release-notes\/ru-RU\/production.txt)\\n\"              - aws s3 cp app\/build\/outputs\/apk\/production\/release\/app-production-release.apk s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk --endpoint https:\/\/storage.yandexcloud.net       - chmod a+x .\/upload_telegram_link.sh         - aws s3 presign s3:\/\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u043a\u0435\u0442\u0430 \u0432 s3}\/{\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u043a\u0435\u0442\u0435}.apk --endpoint-url \"https:\/\/storage.yandexcloud.net\/\" --expires-in 604800|source upload_telegram_link.sh     artifacts:       paths:         - app\/build\/outputs\/apk\/       expire_in: 10 days     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"master\"'<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432 <code>before_script<\/code> \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <code>Python3<\/code> \u0438 <code>pip<\/code> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 awscli. \u0427\u0442\u043e\u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b 2 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code>AWS_ACCESS_KEY_ID<\/code> (ID \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430) \u0438 <code>AWS_SECRET_ACCESS_KEY<\/code> (\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u043b\u044e\u0447\u0430). <a href=\"https:\/\/yandex.cloud\/ru\/docs\/storage\/tools\/aws-cli#before-you-begin\" rel=\"noopener noreferrer nofollow\">\u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0438\u0445 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<pre><code class=\"yaml\">before_script:     - apt update       - apt install python3-pip --yes          - pip3 install awscli --upgrade<\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430\u0448\u0443 \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Play Console. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c Bundle. \u0415\u0441\u043b\u0438 \u0436\u0435 \u043c\u044b \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u0445\u043e\u0442\u0438\u043c \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c APK, \u0442\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>publishProductionReleaseApk<\/code>. \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: <code>publish{Build flavor}{Bundle\/Apk}<\/code>.<\/p>\n<pre><code class=\"yaml\">.\/gradlew publishProductionReleaseBundle  <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Play Console \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 Telegram-\u0433\u0440\u0443\u043f\u043f\u0435 \u043e \u043d\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c APK.<\/p>\n<pre><code class=\"yaml\">.\/gradlew assembleProductionRelease  <\/code><\/pre>\n<p>\u041a\u0430\u043a \u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b \u0440\u0430\u043d\u0435\u0435, \u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445 \u043c\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043d\u0435\u0435 \u0432\u0445\u043e\u0434\u044f\u0442. \u042d\u0442\u0443 \u0436\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u043e \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435.<\/p>\n<pre><code class=\"yaml\">export<\/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-466089","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/466089","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=466089"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/466089\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=466089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=466089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=466089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}