{"id":463391,"date":"2025-06-14T21:00:32","date_gmt":"2025-06-14T21:00:32","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=463391"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=463391","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 1. \u041d\u0430\u0447\u0430\u043b\u043e<\/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\/a7f\/772\/104\/a7f7721049ff489cff146ef4e253b3f6.jpg\" width=\"780\" height=\"426\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a7f\/772\/104\/a7f7721049ff489cff146ef4e253b3f6.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a7f\/772\/104\/a7f7721049ff489cff146ef4e253b3f6.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h2>\u041e \u0447\u0451\u043c \u044d\u0442\u0430 \u0441\u0435\u0440\u0438\u044f \u0441\u0442\u0430\u0442\u0435\u0439?<\/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. \u0421\u0440\u0430\u0437\u0443 \u043e\u0433\u043e\u0432\u043e\u0440\u044e\u0441\u044c, \u043a\u0430\u0441\u0430\u0435\u043c\u043e CI\/CD, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0431\u0443\u0434\u0443 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c &#8212; \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u0435\u0442 \u043d\u0430 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0442.\u0434. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c &#8212; \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439, \u0434\u0430, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u043c\u0430\u043b\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 Habr, \u0434\u0430 \u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u0445 \u0442\u043e\u0436\u0435. \u0418 \u0431\u0443\u0434\u0435\u0442\u0435 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043f\u0440\u0430\u0432\u044b. \u041d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 2 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438: \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u043b\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0451 \u0442\u0430\u043a, \u043a\u0430\u043a \u043d\u0443\u0436\u043d\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u043d\u0435. \u0410 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043b\u0438\u0441\u044c, \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u043a\u0438\u0434\u0430\u043d\u044b \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u0435\u0431\u044f. \u041d\u043e \u0432\u0435\u0440\u044e, \u0447\u0442\u043e \u0447\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0445 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u0442\u0435\u043c \u043f\u0440\u043e\u0449\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u0434\u0440\u0443\u0433\u0438\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u043c\u0435.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e &#8212; \u043c\u043e\u044f \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f &#171;\u0435\u0449\u0435 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e CI\/CD \u043d\u0430 Android&#187; &#8212; \u043f\u043e\u043c\u043e\u0447\u044c \u0441\u0435\u0431\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c, \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 CI\/CD. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u043d\u043e\u0439 &#8212; \u0432\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0443 \u0432\u0441\u0435\u0445 \u0440\u0430\u0437\u043d\u044b\u0435.<\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0435\u0440\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 3 \u0441\u0442\u0430\u0442\u0435\u0439:<\/p>\n<ol>\n<li>\n<p>\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.<\/p>\n<\/li>\n<li>\n<p>\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.<\/p>\n<\/li>\n<li>\n<p>\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 Market.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u043b\u0430 \u0438\u0434\u0435\u044f \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0438\u0448\u0451\u043b \u043a \u043c\u043d\u0435\u043d\u0438\u044e, \u0447\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0441\u0442\u0430\u0442\u044c\u044f \u0440\u0430\u0437\u0434\u0443\u0435\u0442\u0441\u044f \u0434\u043e \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0445 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0443\u0441\u0442\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 \u0441 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438 \u043d\u0430\u043b\u0430\u0434\u0438\u0442\u044c CI\/CD.<\/p>\n<h2>\u0422\u0435\u043f\u0435\u0440\u044c \u043a \u0441\u0443\u0442\u0438<\/h2>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 CI\/CD \u0437\u0432\u0443\u0447\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: <a href=\"https:\/\/www.redhat.com\/en\/topics\/devops\/what-is-ci-cd\" rel=\"noopener noreferrer nofollow\">&#8230; \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0443\u044e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0438 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0443\u044e \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443\/\u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0446\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u041f\u041e.<\/a> \u0421 \u043c\u043e\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u044f \u044d\u0442\u043e \u0432\u0438\u0436\u0443 \u043a\u0430\u043a \u043d\u0430\u0431\u043e\u0440 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u044d\u043a\u043e\u043d\u043e\u043c\u044f\u0442 \u0432\u0440\u0435\u043c\u044f, \u0447\u0442\u043e \u043d\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u0442\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0440\u0430\u043a\u0442\u043e\u0432\u043a\u0438.<\/p>\n<h3>\u041a\u043e\u043c\u0443 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442?<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u043d\u0430\u0434 \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0440\u043e\u0447\u043d\u044b\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0433\u0434\u0435 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u044b \u043a \u043d\u0435\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0432\u0435\u0440\u043d\u0435\u0442\u0435\u0441\u044c, \u0442\u043e CI\/CD, \u0441\u043a\u043e\u0440\u0435\u0435, \u043e\u0442\u043d\u0438\u043c\u0435\u0442 \u0443 \u0432\u0430\u0441 \u0432\u0440\u0435\u043c\u044f. \u0412 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f, \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u043d\u0430\u0434 \u0434\u043e\u043b\u0433\u043e\u0438\u0433\u0440\u0430\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0442\u043e CI\/CD \u0434\u0430\u0441\u0442 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0434\u0435\u043f\u043b\u043e\u0435 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430.<\/p>\n<h3>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/h3>\n<p>\u0414\u0435\u043b\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 CI\/CD \u043d\u0430 Gitlab, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438. \u041d\u0438\u0436\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043e \u0441\u0445\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e pipeline.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e3d\/8d1\/e5c\/e3d8d1e5cc40ea12098982aed155bd6c.png\" width=\"1206\" height=\"450\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e3d\/8d1\/e5c\/e3d8d1e5cc40ea12098982aed155bd6c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e3d\/8d1\/e5c\/e3d8d1e5cc40ea12098982aed155bd6c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433:<\/p>\n<h4>1. \u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u043a\u043e\u0434\u0430<\/h4>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439, \u0447\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f &#171;\u0438\u0437 \u043f\u043e\u0434 \u043a\u043e\u0440\u043e\u0431\u043a\u0438&#187;, <a href=\"https:\/\/developer.android.com\/studio\/write\/lint\" rel=\"noopener noreferrer nofollow\">Android Lint<\/a>. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435 \u043c\u0430\u043b\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u0434\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/github.com\/detekt\/detekt\" rel=\"noopener noreferrer nofollow\">detekt<\/a>, <a href=\"https:\/\/github.com\/pinterest\/ktlint\" rel=\"noopener noreferrer nofollow\">ktlint<\/a>, <a href=\"https:\/\/www.sonarsource.com\/products\/sonarqube\/\" rel=\"noopener noreferrer nofollow\">SonarQube<\/a> \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0435. \u0412 pipeline \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 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435. \u041e\u0442\u0447\u0451\u0442 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432 \u0441\u0430\u043c\u044b\u0445 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 Gitlab.<\/p>\n<h4>2. \u0417\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432<\/h4>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 \u0432\u0430\u0448\u0435\u043c Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u043a\u0430\u043a Unit-\u0442\u0435\u0441\u0442\u044b, \u0442\u0430\u043a \u0438 Android-\u0442\u0435\u0441\u0442\u044b. Unit-\u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043c\u0435\u0442\u043e\u0434\u044b \u0431\u0438\u0437\u043d\u0435\u0441-\u0441\u043b\u043e\u044f, \u0431\u0435\u0437 Android-\u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0439.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f Unit-\u0442\u0435\u0441\u0442\u043e\u0432, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/willowtreeapps\/assertk\" rel=\"noopener noreferrer nofollow\">AssertK<\/a>, <a href=\"https:\/\/github.com\/mockito\/mockito-kotlin\" rel=\"noopener noreferrer nofollow\">Mockito Kotlin<\/a> \u0438 <a href=\"https:\/\/developer.android.com\/kotlin\/coroutines\/test\" rel=\"noopener noreferrer nofollow\">Kotlin coroutines<\/a>. Android-\u0442\u0435\u0441\u0442\u044b \u0443\u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a UI, \u0433\u0434\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/KasperskyLab\/Kaspresso\" rel=\"noopener noreferrer nofollow\">Kaspresso<\/a>, \u0442\u0430\u043a \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/robolectric\/robolectric\" rel=\"noopener noreferrer nofollow\">Robolectric<\/a> \u0438\u043b\u0438 <code>Kaspresso<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0441\u044f. \u041c\u044b \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>Kaspresso<\/code>, \u0442.\u043a. \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u0435\u043d \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f UI, \u043d\u043e \u0438 \u0434\u043b\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p>\u0422\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0442 \u0432\u0441\u0442\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u0433\u0434\u0435 \u0438 \u043a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c Android-\u0442\u0435\u0441\u0442\u044b? \u0423\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043a\u0430\u043a \u043d\u0430 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u0445, \u0442\u0430\u043a \u0438 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445. \u042f \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b 2 \u0440\u0435\u0448\u0435\u043d\u0438\u044f: <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>.  \u041e\u0431\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0442\u043e <code>Marathon Labs<\/code> \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0430\u0441, \u0433\u0434\u0435 \u0438 \u043a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u0442\u0435\u0441\u0442\u044b. \u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, <code>Firebase Test Lab<\/code> \u043d\u0435 \u0434\u0430\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438, \u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Android-\u0442\u0435\u0441\u0442\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u044d\u0442\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0412 pipeline Unit-\u0442\u0435\u0441\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435. \u0410 \u0432\u043e\u0442 Android-\u0442\u0435\u0441\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 merge request&#8217;\u0430\u0445 \u0432 master.<\/p>\n<h4>3. \u0421\u0431\u043e\u0440\u043a\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 \u0433\u0440\u0443\u043f\u043f\u0443 Telegram \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e commit&#8217;\u0430. \u0412 pipeline \u0441\u0431\u043e\u0440\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 merge request&#8217;\u0435 \u0432 develop.<\/p>\n<h4>4. \u0412\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c release-\u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Play Market<\/h4>\n<p>\u0422\u0443\u0442 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0443 \u043d\u0430\u0441 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0430\u0433\u043e\u0432, \u043d\u043e\u0432\u044b\u0435 \u0444\u0438\u0447\u0438 \u0438 \u0442.\u0434. \u0412\u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043e\u0439\u0434\u0443\u0442 \u0432 release-\u0441\u0431\u043e\u0440\u043a\u0443 \u0438 \u043e\u043d\u0430 \u0443\u043b\u0435\u0442\u0438\u0442 \u0432 Play Market \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\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> \u0438 <a href=\"https:\/\/github.com\/fastlane\/fastlane\" rel=\"noopener noreferrer nofollow\">Fastlane<\/a> \u0434\u043b\u044f \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.<\/p>\n<p>\u0412 pipeline \u0441\u0431\u043e\u0440\u043a\u0430 \u0434\u043b\u044f Play Market \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 merge request&#8217;\u0435 \u0432 master.<\/p>\n<h4>5. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Git-Tag \u0432 Gitlab<\/h4>\n<p>\u0414\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439\/release&#8217;\u043e\u0432 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/git-scm.com\/docs\/git-tag\" rel=\"noopener noreferrer nofollow\">Git-Tag<\/a>, \u0442\u0443\u0442 \u0432\u0441\u0435 \u043f\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0435. \u0412 pipeline \u0442\u0435\u0433\u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 Gitlab \u043f\u0440\u0438 merge request&#8217;\u0430\u0445 \u0432 master.<\/p>\n<h2>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a CI\/CD<\/h2>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h3>\n<p>\u0415\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 CI\/CD, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <a href=\"https:\/\/docs.github.com\/en\/actions\" rel=\"noopener noreferrer nofollow\">GitHub Actions<\/a>, <a href=\"https:\/\/www.jenkins.io\/\" rel=\"noopener noreferrer nofollow\">Jenkins<\/a>, <a href=\"https:\/\/docs.gitlab.com\/ci\/\" rel=\"noopener noreferrer nofollow\">GitLab<\/a>, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>.gitlab-ci.yml<\/code> \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0442\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0448 pipeline. \u0414\u0430, \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u0442\u0430\u043f \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438 \u0442.\u0434., \u043d\u043e \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0432\u0441\u0435 \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435, <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/includes\/\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0443\u0442<\/a>. \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u0442\u044b\u043a\u0430\u0435\u043c \u041f\u041a\u041c \u043f\u043e \u043a\u043e\u0440\u043d\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 -&gt; New -&gt; File -&gt; \u0412\u0432\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>.gitlab-ci.yml<\/code>.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/886\/ce6\/c55\/886ce6c554afb5c66d264714e672fb44.png\" width=\"530\" height=\"654\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/886\/ce6\/c55\/886ce6c554afb5c66d264714e672fb44.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/886\/ce6\/c55\/886ce6c554afb5c66d264714e672fb44.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0438\u0436\u0435. \u041a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448 <a href=\"https:\/\/docs.gitlab.com\/runner\/\" rel=\"noopener noreferrer nofollow\">Gitlab Runner<\/a>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ce1\/2f9\/b28\/ce12f9b286c8ab1fbe83c05098c3c974.png\" width=\"170\" height=\"107\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ce1\/2f9\/b28\/ce12f9b286c8ab1fbe83c05098c3c974.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ce1\/2f9\/b28\/ce12f9b286c8ab1fbe83c05098c3c974.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u043a\u043e\u0434\u0443.<\/p>\n<pre><code class=\"yaml\">image: jangrewe\/gitlab-ci-android:33      # \u0417\u0430\u0434\u0430\u0435\u043c \u044d\u0442\u0430\u043f\u044b   stages:     - lint     - tests     - build_flavors     - release     - create_git_tag      # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043e\u0431\u0449\u0438\u0439 before_script \u0434\u043b\u044f \u0432\u0441\u0435\u0445 jobs before_script:     - chmod +x .\/gradlew  <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c Android SDK \u0438 \u043f\u0440\u043e\u0447\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435. \u0427\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u044c, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 <a href=\"https:\/\/github.com\/jangrewe\/gitlab-ci-android\" rel=\"noopener noreferrer nofollow\">Docker image jangrewe\/gitlab-ci-android<\/a>.<\/p>\n<pre><code class=\"yaml\">image: jangrewe\/gitlab-ci-android:33  <\/code><\/pre>\n<p>\u0412 <strong>stages<\/strong> \u0437\u0430\u0434\u0430\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u0442\u0430\u043f\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e.<\/p>\n<pre><code class=\"yaml\">stages:     - lint     - tests     - build_flavors     - release     - create_git_tag <\/code><\/pre>\n<p>\u0412 <code>before_script<\/code>, \u0441\u0442\u0440\u043e\u0447\u043a\u0430 <code>chmod +x .\/gradlew<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u0444\u0430\u0439\u043b <code>gradlew<\/code> \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u043c (\u0434\u0430\u0435\u0442 \u0435\u043c\u0443 \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435). \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/#before_script\" rel=\"noopener noreferrer nofollow\">before_script \u0447\u0438\u0442\u0430\u0435\u043c \u0442\u0443\u0442<\/a>.<\/p>\n<pre><code class=\"yaml\">before_script:     - chmod +x .\/gradlew  <\/code><\/pre>\n<h3>\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430<\/h3>\n<pre><code class=\"yaml\">runAndroidLint:     stage: lint     script:       - .\/gradlew lint     artifacts:       paths:         - \"**\/lint-results.html\"       expire_in: 10 days       when:         always     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f <code>\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<\/code> \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435.<\/p>\n<p>\u0422\u0443\u0442 \u043c\u044b \u0434\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0439 Job&#8217;\u0435.<\/p>\n<pre><code class=\"yaml\">runAndroidLint:  <\/code><\/pre>\n<p>\u0412 <strong>stage<\/strong> \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u044d\u0442\u0430\u043f\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u044d\u0442\u0430 job&#8217;\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>lint<\/code>.<\/p>\n<pre><code class=\"yaml\">stage: lint<\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <code>script<\/code> \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0438\u0448\u0435\u043c \u0441\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c. \u0417\u0434\u0435\u0441\u044c \u0441\u0442\u0440\u043e\u0447\u043a\u0430 <code>.\/gradlew lint<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 Android Lint.<\/p>\n<pre><code class=\"yaml\">script:       - .\/gradlew lint <\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <code>artifacts<\/code> \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432 <code>paths<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c, \u0432 <code>expire_in<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0438 \u0432 <code>when<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u0438 \u043a\u0430\u043a\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/#artifacts\" rel=\"noopener noreferrer nofollow\">artifacts \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\">artifacts:       paths:         - \"**\/lint-results.html\"       expire_in: 10 days       when:         always  <\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <code>rules<\/code> \u043c\u044b \u0437\u0430\u0434\u0430\u0435\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0448\u0430 job&#8217;\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>'$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/#rules\" rel=\"noopener noreferrer nofollow\">rules \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0443\u0442<\/a>.<\/p>\n<pre><code class=\"yaml\">rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/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_PIPELINE_SOURCE<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0425\u0440\u0430\u043d\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0431\u044b\u043b \u0437\u0430\u043f\u0443\u0449\u0435\u043d pipeline. <a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/jobs\/job_rules.html#ci_pipeline_source-predefined-variable\" rel=\"noopener noreferrer nofollow\">\u0422\u0443\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432<\/a><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h3>Unit-tests<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0442\u0435\u0441\u0442\u0430\u043c, \u043f\u043e\u043a\u0430 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e Unit-\u0442\u0435\u0441\u0442\u044b, \u043a Android-\u0442\u0435\u0441\u0442\u0430\u043c \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0433\u0434\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0441\u0432\u044f\u0437\u0430\u0442\u044c <code>Marathon Labs<\/code> \u0438 <code>Firebase Test Lab<\/code> \u0441 \u043d\u0430\u0448\u0438\u043c CI\/CD.<\/p>\n<pre><code class=\"yaml\">runUnitTests:     stage: tests     script:       - .\/gradlew app:test       - .\/gradlew core:some-module:impl:test    ...    artifacts:       paths:         - \"**\/build\/reports\/tests\/testDebugUnitTest\/classes\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/packages\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/index.html\"       expire_in: 10 days       when:         always     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/code><\/pre>\n<p>\u0412 <code>stage<\/code> \u0432\u0441\u0435 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u044e \u0432\u044b\u0448\u0435, \u0437\u0430 \u0442\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u044d\u0442\u0430\u043f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f;<\/p>\n<pre><code class=\"yaml\">stage: tests<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0441\u0445\u0435\u043c\u043e\u0439 \u043d\u0438\u0436\u0435.<\/p>\n<pre><code class=\"yaml\">.\/gradlew {\u041c\u043e\u0434\u0443\u043b\u044c \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043f\u0430\u043a\u0435\u0442\u043e\u0432}:test<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c app \u043c\u043e\u0434\u0443\u043b\u0435 \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e <code>app:test<\/code>, \u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 \u0443\u0436\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u0430\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u043e\u0432. \u041a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440: <code>core:some-module:impl:test<\/code>.<\/p>\n<pre><code class=\"yaml\">script:       - .\/gradlew app:test       - .\/gradlew core:some-module:impl:test  <\/code><\/pre>\n<p>\u0412 <code>artifacts<\/code> \u0432\u0441\u0435 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0432\u044b\u0448\u0435.<\/p>\n<pre><code class=\"yaml\">artifacts:       paths:         - \"**\/build\/reports\/tests\/testDebugUnitTest\/classes\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/packages\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/index.html\"       expire_in: 10 days       when:         always<\/code><\/pre>\n<h3>Build flavors<\/h3>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0443 \u043d\u0430\u0441 \u0441\u0431\u043e\u0440\u043a\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Telegram. \u0414\u043e\u0441\u0442\u0443\u043f \u043a APK \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.<\/p>\n<pre><code class=\"yaml\">assembleSomeBuildFlavor:     stage: build_flavors     script:       - .\/gradlew assembleSomeBuildFlavorDebug           - apt update       - apt install python3-pip --yes          - pip3 install awscli --upgrade          - export VERSION_NAME=\"TEST VERSION\"       - export MR_COMMIT_MESSAGE=${CI_COMMIT_MESSAGE}          - aws s3 cp app\/build\/outputs\/apk\/{\u0412\u0430\u0448 flavor name}\/debug\/{\u0412\u0430\u0448 APK name}.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\/{\u0412\u0430\u0448 flavor name}\/       expire_in: 10 days     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"develop\"'<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0442.\u043a. \u0441\u0431\u043e\u0440\u043a\u0430 \u0443\u043b\u0435\u0442\u0430\u0435\u0442 \u0432 Telegram.<\/p>\n<p>\u0412 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0430\u0448 APK.<\/p>\n<pre><code class=\"yaml\">script:       - .\/gradlew assembleSomeBuildFlavorDebug<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u044d\u0442\u043e <a href=\"https:\/\/developer.android.com\/build\/build-variants\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442 (\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0441\u0431\u043e\u0440\u043e\u043a)<\/a> \u0438 <a href=\"https:\/\/developer.android.com\/build\/building-cmdline#build_bundle\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442 (\u0421\u0431\u043e\u0440\u043a\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e command line)<\/a>.<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0422\u0438\u043f \u0441\u0431\u043e\u0440\u043a\u0438<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">APK<\/p>\n<\/td>\n<td>\n<p align=\"left\">.\/gradlew assemble{Variant name\/flavor}<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Bundle<\/p>\n<\/td>\n<td>\n<p align=\"left\">.\/gradlew bundle{Variant name\/flavor}<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0412 \u043d\u0430\u0448\u0435\u0439 Telegram-\u0433\u0440\u0443\u043f\u043f\u0435, \u0434\u043e\u0441\u0442\u0443\u043f \u043a APK \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b \u0432 \u043e\u0431\u043b\u0430\u043a\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/aws.amazon.com\/cli\/\" rel=\"noopener noreferrer nofollow\">Amazon Web Services Command Line Interface \u0438\u043b\u0438 \u0436\u0435 AWS CLI<\/a>, \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 Amazon Web Services \u0438\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. \u0418 <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/\" rel=\"noopener noreferrer nofollow\">Yandex Object Storage<\/a> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 APK \u0432 \u043e\u0431\u043b\u0430\u043a\u0435. \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0443 <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/quickstart\/quickstart-aws-cli\" rel=\"noopener noreferrer nofollow\">AWS CLI \u0441 Yandex Object Storage \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0431\u0435\u0436\u0438\u043c\u0441\u044f \u043f\u043e \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u0435.<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u0441\u043f\u0438\u0441\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438.<\/p>\n<pre><code class=\"yaml\">- apt update  <\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c python \u0438 pip (\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430\u043c\u0438). \u0413\u0434\u0435, <code>--yes<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<pre><code class=\"yaml\">- apt install python3-pip --yes  <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0434\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 (awscli) \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u0432\u044b\u0448\u0435, \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"yaml\">- pip3 install awscli --upgrade  <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435.<\/p>\n<pre><code class=\"yaml\">- export VERSION_NAME=\"TEST VERSION\"   #\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 - export MR_COMMIT_MESSAGE=${CI_COMMIT_MESSAGE}  #\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u0435\u043a\u0441\u0442 \u0431\u0435\u0440\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 commit \u0432 \u0432\u0435\u0442\u043a\u0435<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043d\u0430\u0448 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 APK \u0432 s3-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c, \u043f\u043e\u0441\u043b\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\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\/download\" rel=\"noopener noreferrer nofollow\">\u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0442\u0443\u0442<\/a>.<\/p>\n<pre><code class=\"yaml\">- aws s3 cp app\/build\/outputs\/apk\/{\u0412\u0430\u0448 flavor name}\/debug\/{\u0412\u0430\u0448 apk name}.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>\u0414\u0430\u043b\u0435\u0435 \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0438\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u043c, \u043e\u0431 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043f\u043e\u0437\u0436\u0435, \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u043e\u043d \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u043e\u0442\u0430 \u0432 \u0433\u0440\u0443\u043f\u043f\u0443 Telegram.<\/p>\n<pre><code class=\"yaml\">- chmod a+x .\/upload_telegram_link.sh  <\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/concepts\/pre-signed-urls\" rel=\"noopener noreferrer nofollow\">Presigned Url<\/a>, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0422\u0430\u043a \u0436\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/operations\/objects\/link-for-download\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a> \u0438 <a href=\"https:\/\/yandex.cloud\/en\/docs\/storage\/operations\/objects\/link-for-download\" rel=\"noopener noreferrer nofollow\">\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0443\u0442<\/a>.<\/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>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0447\u0443 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 <code>--expires-in 604800<\/code> \u043c\u044b \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, \u0447\u0442\u043e \u0440\u0430\u0432\u043d\u044f\u0435\u0442\u0441\u044f 7 \u0434\u043d\u044f\u043c. \u0410 \u0447\u0435\u0440\u0435\u0437 \u0441\u0438\u043c\u0432\u043e\u043b <code>|<\/code> (pipe) \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#8212; \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443) \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u0433\u0434\u0435 <code>source upload_telegram_<\/code><a href=\"http:\/\/link.sh\" rel=\"noopener noreferrer nofollow\"><code>link.sh<\/code><\/a> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043d\u0430\u0448 \u0441\u043a\u0440\u0438\u043f\u0442 (\u041e \u043d\u0435\u043c \u0447\u0443\u0442\u044c \u043d\u0438\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e).<\/p>\n<pre><code class=\"yaml\">--expires-in 604800|source upload_telegram_link.sh  <\/code><\/pre>\n<p>\u0412 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u0445 GitLab \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u0430\u0448 APK.<\/p>\n<pre><code class=\"yaml\">artifacts:       paths:         - app\/build\/outputs\/apk\/{\u0412\u0430\u0448 flavor name}\/       expire_in: 10 days<\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043d\u0430\u0448 \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0440\u0438 MR \u0432 develop \u0432\u0435\u0442\u043a\u0443.<\/p>\n<pre><code class=\"yaml\">rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" &amp;&amp; $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == \"develop\"'<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, <a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/variables\/predefined_variables.html\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043d\u0438\u0445 \u0442\u0443\u0442<\/a>:<\/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\">VERSION_NAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">MR_COMMIT_MESSAGE<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f, \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0441\u0431\u043e\u0440\u043a\u0435, \u0431\u0435\u0440\u0435\u0442\u0441\u044f \u0438\u0437 <em>CI_COMMIT_MESSAGE<\/em><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_COMMIT_MESSAGE<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u0435\u043a\u0441\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_MERGE_REQUEST_TARGET_BRANCH_NAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0442\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u043b\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u043e\u0442\u0430 \u044f \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0434\u0443\u043c\u0430\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u043d\u043e, \u0430 \u0432\u043e\u0442 \u043a \u0440\u0430\u0437\u0431\u043e\u0440\u0443 \u043a\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c. \u041d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Telegram. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u044b\u043a\u0430\u0435\u043c <strong>\u041f\u041a\u041c \u043f\u043e \u043a\u043e\u0440\u043d\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 -&gt; New &#8212; &gt; File -&gt; \u0417\u0430\u0434\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0443<\/strong>, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>upload_telegram_<\/code><a href=\"http:\/\/link.sh\" rel=\"noopener noreferrer nofollow\"><code>link.sh<\/code><\/a>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0438\u0448\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code>#!\/bin\/bash   encodeurl() {     python3 -c \"import urllib.parse; import sys; url = sys.stdin.read(); print(urllib.parse.quote(url))\"   }   TIME=\"10\"   TG_API_URL=\"https:\/\/api.telegram.org\/bot${TELEGRAM_BOT_TOKEN}\/sendMessage\"      read S3URL   ENCODED_S3URL=$(echo ${S3URL} | encodeurl)   curl -s --max-time ${TIME} -d \"chat_id=${TELEGRAM_CHAT_ID}&amp;disable_web_page_preview=1&amp;text=${VERSION_NAME} %0A${MR_COMMIT_MESSAGE} %0A${ENCODED_S3URL}\" ${TG_API_URL} &gt; \/dev\/null<\/code><\/pre>\n<p>\u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 Bash.<\/p>\n<pre><code>#!\/bin\/bash<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>encodeurl<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432 URL \u0444\u043e\u0440\u043c\u0430\u0442. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0438\u0437 s3 \u043d\u0435 \u0441\u043b\u043e\u043c\u0430\u043b\u0438\u0441\u044c.<\/p>\n<pre><code>encodeurl() {     python3 -c \"import urllib.parse; import sys; url = sys.stdin.read(); print(urllib.parse.quote(url))\"   }<\/code><\/pre>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f (timeout) \u0434\u043b\u044f <code>curl<\/code> \u0432 10 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<pre><code>TIME=\"10\"<\/code><\/pre>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c URL, \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u043e\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 API Telegram. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <a href=\"https:\/\/core.telegram.org\/bots\/api#sendmessage\" rel=\"noopener noreferrer nofollow\">sendMessage<\/a>.<\/p>\n<pre><code>TG_API_URL=\"https:\/\/api.telegram.org\/bot${TELEGRAM_BOT_TOKEN}\/sendMessage\"<\/code><\/pre>\n<p>C\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0438\u0437 s3 (\u043e\u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u043c \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0447\u0435\u0440\u0435\u0437 pipe).<\/p>\n<pre><code>read S3URL  <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>encodeurl<\/code> \u0434\u043b\u044f \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 Telegram.<\/p>\n<pre><code>ENCODED_S3URL=$(echo ${S3URL} | encodeurl)<\/code><\/pre>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0448\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0433\u0440\u0443\u043f\u043f\u0443.<\/p>\n<pre><code>curl -s --max-time ${TIME} -d \"chat_id=${TELEGRAM_CHAT_ID}&amp;disable_web_page_preview=1&amp;text=${VERSION_NAME} %0A${MERGE_REQUEST_COMMIT_MESSAGE} %0A${ENCODED_S3URL}\" ${TG_API_URL} &gt; \/dev\/null<\/code><\/pre>\n<p>\u0413\u0434\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c chat id, \u043a\u0443\u0434\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.<\/p>\n<pre><code>chat_id=${TELEGRAM_CHAT_ID}<\/code><\/pre>\n<p>\u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u0440\u0435\u0432\u044c\u044e \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0434\u043b\u044f \u0441\u0441\u044b\u043b\u043e\u043a.<\/p>\n<pre><code>disable_web_page_preview=1<\/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<tr>\n<td>\n<p align=\"left\">S3URL<\/p>\n<\/td>\n<td>\n<p align=\"left\">URL \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0439 APK, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0434\u0430\u0435\u0442 s3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">ENCODED_S3URL<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f, \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 URL \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f APK<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">TIME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u0440\u0435\u043c\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h3>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 Gitlab<\/h3>\n<p>GitLab \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438 \u0433\u0438\u0431\u043a\u0438\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 UI, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0439\u0442\u0438 \u0432 \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 <a href=\"https:\/\/gitlab.com\/\" rel=\"noopener noreferrer nofollow\">Gitlab&#8217;\u0435<\/a>, \u0434\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c: <strong>Settings -&gt; CI\/CD -&gt; Variables<\/strong>.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/637\/431\/c38\/637431c3856e0f1ce6cdb9d5961d12eb.png\" width=\"1741\" height=\"757\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/637\/431\/c38\/637431c3856e0f1ce6cdb9d5961d12eb.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/637\/431\/c38\/637431c3856e0f1ce6cdb9d5961d12eb.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 <code>Add variable<\/code>. \u0418 \u0432\u0438\u0434\u0438\u043c \u043e\u043a\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043d\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.<\/p>\n<p>\u0422\u0443\u0442 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 \u043a\u043b\u044e\u0447 (key) &#8212; \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0438\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 (value), \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 (description). \u0412\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c (visibility) \u043b\u0443\u0447\u0448\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a <code>Masked<\/code> (\u0441\u043a\u0440\u044b\u0442\u043e \u0432 \u043b\u043e\u0433\u0430\u0445 CI\/CD) \u0438\u043b\u0438 <code>Masked and hidden<\/code> (\u0441\u043a\u0440\u044b\u0442\u043e \u0432 \u043b\u043e\u0433\u0430\u0445 CI\/CD \u0438 \u0432 Gitlab UI).<\/p>\n<blockquote>\n<p>\u0412\u0410\u0416\u041d\u041e<br \/>\u0427\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u044b (\u0442\u043e\u043a\u0435\u043d\u044b, \u043a\u043b\u044e\u0447\u0438 \u0438 \u0442.\u0434.) \u043b\u0443\u0447\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 Gitlab variables. \u041a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/yandex.cloud\/en\/docs\/managed-gitlab\/tutorials\/gitlab-lockbox-integration\" rel=\"noopener noreferrer nofollow\">Yandex Lockbox<\/a>, <a href=\"https:\/\/cloud.google.com\/security\/products\/secret-manager\" rel=\"noopener noreferrer nofollow\">Google Cloud Secret Manager<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/github.com\/hashicorp\/vault\" rel=\"noopener noreferrer nofollow\">HashiCorp Vault<\/a>, \u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<\/blockquote>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/109\/bb0\/b37\/109bb0b374715a431c455958e7ce1f7c.png\" width=\"365\" height=\"951\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/109\/bb0\/b37\/109bb0b374715a431c455958e7ce1f7c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/109\/bb0\/b37\/109bb0b374715a431c455958e7ce1f7c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435, \u0432 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u0443\u044e \u043a\u0440\u0430\u0441\u043e\u0442\u0443:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b94\/4ba\/e11\/b944bae11bb38e2a76c6b07c9b752d36.png\" width=\"490\" height=\"156\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/b94\/4ba\/e11\/b944bae11bb38e2a76c6b07c9b752d36.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b94\/4ba\/e11\/b944bae11bb38e2a76c6b07c9b752d36.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h2>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h2>\n<p>\u0425\u043e\u0447\u0443 \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0438\u0441\u0447\u0435\u0440\u043f\u044b\u0432\u0430\u044e\u0449\u0438\u0439:<\/p>\n<ol>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/jobs\/\" rel=\"noopener noreferrer nofollow\">\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e Gitlab jobs<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/pipelines\/\" rel=\"noopener noreferrer nofollow\">\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e Gitlab pipelines<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/variables\/\" rel=\"noopener noreferrer nofollow\">\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e Gitlab variables<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/examples\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u0438\u043c\u0435\u0440\u044b CI\/CD \u043e\u0442 GitLab<\/a><\/p>\n<\/li>\n<\/ol>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c \u043a\u043e\u043c\u0443-\u043d\u0438\u0431\u0443\u0434\u044c \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u0435\u0441\u0442\u044c \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043b\u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c, \u043c\u0438\u043b\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0448\u0443 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438! \u0421 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435\u043c \u0431\u0443\u0434\u0443 \u0447\u0438\u0442\u0430\u0442\u044c.<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c 2 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043b\u044f Android-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f: Marathon Labs \u0438 Firebase Test Lab.<\/p>\n<p>\u041f\u0440\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 release-\u0441\u0431\u043e\u0440\u043e\u043a \u0432 Play Market \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432 3 \u0447\u0430\u0441\u0442\u0438, \u0433\u0434\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c pipeline. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u044d\u0433\u043e\u0432 \u0432 Gitlab \u0431\u0443\u0434\u0435\u0442 \u0432 \u044d\u0442\u043e\u0439 \u0436\u0435 \u0441\u0442\u0430\u0442\u044c\u0435.<\/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\/918364\/\"> https:\/\/habr.com\/ru\/articles\/918364\/<\/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\u0435\u0440\u0438\u044f \u0441\u0442\u0430\u0442\u0435\u0439?<\/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. \u0421\u0440\u0430\u0437\u0443 \u043e\u0433\u043e\u0432\u043e\u0440\u044e\u0441\u044c, \u043a\u0430\u0441\u0430\u0435\u043c\u043e CI\/CD, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0431\u0443\u0434\u0443 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c &#8212; \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u0435\u0442 \u043d\u0430 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0442.\u0434. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c &#8212; \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439, \u0434\u0430, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u043c\u0430\u043b\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 Habr, \u0434\u0430 \u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u0445 \u0442\u043e\u0436\u0435. \u0418 \u0431\u0443\u0434\u0435\u0442\u0435 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043f\u0440\u0430\u0432\u044b. \u041d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 2 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438: \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u043b\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0451 \u0442\u0430\u043a, \u043a\u0430\u043a \u043d\u0443\u0436\u043d\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u043d\u0435. \u0410 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043b\u0438\u0441\u044c, \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u043a\u0438\u0434\u0430\u043d\u044b \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u0435\u0431\u044f. \u041d\u043e \u0432\u0435\u0440\u044e, \u0447\u0442\u043e \u0447\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0445 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u0442\u0435\u043c \u043f\u0440\u043e\u0449\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u0434\u0440\u0443\u0433\u0438\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u043c\u0435.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e &#8212; \u043c\u043e\u044f \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f &#171;\u0435\u0449\u0435 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e CI\/CD \u043d\u0430 Android&#187; &#8212; \u043f\u043e\u043c\u043e\u0447\u044c \u0441\u0435\u0431\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c, \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 CI\/CD. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u043d\u043e\u0439 &#8212; \u0432\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0443 \u0432\u0441\u0435\u0445 \u0440\u0430\u0437\u043d\u044b\u0435.<\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0435\u0440\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 3 \u0441\u0442\u0430\u0442\u0435\u0439:<\/p>\n<ol>\n<li>\n<p>\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.<\/p>\n<\/li>\n<li>\n<p>\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.<\/p>\n<\/li>\n<li>\n<p>\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 Market.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u043b\u0430 \u0438\u0434\u0435\u044f \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0438\u0448\u0451\u043b \u043a \u043c\u043d\u0435\u043d\u0438\u044e, \u0447\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0441\u0442\u0430\u0442\u044c\u044f \u0440\u0430\u0437\u0434\u0443\u0435\u0442\u0441\u044f \u0434\u043e \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0445 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0443\u0441\u0442\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 \u0441 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438 \u043d\u0430\u043b\u0430\u0434\u0438\u0442\u044c CI\/CD.<\/p>\n<h2>\u0422\u0435\u043f\u0435\u0440\u044c \u043a \u0441\u0443\u0442\u0438<\/h2>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 CI\/CD \u0437\u0432\u0443\u0447\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: <a href=\"https:\/\/www.redhat.com\/en\/topics\/devops\/what-is-ci-cd\" rel=\"noopener noreferrer nofollow\">&#8230; \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0443\u044e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0438 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0443\u044e \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443\/\u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0446\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u041f\u041e.<\/a> \u0421 \u043c\u043e\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u044f \u044d\u0442\u043e \u0432\u0438\u0436\u0443 \u043a\u0430\u043a \u043d\u0430\u0431\u043e\u0440 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u044d\u043a\u043e\u043d\u043e\u043c\u044f\u0442 \u0432\u0440\u0435\u043c\u044f, \u0447\u0442\u043e \u043d\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u0442\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0440\u0430\u043a\u0442\u043e\u0432\u043a\u0438.<\/p>\n<h3>\u041a\u043e\u043c\u0443 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442?<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u043d\u0430\u0434 \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0440\u043e\u0447\u043d\u044b\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0433\u0434\u0435 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u044b \u043a \u043d\u0435\u043c\u0443 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0432\u0435\u0440\u043d\u0435\u0442\u0435\u0441\u044c, \u0442\u043e CI\/CD, \u0441\u043a\u043e\u0440\u0435\u0435, \u043e\u0442\u043d\u0438\u043c\u0435\u0442 \u0443 \u0432\u0430\u0441 \u0432\u0440\u0435\u043c\u044f. \u0412 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f, \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u043d\u0430\u0434 \u0434\u043e\u043b\u0433\u043e\u0438\u0433\u0440\u0430\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0442\u043e CI\/CD \u0434\u0430\u0441\u0442 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0434\u0435\u043f\u043b\u043e\u0435 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430.<\/p>\n<h3>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/h3>\n<p>\u0414\u0435\u043b\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 CI\/CD \u043d\u0430 Gitlab, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438. \u041d\u0438\u0436\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043e \u0441\u0445\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e pipeline.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433:<\/p>\n<h4>1. \u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u043a\u043e\u0434\u0430<\/h4>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439, \u0447\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f &#171;\u0438\u0437 \u043f\u043e\u0434 \u043a\u043e\u0440\u043e\u0431\u043a\u0438&#187;, <a href=\"https:\/\/developer.android.com\/studio\/write\/lint\" rel=\"noopener noreferrer nofollow\">Android Lint<\/a>. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435 \u043c\u0430\u043b\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u0434\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/github.com\/detekt\/detekt\" rel=\"noopener noreferrer nofollow\">detekt<\/a>, <a href=\"https:\/\/github.com\/pinterest\/ktlint\" rel=\"noopener noreferrer nofollow\">ktlint<\/a>, <a href=\"https:\/\/www.sonarsource.com\/products\/sonarqube\/\" rel=\"noopener noreferrer nofollow\">SonarQube<\/a> \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0435. \u0412 pipeline \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 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435. \u041e\u0442\u0447\u0451\u0442 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432 \u0441\u0430\u043c\u044b\u0445 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 Gitlab.<\/p>\n<h4>2. \u0417\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432<\/h4>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 \u0432\u0430\u0448\u0435\u043c Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u043a\u0430\u043a Unit-\u0442\u0435\u0441\u0442\u044b, \u0442\u0430\u043a \u0438 Android-\u0442\u0435\u0441\u0442\u044b. Unit-\u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043c\u0435\u0442\u043e\u0434\u044b \u0431\u0438\u0437\u043d\u0435\u0441-\u0441\u043b\u043e\u044f, \u0431\u0435\u0437 Android-\u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0439.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f Unit-\u0442\u0435\u0441\u0442\u043e\u0432, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/willowtreeapps\/assertk\" rel=\"noopener noreferrer nofollow\">AssertK<\/a>, <a href=\"https:\/\/github.com\/mockito\/mockito-kotlin\" rel=\"noopener noreferrer nofollow\">Mockito Kotlin<\/a> \u0438 <a href=\"https:\/\/developer.android.com\/kotlin\/coroutines\/test\" rel=\"noopener noreferrer nofollow\">Kotlin coroutines<\/a>. Android-\u0442\u0435\u0441\u0442\u044b \u0443\u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a UI, \u0433\u0434\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/KasperskyLab\/Kaspresso\" rel=\"noopener noreferrer nofollow\">Kaspresso<\/a>, \u0442\u0430\u043a \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/robolectric\/robolectric\" rel=\"noopener noreferrer nofollow\">Robolectric<\/a> \u0438\u043b\u0438 <code>Kaspresso<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0441\u044f. \u041c\u044b \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>Kaspresso<\/code>, \u0442.\u043a. \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u0435\u043d \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f UI, \u043d\u043e \u0438 \u0434\u043b\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p>\u0422\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0442 \u0432\u0441\u0442\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u0433\u0434\u0435 \u0438 \u043a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c Android-\u0442\u0435\u0441\u0442\u044b? \u0423\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043a\u0430\u043a \u043d\u0430 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u0445, \u0442\u0430\u043a \u0438 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445. \u042f \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b 2 \u0440\u0435\u0448\u0435\u043d\u0438\u044f: <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>.  \u041e\u0431\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0442\u043e <code>Marathon Labs<\/code> \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0430\u0441, \u0433\u0434\u0435 \u0438 \u043a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u0442\u0435\u0441\u0442\u044b. \u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, <code>Firebase Test Lab<\/code> \u043d\u0435 \u0434\u0430\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438, \u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Android-\u0442\u0435\u0441\u0442\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u044d\u0442\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0412 pipeline Unit-\u0442\u0435\u0441\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435. \u0410 \u0432\u043e\u0442 Android-\u0442\u0435\u0441\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 merge request&#8217;\u0430\u0445 \u0432 master.<\/p>\n<h4>3. \u0421\u0431\u043e\u0440\u043a\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 \u0433\u0440\u0443\u043f\u043f\u0443 Telegram \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e commit&#8217;\u0430. \u0412 pipeline \u0441\u0431\u043e\u0440\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 merge request&#8217;\u0435 \u0432 develop.<\/p>\n<h4>4. \u0412\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c release-\u0441\u0431\u043e\u0440\u043a\u0443 \u0432 Play Market<\/h4>\n<p>\u0422\u0443\u0442 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0443 \u043d\u0430\u0441 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0430\u0433\u043e\u0432, \u043d\u043e\u0432\u044b\u0435 \u0444\u0438\u0447\u0438 \u0438 \u0442.\u0434. \u0412\u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043e\u0439\u0434\u0443\u0442 \u0432 release-\u0441\u0431\u043e\u0440\u043a\u0443 \u0438 \u043e\u043d\u0430 \u0443\u043b\u0435\u0442\u0438\u0442 \u0432 Play Market \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\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> \u0438 <a href=\"https:\/\/github.com\/fastlane\/fastlane\" rel=\"noopener noreferrer nofollow\">Fastlane<\/a> \u0434\u043b\u044f \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.<\/p>\n<p>\u0412 pipeline \u0441\u0431\u043e\u0440\u043a\u0430 \u0434\u043b\u044f Play Market \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 merge request&#8217;\u0435 \u0432 master.<\/p>\n<h4>5. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Git-Tag \u0432 Gitlab<\/h4>\n<p>\u0414\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439\/release&#8217;\u043e\u0432 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/git-scm.com\/docs\/git-tag\" rel=\"noopener noreferrer nofollow\">Git-Tag<\/a>, \u0442\u0443\u0442 \u0432\u0441\u0435 \u043f\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0435. \u0412 pipeline \u0442\u0435\u0433\u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 Gitlab \u043f\u0440\u0438 merge request&#8217;\u0430\u0445 \u0432 master.<\/p>\n<h2>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a CI\/CD<\/h2>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h3>\n<p>\u0415\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 CI\/CD, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <a href=\"https:\/\/docs.github.com\/en\/actions\" rel=\"noopener noreferrer nofollow\">GitHub Actions<\/a>, <a href=\"https:\/\/www.jenkins.io\/\" rel=\"noopener noreferrer nofollow\">Jenkins<\/a>, <a href=\"https:\/\/docs.gitlab.com\/ci\/\" rel=\"noopener noreferrer nofollow\">GitLab<\/a>, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>.gitlab-ci.yml<\/code> \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0442\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0448 pipeline. \u0414\u0430, \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u0442\u0430\u043f \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438 \u0442.\u0434., \u043d\u043e \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0432\u0441\u0435 \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435, <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/includes\/\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0443\u0442<\/a>. \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u0442\u044b\u043a\u0430\u0435\u043c \u041f\u041a\u041c \u043f\u043e \u043a\u043e\u0440\u043d\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 -&gt; New -&gt; File -&gt; \u0412\u0432\u043e\u0434\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>.gitlab-ci.yml<\/code>.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0438\u0436\u0435. \u041a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430\u0448 <a href=\"https:\/\/docs.gitlab.com\/runner\/\" rel=\"noopener noreferrer nofollow\">Gitlab Runner<\/a>.<\/p>\n<figure class=\"\"><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u043a\u043e\u0434\u0443.<\/p>\n<pre><code class=\"yaml\">image: jangrewe\/gitlab-ci-android:33      # \u0417\u0430\u0434\u0430\u0435\u043c \u044d\u0442\u0430\u043f\u044b   stages:     - lint     - tests     - build_flavors     - release     - create_git_tag      # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043e\u0431\u0449\u0438\u0439 before_script \u0434\u043b\u044f \u0432\u0441\u0435\u0445 jobs before_script:     - chmod +x .\/gradlew  <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c Android SDK \u0438 \u043f\u0440\u043e\u0447\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435. \u0427\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u044c, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 <a href=\"https:\/\/github.com\/jangrewe\/gitlab-ci-android\" rel=\"noopener noreferrer nofollow\">Docker image jangrewe\/gitlab-ci-android<\/a>.<\/p>\n<pre><code class=\"yaml\">image: jangrewe\/gitlab-ci-android:33  <\/code><\/pre>\n<p>\u0412 <strong>stages<\/strong> \u0437\u0430\u0434\u0430\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u0442\u0430\u043f\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e.<\/p>\n<pre><code class=\"yaml\">stages:     - lint     - tests     - build_flavors     - release     - create_git_tag <\/code><\/pre>\n<p>\u0412 <code>before_script<\/code>, \u0441\u0442\u0440\u043e\u0447\u043a\u0430 <code>chmod +x .\/gradlew<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u0444\u0430\u0439\u043b <code>gradlew<\/code> \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u043c (\u0434\u0430\u0435\u0442 \u0435\u043c\u0443 \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435). \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/#before_script\" rel=\"noopener noreferrer nofollow\">before_script \u0447\u0438\u0442\u0430\u0435\u043c \u0442\u0443\u0442<\/a>.<\/p>\n<pre><code class=\"yaml\">before_script:     - chmod +x .\/gradlew  <\/code><\/pre>\n<h3>\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430<\/h3>\n<pre><code class=\"yaml\">runAndroidLint:     stage: lint     script:       - .\/gradlew lint     artifacts:       paths:         - \"**\/lint-results.html\"       expire_in: 10 days       when:         always     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f <code>\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<\/code> \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435.<\/p>\n<p>\u0422\u0443\u0442 \u043c\u044b \u0434\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0439 Job&#8217;\u0435.<\/p>\n<pre><code class=\"yaml\">runAndroidLint:  <\/code><\/pre>\n<p>\u0412 <strong>stage<\/strong> \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u044d\u0442\u0430\u043f\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u044d\u0442\u0430 job&#8217;\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>lint<\/code>.<\/p>\n<pre><code class=\"yaml\">stage: lint<\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <code>script<\/code> \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0438\u0448\u0435\u043c \u0441\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c. \u0417\u0434\u0435\u0441\u044c \u0441\u0442\u0440\u043e\u0447\u043a\u0430 <code>.\/gradlew lint<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 Android Lint.<\/p>\n<pre><code class=\"yaml\">script:       - .\/gradlew lint <\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <code>artifacts<\/code> \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432 <code>paths<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c, \u0432 <code>expire_in<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0438 \u0432 <code>when<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u0438 \u043a\u0430\u043a\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/#artifacts\" rel=\"noopener noreferrer nofollow\">artifacts \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\">artifacts:       paths:         - \"**\/lint-results.html\"       expire_in: 10 days       when:         always  <\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <code>rules<\/code> \u043c\u044b \u0437\u0430\u0434\u0430\u0435\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0448\u0430 job&#8217;\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>'$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c merge request&#8217;\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/docs.gitlab.com\/ci\/yaml\/#rules\" rel=\"noopener noreferrer nofollow\">rules \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0443\u0442<\/a>.<\/p>\n<pre><code class=\"yaml\">rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/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_PIPELINE_SOURCE<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0425\u0440\u0430\u043d\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0431\u044b\u043b \u0437\u0430\u043f\u0443\u0449\u0435\u043d pipeline. <a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/jobs\/job_rules.html#ci_pipeline_source-predefined-variable\" rel=\"noopener noreferrer nofollow\">\u0422\u0443\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432<\/a><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h3>Unit-tests<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0442\u0435\u0441\u0442\u0430\u043c, \u043f\u043e\u043a\u0430 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e Unit-\u0442\u0435\u0441\u0442\u044b, \u043a Android-\u0442\u0435\u0441\u0442\u0430\u043c \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0433\u0434\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0441\u0432\u044f\u0437\u0430\u0442\u044c <code>Marathon Labs<\/code> \u0438 <code>Firebase Test Lab<\/code> \u0441 \u043d\u0430\u0448\u0438\u043c CI\/CD.<\/p>\n<pre><code class=\"yaml\">runUnitTests:     stage: tests     script:       - .\/gradlew app:test       - .\/gradlew core:some-module:impl:test    ...    artifacts:       paths:         - \"**\/build\/reports\/tests\/testDebugUnitTest\/classes\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/packages\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/index.html\"       expire_in: 10 days       when:         always     rules:       - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'<\/code><\/pre>\n<p>\u0412 <code>stage<\/code> \u0432\u0441\u0435 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u044e \u0432\u044b\u0448\u0435, \u0437\u0430 \u0442\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u044d\u0442\u0430\u043f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f;<\/p>\n<pre><code class=\"yaml\">stage: tests<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0441\u0445\u0435\u043c\u043e\u0439 \u043d\u0438\u0436\u0435.<\/p>\n<pre><code class=\"yaml\">.\/gradlew {\u041c\u043e\u0434\u0443\u043b\u044c \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043f\u0430\u043a\u0435\u0442\u043e\u0432}:test<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c app \u043c\u043e\u0434\u0443\u043b\u0435 \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e <code>app:test<\/code>, \u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 \u0443\u0436\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u0430\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u043e\u0432. \u041a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440: <code>core:some-module:impl:test<\/code>.<\/p>\n<pre><code class=\"yaml\">script:       - .\/gradlew app:test       - .\/gradlew core:some-module:impl:test  <\/code><\/pre>\n<p>\u0412 <code>artifacts<\/code> \u0432\u0441\u0435 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0432\u044b\u0448\u0435.<\/p>\n<pre><code class=\"yaml\">artifacts:       paths:         - \"**\/build\/reports\/tests\/testDebugUnitTest\/classes\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/packages\"         - \"**\/build\/reports\/tests\/testDebugUnitTest\/index.html\"       expire_in: 10 days       when:         always<\/code><\/pre>\n<h3>Build flavors<\/h3>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0443 \u043d\u0430\u0441 \u0441\u0431\u043e\u0440\u043a\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Telegram. \u0414\u043e\u0441\u0442\u0443\u043f \u043a APK \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.<\/p>\n<pre><code class=\"yaml\">assembleSomeBuildFlavor:     stage: build_flavors     script:       - .\/gradlew assembleSomeBuildFlavorDebug           - apt update       - apt install python3-pip --yes          - pip3 install awscli --upgrade          - 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-463391","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/463391","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=463391"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/463391\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=463391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=463391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=463391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}