{"id":396181,"date":"2024-06-29T12:41:16","date_gmt":"2024-06-29T12:41:16","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=396181"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=396181","title":{"rendered":"<span>\u041a\u0430\u043a \u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c iOS: \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Gitlab CI + Fastlane + Firebase + ItunesConnect<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u0434\u0435\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f CI\/CD \u0434\u043b\u044f iOS, \u0434\u0430 \u0438 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c, \u2014 \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0443\u0442\u0438\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c, \u043c\u043e\u0436\u0435\u043c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442. \u041d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0440\u0430\u0441\u0442\u0451\u0442, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0435\u0435, \u0447\u0435\u043c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043b\u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c, \u0447\u0442\u043e \u0436\u0435 \u0442\u0430\u043c \u0441 Code-signing \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c. <\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u0441\u0430\u043c\u043e\u0435 \u0440\u0443\u0442\u0438\u043d\u043d\u043e\u0435 \u0438 \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u0437\u0430\u043d\u044f\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0435\u0440\u0451\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f CI, \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432. \u041d\u0435\u0442 \u0437\u0435\u043b\u0451\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432? \u0412 master \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0451\u0448\u044c. \u0410 \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043a\u0442\u043e-\u0442\u043e \u0432\u043e\u043b\u044c\u0451\u0442 \u0432 master \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434, \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u041d\u0443\u0436\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u043f\u0443\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Gitlab CI + Fastlane + Firebase + Testflight. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438 10 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u044b \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c, \u0438 \u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f \u043a\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u044d\u0442\u043e\u0442 \u043e\u043f\u044b\u0442? \u0414\u043b\u044f \u0432\u0441\u0435\u0445, \u043a\u043e\u043c\u0443 \u043d\u0443\u0436\u0435\u043d CI\/CD \u0438 \u043a\u0442\u043e \u0441\u0438\u0434\u0438\u0442 \u043d\u0430 Gitlab. \u0414\u043b\u044f Github \u0431\u0443\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0432\u044f\u0437\u043a\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441 Travis, \u2014 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u044b. \u0412 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0432\u0441\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 Gitlab CI, Fastlane \u0432\u043c\u0435\u0441\u0442\u043e \u0433\u043e\u043b\u043e\u0433\u043e xcodebuild \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0442\u044b \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, Firebase \u0438 Testflight.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 Gitlab \u0438 \u043c\u044b \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u0432 \u043b\u0438\u043c\u0438\u0442 Firebase, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 CI\/CD.<\/p>\n<h3>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/h3>\n<p><strong>Gitlab CI<\/strong> \u2014 \u044d\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438. \u041e\u043d\u0430 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u0447\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0446\u0435\u043b\u0435\u0439. \u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u043a \u043d\u0435\u043c\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 <em>.gitlab-ci.yml. <\/em>\u041e\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0431\u043e\u0442\u0430 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u043d\u0430 \u043d\u043e\u0443\u0442\u0431\u0443\u043a\u0430\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0435\u0441\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0448\u0438\u043d\u044b \u043d\u0430 MacOS \u2014 \u0438\u0445 \u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0432 Gitlab CI.<\/p>\n<p><strong>Fastlane <\/strong>\u2014 \u0432\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434 \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435. \u0414\u043b\u044f \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c <a href=\"https:\/\/docs.fastlane.tools\/plugins\/available-plugins\/\">\u043c\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: \u043e\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 AppIcon \u0434\u043e \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore. \u041f\u043b\u0430\u0433\u0438\u043d\u044b, \u043a\u0430\u043a \u0438 \u0441\u0430\u043c Fastlane, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 ruby, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u044d\u0442\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043d\u0430 ruby.<\/p>\n<p>Gitlab CI \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0432 \u0432\u0438\u0434\u0435 shell-\u043a\u043e\u043c\u0430\u043d\u0434 \u043d\u0430 \u0440\u0430\u043d\u043d\u0435\u0440, \u0432 \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043c\u0430\u043d\u0434 \u0432\u0445\u043e\u0434\u0438\u0442 Fastlane. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043e\u043d\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0432\u043e\u0438 \u0437\u0430\u0434\u0430\u0447\u0438.<\/p>\n<p><strong>Firebase<\/strong> \u2014 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u044c\u044e\u0442\u0438\u043d\u0433\u0430 \u0441\u0431\u043e\u0440\u043e\u043a, \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u0431\u043e\u0440\u043e\u043a \u0434\u043e \u0432\u0430\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Firebase App Distribution \u2014 \u043e\u043d \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0438 \u0431\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e.<\/p>\n<p><strong>Code coverage<\/strong> \u2014 \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u0434\u0430 \u0442\u0435\u0441\u0442\u0430\u043c\u0438. \u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0444\u043e\u0440\u043c\u0443\u043b\u0435:<\/p>\n<p><em>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \/ \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430) * 100%<\/em><\/p>\n<h3>[Gitlab CI] Gitlab-runner<\/h3>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430 \u043f\u0443\u0442\u0438 \u0441\u0430\u043c\u0443\u0440\u0430\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u2014 \u044d\u0442\u043e \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c \u043d\u0430\u0448 mac \u0441 CI. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u043c\u0430\u043a\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043a\u043e\u043c\u0430\u043d\u0434:<\/p>\n<ol>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/runner\/install\/osx.html\">\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c<\/a> \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 gitlab-runner      \u043d\u0430 mac (\u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Homebrew). <a href=\"https:\/\/brew.sh\/index_ru\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 Homebrew<\/a>. <\/p>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b:<\/p>\n<p><em>brew install gitlab-runner<\/em><\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0434\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 mac \u043a\u0430\u043a \u0440\u0430\u043d\u043d\u0435\u0440 \u0434\u043b\u044f CI:<\/p>\n<p><em>gitlab-runner register<\/em><\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0432\u0435\u0441\u0442\u0438 URL \u0434\u043e \u0433\u0438\u0442\u043b\u0430\u0431\u0430, \u0433\u0434\u0435 \u0445\u043e\u0441\u0442\u0438\u043c\u0441\u044f.<\/p>\n<p>\u0415\u0449\u0451 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f CI. \u0415\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u0434\u0443\u0447\u0438 Owner\u2019\u043e\u043c \u0438\u043b\u0438 Maintainer\u2019\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 Settings \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b CI\/CD. \u0420\u0430\u0437\u0434\u0435\u043b Runners.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/408\/357\/db0\/408357db04280e0758798a35b6ac0265.png\" alt=\"\u0420\u0430\u0437\u0434\u0435\u043b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 CI\/CD\" title=\"\u0420\u0430\u0437\u0434\u0435\u043b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 CI\/CD\" width=\"1600\" height=\"219\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/408\/357\/db0\/408357db04280e0758798a35b6ac0265.png\"\/><figcaption>\u0420\u0430\u0437\u0434\u0435\u043b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 CI\/CD<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/20b\/0ff\/9a8\/20b0ff9a8429638d04fc19b7482bd517.png\" width=\"1398\" height=\"560\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/20b\/0ff\/9a8\/20b0ff9a8429638d04fc19b7482bd517.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u0442\u0443\u0434\u0430.<\/p>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0440\u0430\u043d\u043d\u0435\u0440\u0430 \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442, \u043e\u043d\u043e \u0434\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0438.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u0435\u0433\u0438 \u0440\u0430\u043d\u043d\u0435\u0440\u0430. \u0411\u0435\u0437 \u0442\u0435\u0433\u043e\u0432 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u0443\u0436\u0435\u043d \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u0438\u043d. \u041f\u043e \u0442\u0435\u0433\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0430\u043d\u043d\u0435\u0440\u044b: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u0438\u043d \u0431\u0443\u0434\u0435\u0442 \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u0441\u0435\u0442\u0438 \u0438 \u0441\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0438, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043d\u0435\u0442. \u0422\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0435\u0433\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0432\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u0433\u0438 ios_tests,ios_firebase, \u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u2014 \u0442\u043e\u043b\u044c\u043a\u043e ios_tests. \u0418 \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439 \u043f\u043e \u0442\u0438\u043f\u0443. <\/p>\n<p>\u0422\u0438\u043f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 shell.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d1a\/e45\/bad\/d1ae45bad3d492c117fc14dbf6b76aa3.png\" alt=\"gitlab-runner register\" title=\"gitlab-runner register\" width=\"1448\" height=\"898\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d1a\/e45\/bad\/d1ae45bad3d492c117fc14dbf6b76aa3.png\"\/><figcaption>gitlab-runner register<\/figcaption><\/figure>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430\u0448 \u0440\u0430\u043d\u043d\u0435\u0440. \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0436\u0435 \u0441\u043f\u0438\u0441\u043a\u0435 Runners \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d26\/b9a\/1e3\/d26b9a1e31bef741bba73a25d53bca4f.png\" width=\"1550\" height=\"356\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d26\/b9a\/1e3\/d26b9a1e31bef741bba73a25d53bca4f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u043e\u0441\u043a\u043b\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0437\u043d\u0430\u043a \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0440\u0430\u043d\u043d\u0435\u0440 \u0435\u0449\u0451 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0438 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435. \u0418\u0434\u0451\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0448\u0430\u0433\u0443.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0440\u0430\u043d\u043d\u0435\u0440. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435:<\/p>\n<pre><code>gitlab-runner install gitlab-runner start<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u0440\u0430\u043d\u043d\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0433\u043e\u0440\u0435\u0442\u044c\u0441\u044f \u0437\u0435\u043b\u0451\u043d\u044b\u043c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6f0\/0c3\/19d\/6f00c319d53ca464cd12edc84e2dbc14.png\" width=\"1532\" height=\"376\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6f0\/0c3\/19d\/6f00c319d53ca464cd12edc84e2dbc14.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0423 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043b\u043e\u0433\u0430\u043c\u0438. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043b\u043e\u0433\u043e\u0432, \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u043f\u0443\u0442\u0438 \u201c<strong><em>~\/.gitlab-runner\/<\/em><\/strong>\u201d. \u0422\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0444\u0430\u0439\u043b <strong><em>config.toml<\/em><\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u043d\u043d\u0435\u0440\u0430\u0445, \u0432 \u043d\u0451\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <strong><em>output_limit<\/em><\/strong>, \u2014 \u044d\u0442\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0432 \u0431\u0430\u0439\u0442\u0430\u0445 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u043b\u043e\u0433\u043e\u0432 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445. \u0414\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0435\u0441\u0442\u044c <a href=\"https:\/\/docs.gitlab.com\/runner\/configuration\/advanced-configuration.html#the-runners-section\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>, \u0434\u043b\u044f output_limit \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e: \u201cMaximum build log size in kilobytes. Default is 4096 (4MB)\u201d. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u2014 4 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u0430. <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 IOS-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0442\u043e \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e. \u0417\u043d\u0430\u0447\u0438\u0442, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0451\u043c \u043b\u043e\u0433\u043e\u0432, \u043d\u0430\u0434\u043e \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435.<\/p>\n<p>\u0412\u0441\u0451, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u043e\u0440\u043e\u0433, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0434\u0436\u043e\u0431\u0430\u0445. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c:<\/p>\n<pre><code>[[runners]]   output_limit = 500000   name = \"My first runner\"   url = \"https:\/\/gitlab-01\"   token = \"7qybRaWukobUuXYoiSMc\"   executor = \"shell\"   [runners.custom_build_dir]   [runners.cache]     [runners.cache.s3]     [runners.cache.gcs]     [runners.cache.azure]<\/code><\/pre>\n<p>\u041d\u0443\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u044b\u043c \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b \u043b\u043e\u0433\u043e\u0432 \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c \u0432\u0435\u0441\u0438\u0442 37 \u041c\u0431, \u043e\u043d \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430. \u0412\u0441\u0435 \u043b\u043e\u0433\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0433\u0438\u0442\u043b\u0430\u0431\u0435 \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f. \u0413\u043e\u0442\u043e\u0432\u043e, Gitlab CI \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u043c!<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Fastlane<\/h3>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Fastlane \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 Homebrew (<a href=\"https:\/\/docs.fastlane.tools\/getting-started\/ios\/setup\/\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>). \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 ruby \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u043e\u0431\u044b\u0447\u043d\u043e \u043e\u043d \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 macos \u043f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443. \u041d\u0430\u0431\u0438\u0440\u0430\u0435\u043c:<\/p>\n<pre><code>brew install fastlane<\/code><\/pre>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>cd.\/path_to_project<\/strong> \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443<\/p>\n<pre><code>fastlane init<\/code><\/pre>\n<p>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u0441\u044f \u043f\u0430\u043f\u043a\u0430 Fastlane \u0441 \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438. \u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Fastlane \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Swift: \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043b\u0430\u0439\u043d\u044b \u043d\u0430 Swift, \u0430 \u043d\u0435 \u043d\u0430 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c DSL, \u2014 \u044d\u0442\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u0433 (<a href=\"https:\/\/docs.fastlane.tools\/getting-started\/ios\/fastlane-swift\/\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>). <\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u0432\u0430\u0436\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0434\u0435\u0441\u044c \u2014 \u044d\u0442\u043e Fastfile. \u041e\u043d \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 lane. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 Fastlane. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0430\u043c Fastlane \u043a\u0430\u043a \u043d\u0435\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 (\u0432 \u041e\u041e\u041f), \u0430 lane \u2014 \u043a\u0430\u043a \u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439. <\/p>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 lane \u0434\u043b\u044f \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u043e\u0432. \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 \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b. \u041c\u044b \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0432\u044b\u0431\u0440\u0430\u043b\u0438 scan \u043a\u0430\u043a \u0441\u0430\u043c\u044b\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434\u0430. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435, \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0438 \u0438\u0445 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0432 <a href=\"https:\/\/docs.fastlane.tools\/actions\/scan\/#parameters\">\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043f\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0443 scan<\/a>.\u00a0<\/p>\n<pre><code>desc \"\u041f\u0440\u043e\u0433\u043e\u043d \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0445\u0435\u043c. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane unit_test scheme:CoreTests\" lane :unit_test do |options|     scheme = options[:scheme]     scan(         scheme: scheme,         device: \"iPhone 11 Pro\",         fail_build: false,         clean: true,         derived_data_path: \".\/tests\/derived\",         max_concurrent_simulators: \"3\",         code_coverage: true,         output_directory: \".\/tests\/#{scheme}_report\/\",         result_bundle: true     ) end<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f lane, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f \u0441\u0445\u0435\u043c\u044b CoreTests, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0435\u0440\u0451\u043c \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432\u044b\u0437\u043e\u0432\u0430 lane. \u0415\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0440\u043c\u043b\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u0445\u0435\u043c\u044b \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432, \u0442\u0430\u043a \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0445\u0435\u043c\u044b \u043f\u043e\u0434 \u0442\u0435\u0441\u0442\u044b. \u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c, \u0430 \u043d\u0435 \u0441\u0430\u043c\u0438 \u0442\u0430\u0440\u0433\u0435\u0442\u044b.<\/p>\n<p>\u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043e\u0434\u0438\u043d \u0442\u0430\u0440\u0433\u0435\u0442, \u043e\u0434\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u2014 \u0438 \u043d\u0435\u0442 \u043f\u0443\u0442\u0430\u043d\u0438\u0446\u044b. \u041d\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 CI \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 30\u201340 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439, \u0430 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432 \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435, \u0432\u0430\u0436\u043d\u043e \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f. \u0422\u0430\u0440\u0433\u0435\u0442 \u2014 \u044d\u0442\u043e executable(buildable)-\u043f\u0440\u043e\u0435\u043a\u0442, \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441 Build Phase, Build Settings, General. \u0421\u0445\u0435\u043c\u044b \u2014 \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0435, \u043a\u0430\u043a \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u0440\u0433\u0435\u0442\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432 \u043f\u043e\u0434 \u0441\u043e\u0431\u043e\u0439. \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u044b Fastlane \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441\u043e \u0441\u0445\u0435\u043c\u0430\u043c\u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9ef\/9b8\/5f4\/9ef9b85f457b9b4e74e580b928ef7d04.png\" width=\"1180\" height=\"456\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9ef\/9b8\/5f4\/9ef9b85f457b9b4e74e580b928ef7d04.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 lane \u0432\u0432\u0435\u0434\u0451\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code>fastlane unit_test scheme:CoreTests<\/code><\/pre>\n<p>\u0412 \u043e\u0442\u0432\u0435\u0442 \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u043b\u043e\u0433\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0438 \u0441\u0430\u043c\u0438 \u043b\u043e\u0433\u0438 Fastlane. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u0430\u043f\u043a\u0443 <strong><em>.\/tests\/CoreTests_report\/<\/em><\/strong> \u0441 \u043e\u0442\u0447\u0451\u0442\u043e\u043c \u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong><em>.xcresult<\/em><\/strong>. \u041f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443 \u043f\u043b\u0430\u0433\u0438\u043d scan \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u0430\u043c \u0435\u0449\u0451 \u0434\u0432\u0430 \u0444\u0430\u0439\u043b\u0430 \u2014 <strong><em>report.html &amp; report.junit<\/em><\/strong>. \u041f\u0435\u0440\u0432\u044b\u0439 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u043b\u044e\u0434\u044f\u043c, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u2014 \u0434\u043b\u044f Gitlab CI \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0447\u0451\u0442\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u2014 \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0437\u0436\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043f\u0440\u043e \u0430\u0440\u0442\u0438\u0444\u0430\u043a\u0442\u044b \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430\u0445.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u0447\u0451\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0431\u044b\u043b\u0438 \u043b\u0438 \u0437\u0430\u0444\u0435\u0439\u043b\u0435\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0438 \u0432 \u043a\u0430\u043a\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 <a href=\"https:\/\/gist.github.com\/yawillianpsb\/8773ff01cb1f9390d5a03d54de27a508\">\u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430 Swift<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 report.junit \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u0432 \u043a\u0430\u043a\u0438\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u0445. <\/p>\n<h3>Code coverage<\/h3>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043c\u0435\u0440\u0436 \u0432 master. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Fastlane. \u041e\u043d \u0443\u0436\u0435 \u0432\u044b\u0434\u0430\u043b \u043d\u0430\u043c <strong><em>.xcresult<\/em><\/strong>, \u0438 \u043d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f.<\/p>\n<p><a href=\"http:\/\/docs.fastlane.tools\/actions\/xcov\/#xcov\">\u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f Fastlane xcov<\/a> \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u043e\u0442\u0447\u0451\u0442\u043e\u0432. \u041d\u0430\u043c \u043d\u0443\u0436\u0435\u043d json, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0441\u0430\u043c \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f, \u0430 \u043f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 json.<\/p>\n<pre><code>desc \"\u0420\u0430\u0441\u0447\u0435\u0442 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0441\u0445\u0435\u043c. \u0414\u043e\u043b\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043b\u0435\u0439\u043d\u0430 unit_test. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane code_coverage scheme:BaseTests\" lane :code_coverage do |options|     scheme = options[:scheme]     FileUtils.mv(\"..\/tests\/#{scheme}_report\/#{scheme}.xcresult\", \"..\/tests\/derived\/Logs\/Test\/#{scheme}.xcresult\")     begin         FileUtils.rm_rf(\"..\/tests\/#{scheme}_report\/coverage_result\")     rescue         puts \"Folder alredy deleted\"     end     xcov(         workspace: \"PSB.xcworkspace\",         scheme: scheme,         derived_data_path: \".\/tests\/derived\",         output_directory: \".\/tests\/#{scheme}_report\/coverage_result\",         html_report: false,         markdown_report: false,         json_report: true     ) end<\/code><\/pre>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u043c\u0430\u0445\u0438\u043d\u0430\u0446\u0438\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c <strong><em>.xcresult<\/em><\/strong> \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e <strong><em>xcov<\/em><\/strong> \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u043b\u0441\u044f \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043f\u0430\u043f\u043a\u0438 <strong><em>derived<\/em><\/strong>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c \u0435\u0433\u043e \u0432 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u043e\u043c code coverage. \u0418 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0430\u043f\u043a\u0430 <em>output_directory<\/em> \u0431\u044b\u043b\u0430 \u043f\u0443\u0441\u0442\u0430, \u0442. \u043a. <strong><em>xcov<\/em><\/strong> \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u0442\u0438\u0440\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442\u044b, \u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0430\u0434\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0432\u0438\u0434\u0438\u0442, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0441 \u0442\u0430\u043a\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c. <\/p>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c <strong><em>report.json<\/em><\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 coverage \u2014 \u044d\u0442\u043e \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u043d\u0442. \u042d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u043e\u0431\u0449\u0435\u043c\u0443 coverage, \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0442\u0430\u0440\u0433\u0435\u0442\u0443, \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 \u0438 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u043c\u0443 \u0441\u043a\u043e\u0443\u043f\u0443.<\/p>\n<pre><code>{    \"coverage\":0.5167708082636994,    \"targets\":[       {          \"name\":\"SomeFramework.framework\",          \"coverage\":0.8335146898803046,          \"files\":{                       }       },       {          \"name\":\"SomeFramework2.framework\",          \"coverage\":0.4323423536236234,          \"files\":{                       }       }    ] }<\/code><\/pre>\n<p>\u0421\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0432\u0435\u0440\u0430\u0436\u0430 \u0432 Gitlab CI \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435. \u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0432\u044b \u0437\u0430\u0434\u0430\u0451\u0442\u0435 Regex-\u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u0447\u043a\u0435 \u043b\u043e\u0433\u043e\u0432, \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043b\u0438 \u0447\u0438\u0441\u043b\u043e \u043f\u043e\u0434 \u043f\u0430\u0442\u0442\u0435\u0440\u043d. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0444\u043e\u0440\u043c\u0430\u0442:<\/p>\n<pre><code>\\((\\d+.\\d+|\\d+)\\%\\) covered<\/code><\/pre>\n<p>\u0421 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f \u0432\u044b\u0432\u043e\u0434 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 Swift. \u041f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u0442\u0438\u043f\u0430 \u201c(51.67%)covered\u201d<\/p>\n<p><a href=\"https:\/\/gist.github.com\/yawillianpsb\/fb51e7f1a957e903e27235e2864d2035\">\u041d\u0430\u0448 \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 Swift<\/a>. \u041e\u043d \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0432\u0435\u0441\u0442\u0438 coverage \u0432 \u043d\u0443\u0436\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0412\u0441\u0451, \u0447\u0442\u043e \u043e\u0442 \u043d\u0435\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u2014 \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u043a\u0430\u044f-\u043d\u0438\u0431\u0443\u0434\u044c \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u0447\u043a\u0430 \u0432 \u043a\u043e\u0434\u0435 \u043d\u0435 \u043f\u043e\u043f\u0430\u043b\u0430 \u043f\u043e\u0434 \u044d\u0442\u043e regexp.<\/p>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c .junit, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043e\u0442\u0447\u0451\u0442\u043e\u0432 \u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 Gitlab CI. \u0412\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438 \u043a\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0448\u043b\u0438, \u0430 \u043a\u0430\u043a\u0438\u0435 \u043d\u0435\u0442, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u043d\u0438\u043c, \u2014 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043e\u0442\u0447\u0451\u0442 junit. .xcresult, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0441\u0435\u0431\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f code coverage.<\/p>\n<p>\u0421\u0430\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Regex \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <strong>Settings -> CI\/CD -> General pipelines<\/strong>, \u0432 \u0433\u0440\u0430\u0444\u0435<strong> Test coverage parsing<\/strong>. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e Regex \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/post\/545150\/\">\u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/a> \u0422\u0430\u043c \u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0441\u0430\u0439\u0442\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0444\u043e\u0440\u043c\u0443\u043b\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/regex101.com\/\">\u0442\u0443\u0442<\/a>).<\/p>\n<h3>Firebase deploy<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Firebase CLI, \u2014 \u044d\u0442\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u0432 Firebase \u0438\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. \u0412 \u043e\u0431\u044b\u0447\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438\u0434\u0451\u0442 \u043d\u0430 \u0441\u0430\u043c \u0441\u0430\u0439\u0442 Firebase, \u0437\u0430\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442 \u0442\u0443\u0434\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043d\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u0438 \u043d\u0443\u0436\u0435\u043d Firebase.<\/p>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 Firebase App Distribution (\u0432 Firebase \u0435\u0441\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u0444\u0438\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a CI\/CD). <\/p>\n<p>\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Google Firebase: <a href=\"https:\/\/firebase.google.com\/docs\/app-distribution\/ios\/distribute-fastlane\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a><\/p>\n<p>\u0412\u043e\u0442 \u043a\u0440\u0430\u0442\u043a\u0438\u0439 \u043f\u043b\u0430\u043d:<\/p>\n<p>1. \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u043b\u0430\u0433\u0438\u043d \u043a Fastlane \u2014 Firebase.<\/p>\n<p>2. \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Firebase CLI.<\/p>\n<p>3. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u0443\u0434\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448\u0438 \u0441\u0431\u043e\u0440\u043a\u0438.<\/p>\n<p>4. \u0412\u043e\u0442 lane, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 Firebase.<\/p>\n<pre><code>def archive_project(scheme, forTestflight, filename)     if forTestflight         build_ios_app(             workspace: \"PSB.xcworkspace\",             configuration: scheme,             scheme: scheme,             silent: true,             clean: true,             output_directory: \".\/ipas\",             output_name: \"#{filename}.ipa\",             export_options: \".\/ExportOptions.plist\"         )     else         build_ios_app(             workspace: \"PSB.xcworkspace\",             configuration: scheme,             scheme: scheme,             silent: true,             clean: true,             output_directory: \".\/ipas\",             output_name: \"#{filename}.ipa\",             export_method: \"development\",             include_bitcode: false         )     end end<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0443\u043c\u0435\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore, \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432, \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0432 ExportOptions. \u041f\u0440\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0438 export method: \u201cdevelopment\u201d ExportOptions \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. \u0414\u043b\u044f production ExportOptions \u043d\u0430\u0434\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0438 \u0434\u043b\u044f production- \u0438 development-\u043e\u043f\u0446\u0438\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430.<\/p>\n<pre><code>def send_to_firebase(ipa_name, scheme)     firebase_apps = {         \"Dev\" => \"1:1234567890:ios:0a1b2c3d4e5f67890\",         \"PreProd\" => \"1:0987654321:ios:0a1b2c3d4e5f67890\"     }     firebase_app_distribution(         app: firebase_apps[scheme], # \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0445\u0435\u043c \u0440\u0430\u0437\u043d\u044b\u0435 \u0430\u0439\u0434\u0438         # groups: \"\u0412\u0421\u0415\u041c\",         # testers: \"tester@gmail.com\",         ipa_path: \".\/ipas\/#{ipa_name}.ipa\",         firebase_cli_path: \"\/usr\/local\/bin\/firebase\",         firebase_cli_token: \"\u0432\u0430\u0448 \u0442\u043e\u043a\u0435\u043d\",         debug: true     ) end<\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u0432 \u043e\u0434\u0438\u043d lane \u0438\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0447\u0442\u043e\u0431\u044b CI \u043c\u043e\u0433 \u0434\u0451\u0440\u0433\u0430\u0442\u044c \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u043a\u0430\u043a\u043e\u043c \u0443\u0433\u043e\u0434\u043d\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0435. \u0423 \u043d\u0430\u0441 \u044d\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043e.<\/p>\n<pre><code>desc \"\u0421\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u043e\u0439. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane archive_project scheme:\\\"Dev\\\" filename:\\\"dev_1.2.3\\\"\" lane :archive_project do |options|     scheme = options[:scheme]     filename = options[:filename]     archive_project(scheme, false, filename) end desc \"\u0421\u043e\u0431\u0440\u0430\u0442\u044c \u0440\u0435\u043b\u0438\u0437\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane archive_beta scheme:\\\"Prod\\\" filename:\\\"release_1.2.3\\\"\" lane :archive_beta do |options|     scheme = options[:scheme]     filename = options[:filename]     archive_project(scheme, true, filename) end desc \"\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u0436\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0430\u0440\u0445\u0438\u0432 ipa \u0432 \u0444\u0430\u0435\u0440\u0431\u0435\u0439\u0437 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0430\u0439\u043b\u0430. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane distribute_to_firebase filename:\\\"dev_1.2.3\\\" scheme:\\\"Dev\\\"\" lane :distribute_to_firebase do |options|     filename = options[:filename]     scheme = options[:scheme]     send_to_firebase(filename, scheme) end<\/code><\/pre>\n<p>\u0412\u0441\u0451, \u0447\u0442\u043e \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0430 Fastlane, \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 Firebase \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0434\u0432\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e\u0434\u0440\u044f\u0434:<\/p>\n<pre><code>fastlane archive_project scheme:\u201cDev\u201d filename:\u201cdev_1.2.3\u201d fastlane distribute_to_firebase filename:\u201cdev_1.2.3\u201d scheme:\u201cDev\u201d<\/code><\/pre>\n<p>\u042d\u0442\u0438 \u0436\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0432 \u043e\u0434\u043d\u0443 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u201c;\u201d<\/p>\n<pre><code>fastlane archive_project scheme:\u201cDev\u201d filename:\u201cdev_1.2.3\u201d fastlane distribute_to_firebase filename:\u201cdev_1.2.3\u201d scheme:\u201cDev\u201d<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f git tags. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043c\u044b \u0434\u043b\u044f \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0437\u0430\u043f\u0443\u0448\u0438\u043c \u0442\u0435\u0433 dev_1.72.44.TASK-123, \u0442\u043e \u0432 Firebase \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0441 \u043d\u043e\u043c\u0435\u0440\u043e\u043c 1.72.44.TASK-123. \u0421\u0430\u043c\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0434\u0443\u0442 \u0438\u0437 gitlab-ci.yml. \u0415\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0439\u0434\u0451\u0442 \u043d\u0435 \u0442\u0430\u043a, \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u0444\u0435\u0439\u043b\u0438\u0442\u0441\u044f \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u043f\u0440\u0438\u0434\u0451\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u043d\u0430 \u043b\u043e\u0433\u0438 \u0434\u0436\u043e\u0431\u044b, \u043e\u043d \u0443\u0432\u0438\u0434\u0438\u0442 \u043f\u0440\u0438\u0447\u0438\u043d\u0443: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u043e\u0435\u043a\u0442 \u0443\u0434\u0430\u043b\u0438\u043b\u0438 \u0438\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u0435\u0449\u0451 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u0435 \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. Firebase \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439.<\/p>\n<h3>Testflight deploy \u0434\u043b\u044f itunesconnect \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 AppStore<\/h3>\n<p>Testflight \u2014 \u044d\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0431\u043e\u0440\u043e\u043a \u043e\u0442 Apple. \u0412 \u043d\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u043b\u0438\u0437\u0438\u0442\u044c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438. \u041f\u043e \u0441\u0445\u0435\u043c\u0435 CI\/CD \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441 Firebase, \u0442. \u043a. \u043e\u043d\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c\u044b, \u0442\u043e\u043b\u044c\u043a\u043e Firebase \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u0435\u043d \u0434\u043b\u044f \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a. \u0410 Testflight \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u0440\u0435\u043b\u0438\u0437\u0430 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>Firebase \u2014 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0430, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435. Testflight \u2014 \u0434\u043b\u044f production, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0435\u043b\u0438\u0437\u0438\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0451.<\/p>\n<p>\u041c\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043d\u0430\u0448 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u0432 ItunesConnect, \u0438 \u0441\u0430\u043c\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u0440\u0430\u0437\u0443 \u0432 Testflight. Testflight \u0434\u0430\u0451\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u0430\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c, \u043f\u0440\u044f\u043c\u043e \u043d\u0430 \u0430\u0439\u0444\u043e\u043d.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u0442\u0430\u043f\u044b \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore \u0442\u0435 \u0436\u0435. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0432 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e, \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 AppStore. \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0441\u043a\u0430\u0447\u0430\u0435\u0442 Testflight \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u043b\u0438. <\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f \u2014 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u0431\u043e\u0440\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0430\u0437\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u043e\u0434 \u0441\u0435\u0431\u044f \u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u0438\u0445 \u0431\u0438\u043b\u0434-\u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438. \u0422\u0430\u043a \u0432\u043e\u0442, AppStore \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p>\u0415\u0441\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 lane \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u043d\u043e\u043c\u0435\u0440\u0430 \u0431\u0438\u043b\u0434\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Fastlane.<\/p>\n<pre><code>desc \"\u041c\u0435\u043d\u044f\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0441 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0435\u0439 \u0441\u0430\u043c\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u0414\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0432\u0438\u0434\u0430 1.56.45 \u0438\u043b\u0438 1.34.21(12), \u0433\u0434\u0435 12 - \u043d\u043e\u043c\u0435\u0440 \u0431\u0438\u043b\u0434\u0430. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane update_version version:\\\"1.46.45\\\"\" lane :update_version do |options|     git_tag_version = options[:version]     puts git_tag_version     major = \"\"     minor = \"\"     patch = \"\"     build = \"\"     errorMsg = \"Wrong version number: \\\"#{git_tag_version}\\\"!\\nPlease use versioning like {major_number}.{minor_number}.{patch_number}({build_number})\\n or {major_number}.{minor_number}.{patch_number}\"     patternWithBuild = \/\\A(\\d+).(\\d+).(\\d+)\\((\\d+)\\)\\z\/     pattern = \/\\A(\\d+).(\\d+).(\\d+)\\z\/     if match = patternWithBuild.match(git_tag_version)         major, minor, patch, build = match.captures     elsif match = pattern.match(git_tag_version)         major, minor, patch = match.captures     else         UI.user_error!(errorMsg)     end     if major.to_s.empty? || minor.to_s.empty? || patch.to_s.empty?         UI.user_error!(errorMsg)     end     if build.to_s.empty?         build = \"1\"     end     version = \"#{major}.#{minor}.#{patch}\"     increment_version_number_in_plist(version_number: \"#{version}\" , target: \"PSB\")     increment_version_number_in_plist(version_number: \"#{version}\", target: \"notificationService\")     increment_build_number_in_plist(build_number: \"#{build}\", target: \"PSB\")     increment_build_number_in_plist(build_number: \"#{build}\", target: \"notificationService\") end desc \"\u041c\u0435\u043d\u044f\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0431\u0435\u0437 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0441\u0430\u043c\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane force_update_version version:\\\"1.46.45_TASK\\\"\" lane :force_update_version do |options|     git_tag_version = options[:version]     puts git_tag_version     increment_version_number_in_plist(version_number: \"#{git_tag_version}\" , target: \"PSB\")     increment_version_number_in_plist(version_number: \"#{git_tag_version}\", target: \"notificationService\") end<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0434\u0432\u0430 lane: \u043e\u0434\u0438\u043d \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u044e, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b\u0430 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore, \u0432\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u0432\u0435\u0440\u0441\u0438\u044e \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e (\u043d\u0443 \u0438\u043b\u0438 \u043f\u043e\u0447\u0442\u0438 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e). \u041f\u0435\u0440\u0432\u044b\u0439 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f Testflight, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u2014 \u0434\u043b\u044f Firebase, \u0442. \u043a. Firebase \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u043a\u0432\u044b \u0432 \u0432\u0435\u0440\u0441\u0438\u044e \u0438 \u043d\u0435 \u043f\u0440\u0438\u0434\u0438\u0440\u0447\u0438\u0432 \u043a \u043f\u043e\u0432\u0442\u043e\u0440\u0430\u043c.<\/p>\n<p>\u0415\u0449\u0451 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0430\u043c lane \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore:\u00a0<\/p>\n<pre><code>desc \"\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u0436\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0430\u0440\u0445\u0438\u0432 ipa \u0432 Testflight \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0430\u0439\u043b\u0430. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane distribute_to_testflight itunes_username:\\\"email@gg.ru\\\" filename:\\\"release_1.2.3\\\"\" lane :distribute_to_testflight do |options|     username = options[:itunes_username]     filename = options[:filename]     puts \"username #{username} and filename #{filename}\"     if username.to_s.empty?          UI.user_error!(\"Need to pass ITUNES_USERNAME to testflight lane\")     end     upload_to_testflight(         username: \"#{username}\",         ipa: \".\/ipas\/#{filename}.ipa\",         skip_waiting_for_build_processing: true     ) end<\/code><\/pre>\n<p>Lane \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u044b\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0443\u0442 \u043d\u0435\u0447\u0435\u0433\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0442\u044c, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u043f\u043b\u0430\u0433\u0438\u043d Fastlane. \u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u0437\u043e\u0432\u0430 lane \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore \u043f\u0440\u043e\u0441\u0442:<\/p>\n<pre><code>fastlane update_version version:\u201c$right_version\u201d fastlane archive_beta scheme:${scheme} filename:${filename} fastlane distribute_to_testflight itunes_username:\u201d${ITUNES_USERNAME}\u201d filename:${filename}<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c $right_version \u2014 \u044d\u0442\u043e \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u0432\u0435\u0440\u0441\u0438\u0438. \u0415\u0441\u043b\u0438 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c, \u0442\u043e lane \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0442\u0441\u044f \u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u043f\u0443\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u0441\u044f. ${ITUNES_USERNAME} \u2014 \u044d\u0442\u043e email \u044e\u0437\u0435\u0440\u0430, \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0432 \u0432 Testflight.<\/p>\n<h3>[Gitlab CI].gitlab-ci.yml<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438\u0432\u0435\u043d\u0442\u043e\u0432 \u0432 Gitlab \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432. \u0418 \u0438\u043c\u044f \u0435\u043c\u0443 \u200a\u2014\u200a gitlab-ci.yml. \u042d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0437\u0430\u0434\u0430\u0451\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u042d\u0442\u043e \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0432\u0441\u0435 lane, \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u043c\u0438. \u041e\u0434\u0438\u043d \u0438\u0437 \u0435\u0433\u043e \u043c\u0438\u043d\u0443\u0441\u043e\u0432(\u0430 \u043c\u043e\u0436\u0435\u0442, \u0438 \u043f\u043b\u044e\u0441\u043e\u0432) \u2014 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043d\u0430 bash. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0443\u0442 \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043e\u0431\u044b\u0447\u043d\u043e\u0435. \u041e\u0431 \u044d\u0442\u043e\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u043e\u0437\u0436\u0435, \u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code>stages:   - test_stage test_job:   stage: test_stage   tags:     - ios_tests   script:     - echo \"Hello world\"<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0443\u0448\u0438\u043c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0444\u0430\u0439\u043b .gitlab-ci.yml \u0441 \u0442\u0430\u043a\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c, \u0442\u043e \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0432\u0435\u043d\u0442 \u0433\u0438\u0442\u043b\u0430\u0431\u0430 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0436\u043e\u0431\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 <em>echo \u201cHello world\u201d.<\/em><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/30e\/3e4\/938\/30e3e4938de86934395da3522a502ce8.png\" width=\"1600\" height=\"630\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/30e\/3e4\/938\/30e3e4938de86934395da3522a502ce8.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043f\u0440\u043e\u0441\u0442:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/192\/2cd\/53a\/1922cd53aa198f1f5ddc209205d91846.png\" width=\"766\" height=\"336\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/192\/2cd\/53a\/1922cd53aa198f1f5ddc209205d91846.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0418\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u043a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u0440\u0451\u0445 \u0441\u0442\u0430\u0434\u0438\u044f\u0445, \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443:<\/p>\n<ul>\n<li>\n<p>before_script<\/p>\n<\/li>\n<li>\n<p>script<\/p>\n<\/li>\n<li>\n<p>after_script<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 Fastlane, Swift \u0438 \u0447\u0442\u043e \u0434\u0443\u0448\u0435 \u0443\u0433\u043e\u0434\u043d\u043e.<\/p>\n<p><strong>\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b \u0441 .gitlab-ci.yml<\/strong><\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0443 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0438\u0437 \u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b.<\/p>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441 <a href=\"https:\/\/gist.github.com\/yawillianpsb\/e8f6558d32264dc049fa114cc448070c\">\u0442\u0430\u043a\u0438\u043c \u0444\u0430\u0439\u043b\u043e\u043c\u00a0CI<\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c 5 \u0441\u0442\u0430\u0434\u0438\u0439 \u0438 8 \u0434\u0436\u043e\u0431, \u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f3c\/b0c\/6e7\/f3cb0c6e74e81eedaf2d2baf45947027.png\" width=\"1600\" height=\"367\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f3c\/b0c\/6e7\/f3cb0c6e74e81eedaf2d2baf45947027.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0443\u0442 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0430\u0432\u0438\u043b:<\/p>\n<ol>\n<li>\n<p>\u041f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b (pipeline) \u0441\u043e\u0441\u0442\u043e\u044f\u0442 \u0438\u0437 \u0441\u0442\u0430\u0434\u0438\u0439 (stage), \u0430 \u043e\u043d\u0438 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u2014 \u0438\u0437 \u0434\u0436\u043e\u0431 (job)<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0434\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0430\u0434\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0434\u0436\u043e\u0431, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e. \u0417\u043d\u0430\u0447\u0438\u0442, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432, \u0442\u043e <em>test_job1<\/em> \u0438 <em>test_job2<\/em> \u0441\u0442\u0430\u0440\u0442\u0430\u043d\u0443\u043b\u0438 \u0431\u044b \u043f\u043e\u0447\u0442\u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u043d\u0435 \u043e\u0436\u0438\u0434\u0430\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430<\/p>\n<\/li>\n<li>\n<p>\u00a0\u0421\u0442\u0430\u0434\u0438\u0438 \u0438\u0434\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043a\u0430\u0436\u0434\u0430\u044f \u043f\u0435\u0440\u0435\u0434 \u0441\u0442\u0430\u0440\u0442\u043e\u043c \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0434\u0436\u043e\u0431 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0434\u0436\u043e\u0431\u044b \u0432\u044b\u0437\u0432\u0430\u043b\u0430\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0430 <em>exit<\/em> \u0441 \u043d\u0435\u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u0442\u043e \u0434\u0436\u043e\u0431\u0430 \u0444\u0435\u0439\u043b\u0438\u0442\u0441\u044f: <em>exit 0<\/em> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0436\u043e\u0431\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c; \u043b\u044e\u0431\u0430\u044f \u0434\u0440\u0443\u0433\u0430\u044f \u0446\u0438\u0444\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0443<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u0441\u0442\u0430\u0434\u0438\u0438 \u043e\u0434\u043d\u0430 \u0438\u0437 \u0434\u0436\u043e\u0431 \u0437\u0430\u0444\u0435\u0439\u043b\u0438\u043b\u0430\u0441\u044c \u0431\u0435\u0437 \u0444\u043b\u0430\u0433\u0430 <em>allow_failure: true<\/em>, \u0442\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0430\u0434\u0438\u044f \u043d\u0435 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442. \u0414\u043b\u044f<em> test_job3<\/em> \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433 \u0432\u043a\u043b\u044e\u0447\u0451\u0435\u043d, \u0430 \u0434\u043b\u044f <em>test_job5 <\/em>\u043d\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u0441\u0442\u0430\u0434\u0438\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0436\u043e\u0431 \u0438 \u043e\u0434\u043d\u0430 \u0438\u0437 \u043d\u0438\u0445 \u0437\u0430\u0444\u0435\u0439\u043b\u0438\u043b\u0430\u0441\u044c, \u0442\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0436\u043e\u0431\u044b \u0441\u0442\u0430\u0434\u0438\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0440\u0430\u0437\u043d\u044b\u0445 \u0434\u0436\u043e\u0431\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c coverage. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0434\u0436\u043e\u0431\u0435 1 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 coverage 0%, \u0432 \u0434\u0436\u043e\u0431\u0435 2 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 10%, \u0438 \u0432 \u0434\u0436\u043e\u0431\u0435 4 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 100%. \u0422\u043e\u0433\u0434\u0430 \u043e\u0431\u0449\u0438\u0439 coverage \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0441\u0440\u0435\u0434\u0438 \u0432\u0441\u0435\u0445 \u0434\u0436\u043e\u0431 (0 + 10 + 100) \/ 3. \u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0430\u0434\u0438\u044e \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043d\u0430 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u2014 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0434\u0436\u043e\u0431\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a. \u041d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u044b \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Xcode. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0434\u043b\u044f \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u0441\u0435\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0442\u0430\u0440\u0433\u0435\u0442\u044b. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f\u200a \u200a\u043f\u0440\u043e\u0433\u043d\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0432 \u044d\u0442\u0438\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u0430\u0445 \u0438 \u0441\u0440\u0435\u0434\u043d\u0438\u0439 coverage \u043f\u043e \u043d\u0438\u043c<\/p>\n<\/li>\n<li>\n<p>Coverage \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u0444\u0435\u0439\u043b\u0438\u043b\u0430\u0441\u044c<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0434\u0436\u043e\u0431\u0435 8 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0444\u043b\u0430\u0433 <em>when: on_failure<\/em>, \u2014 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0434\u0436\u043e\u0431\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0437\u0430\u0444\u0435\u0439\u043b\u0438\u043b\u0441\u044f. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043f\u0440\u043e\u0448\u0451\u043b \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u044d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f. \u0422\u0430\u043a\u043e\u0439 \u0444\u043b\u0430\u0433 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0441\u0442\u0430\u0432\u0438\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0434\u0436\u043e\u0431\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u043e\u0432\u0435\u0449\u0430\u044e\u0442 \u043e \u0437\u0430\u0444\u0435\u0439\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u0442\u0430\u0434\u0438\u0439 \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0438\u0445 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0432 \u0444\u0430\u0439\u043b\u0435 CI \u0432 \u0444\u0430\u0437\u0435 <em>stages:<\/em> \u043f\u0435\u0440\u0432\u044b\u043c\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u0435, \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u044b\u0448\u0435 \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u0414\u0436\u043e\u0431\u044b \u2014 \u0442\u0430\u043a \u0436\u0435: \u0447\u0435\u043c \u0432\u044b\u0448\u0435 \u0432\u044b \u0438\u0445 \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435, \u0442\u0435\u043c \u0440\u0430\u043d\u044c\u0448\u0435 \u043e\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u0441\u044f \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435 CI \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u2014 \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 <em>extends:<\/em>. \u041c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u0443\u044e \u0434\u0436\u043e\u0431\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u043d\u0430\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438. <\/p>\n<p>\u0412\u0430\u0436\u043d\u043e\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0435\u0441\u043b\u0438 \u043c\u044b \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <em>script<\/em> \u0438\u043b\u0438 <em>tags<\/em>, \u0430 \u043d\u0435 \u0432 \u0434\u0436\u043e\u0431\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 \u044d\u0442\u043e\u0442 \u0448\u0430\u0431\u043b\u043e\u043d, \u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0432 \u0434\u0436\u043e\u0431\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 script, \u0442\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u0441\u044f \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0442, \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0432 \u0434\u0436\u043e\u0431\u0435. \u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u0434\u0436\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u0442\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u043c \u044d\u0442\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432 <em>before_script<\/em> \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u0430 \u0432 \u0441\u0430\u043c\u0438\u0445 \u0434\u0436\u043e\u0431\u0430\u0445 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u0444\u0430\u0437\u0443 <em>script<\/em>.<\/p>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043c\u044b \u0433\u043e\u043d\u044f\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0438 \u0441\u0447\u0438\u0442\u0430\u0435\u043c coverage. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c\u00a0<a href=\"https:\/\/gist.github.com\/yawillianpsb\/f4cbd38cccabe0d2f4b607735123d893\"><strong><em>.gitlab-ci.yml<\/em><\/strong> \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430<\/a> \u2014 \u0441\u0432\u0435\u0440\u0445\u0443 \u0432\u043d\u0438\u0437 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0443\u043d\u043a\u0442\u0443.<\/p>\n<h4>Variables<\/h4>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435 .gitlab-ci.yml \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438, \u0433\u0434\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0434\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430. \u0422\u0430\u043a\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u043c\u0438\u043c\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043a\u0430\u0436\u0435\u0442\u0435 \u0432 \u0441\u0430\u043c\u043e\u043c \u0444\u0430\u0439\u043b\u0435, \u0432\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0446\u0435\u043b\u044b\u0439 \u043d\u0430\u0431\u043e\u0440<a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/variables\/predefined_variables.html\"> Predefined CI\/CD variables<\/a> \u0438 \u043d\u0430\u0431\u043e\u0440 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (Settings \u20d7\u20d7\u2192 CI\/CD \u2192 Variables). \u0412\u0441\u0435 \u0442\u0440\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043e \u0432\u0441\u0435\u0445 \u0432\u0430\u0448\u0438\u0445 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0436\u043e\u0431\u0430\u0445 \u0432\u043d\u0443\u0442\u0440\u0438 .gitlab-ci.yml.<\/p>\n<h4>Stages<\/h4>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0431\u043e\u0440 \u0441\u0442\u0430\u0434\u0438\u0439 \u0434\u043b\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432, \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u043e\u043d\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0442, \u043a\u0430\u043a \u0434\u0436\u043e\u0431\u044b \u0431\u0443\u0434\u0443\u0442 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432.<\/p>\n<h4>Jobs<\/h4>\n<p>\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u0436\u043e\u0431:<\/p>\n<ul>\n<li>\n<p>extends \u2014 \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438;<\/p>\n<\/li>\n<li>\n<p>stage \u2014 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0432 \u043a\u0430\u043a\u043e\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u0436\u043e\u0431\u0430. \u0412\u043d\u0443\u0442\u0440\u0438 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u043e\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e;<\/p>\n<\/li>\n<li>\n<p>before script, script, after script \u2014 \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043c\u0430\u043d\u0434 Shell \u0432 \u0442\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p>only\/except \u2014 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442, \u043f\u043e\u0434 \u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \/ \u0442\u043e\u0447\u043d\u043e \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0434\u0436\u043e\u0431\u0430;<\/p>\n<\/li>\n<li>\n<p>tags \u2014 \u0442\u0435\u0433\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u044b \u043f\u043e\u043c\u0435\u0442\u0438\u043b\u0438 \u0440\u0430\u043d\u043d\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0435\u0433\u043e;<\/p>\n<\/li>\n<li>\n<p>allow failure \u2014 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \/ \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u0437\u0430\u0444\u0435\u0439\u043b\u0435\u043d\u043d\u0443\u044e \u0434\u0436\u043e\u0431\u0443, \u0437\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 exit codes;<\/p>\n<\/li>\n<li>\n<p>artifacts \u2014 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0434\u0436\u043e\u0431\u044b.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041a\u0430\u043a \u0434\u0435\u0431\u0430\u0436\u0438\u0442\u044c<\/h3>\n<p>Gitlab-runner \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\u043a\u0430\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0432\u0430\u0448\u0438 \u0434\u0436\u043e\u0431\u044b \u0434\u043b\u044f \u0438\u0445 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u043f\u0443\u0448\u0435\u043c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u0447\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0436\u0438\u0437\u043d\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443<\/p>\n<pre><code>gitlab-runner exec shell exec shell test_job1<\/code><\/pre>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u0434\u043b\u044f <a href=\"https:\/\/gist.github.com\/yawillianpsb\/e8f6558d32264dc049fa114cc448070c\">\u0442\u0430\u043a\u043e\u0433\u043e gitlab-ci.yml<\/a>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/834\/4f5\/b6b\/8344f5b6bb13b622da1d7da0c3c24a6b.png\" width=\"1364\" height=\"982\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/834\/4f5\/b6b\/8344f5b6bb13b622da1d7da0c3c24a6b.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0423 \u0442\u0430\u043a\u043e\u0433\u043e \u0434\u0435\u0431\u0430\u0433\u0433\u0438\u043d\u0433\u0430 \u0435\u0441\u0442\u044c \u043c\u0438\u043d\u0443\u0441: \u200a\u0432\u0430\u043c \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043e \u0442\u0438\u043f\u0443 CI_JOB_ID, CI_PIPELINE_ID, \u0442. \u043a. \u044d\u0442\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f Gitlab \u043d\u0430 \u0440\u0430\u043d\u043d\u0435\u0440. \u041d\u043e \u0442\u0430\u043a\u043e\u0439 \u0434\u0435\u0431\u0430\u0433\u0433\u0438\u043d\u0433 \u0432\u043f\u043e\u043b\u043d\u0435 \u0441\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432. \u0412\u043e\u0442 \u0435\u0449\u0451 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0432\u043e\u0434\u0430 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/01a\/d02\/0e6\/01ad020e6067cfdf22b159f8d3fe1011.png\" width=\"1980\" height=\"954\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/01a\/d02\/0e6\/01ad020e6067cfdf22b159f8d3fe1011.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0418\u0442\u043e\u0433\u043e<\/h3>\n<ol>\n<li>\n<p>\u041c\u044b \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c Gitlab-runner \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 Fastlane<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c lane, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442: \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e code coverage, \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0432 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 Firebase \u0438\u043b\u0438 Testflight<\/p>\n<\/li>\n<\/ol>\n<p>\u0415\u0449\u0451 \u0440\u0430\u0437 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435:<\/p>\n<ol>\n<li>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c gitlab-runner<\/p>\n<p><code>brew install gitlab-runner<\/code><\/p>\n<\/li>\n<li>\n<p>\u0414\u0435\u043b\u0430\u0435\u043c mac \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u043c \u0434\u043b\u044f CI<\/p>\n<p><code>gitlab-runner register<\/code><\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0440\u0430\u043d\u043d\u0435\u0440<\/p>\n<p><code>gitlab-runner install<\/code><\/p>\n<p><code>gitlab-runner start<\/code><\/p>\n<\/li>\n<li>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Fastlane<\/p>\n<p><code>brew install fastlane<\/code><\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u043f\u043a\u0430 Fastlane \u0441 \u043d\u0443\u0436\u043d\u044b\u043c\u0438      \u0444\u0430\u0439\u043b\u0430\u043c\u0438<\/p>\n<p><code>fastlane init<\/code><\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c      \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c lane<\/p>\n<p><code>fastlane unit_test scheme:CoreTests<\/code><\/p>\n<\/li>\n<li>\n<p>\u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0432 Firebase<\/p>\n<p><code>fastlane archive_project scheme:\u201cDev\u201d filename:\u201cdev_1.2.3\u201d<\/code><\/p>\n<p><code>fastlane distribute_to_firebase filename:\u201cdev_1.2.3\u201d scheme:\u201cDev\u201d<\/code><\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0437\u043e\u0432 lane \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore<\/p>\n<p><code>fastlane update_version version:\u201c$right_version\u201d<\/code><\/p>\n<p><code>fastlane archive_beta scheme:${scheme} filename:${filename}<\/code><\/p>\n<p><code>fastlane distribute_to_testflight<\/code><\/p>\n<p><code>itunes_username:\u201d${ITUNES_USERNAME}\u201d filename:${filename}<\/code><\/p>\n<\/li>\n<li>\n<p>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0434\u0436\u043e\u0431\u044b, \u0447\u0442\u043e\u0431\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u0435\u0440\u0435\u0434 \u043f\u0443\u0448\u0435\u043c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/p>\n<p><code>gitlab-runner exec shell exec shell test_job1<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Gitlab CI + Fastlane + Firebase + Testflight \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0435\u0434\u043e\u0440\u043e\u0433\u043e. \u041c\u043e\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c 2\u20133 \u043c\u0430\u0448\u0438\u043d\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443.<\/p>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ol>\n<li>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u0434\u0435\u043b\u0430\u043b \u0437\u0430\u0434\u0430\u0447\u0443, \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043d\u0430 \u043d\u0435\u0451 \u0442\u0435\u0441\u0442\u044b \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b \u041c\u0420 \u043d\u0430 \u043a\u043e\u0434-\u0440\u0435\u0432\u044c\u044e. \u00a0       <\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u041c\u0420 CI\/CD \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u043d\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043b\u0438 \u043d\u0438\u0437\u043a\u0438\u0439 code coverage, \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442. \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 MP \u043d\u0430 \u0440\u0435\u0432\u044c\u044e, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0435\u0433 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043a\u043e\u043c\u043c\u0438\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440  dev_1.33.22.TASK-123 cicd \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .      \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/p>\n<\/li>\n<li>\n<p>\u041e\u043d \u0433\u043e\u0442\u043e\u0432\u0438\u0442 \u0441\u0431\u043e\u0440\u043a\u0443 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0435 \u0432 Firebase. \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0 <\/p>\n<\/li>\n<li>\n<p>\u0418\u0437 Firebase \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0431\u043e\u0440\u043a\u0443. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u0435\u0432\u044c\u044e \u0438 \u00a0 \u043d\u0443\u0436\u043d\u044b\u0435 \u0430\u043f\u0440\u0443\u0432\u044b.      \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/p>\n<\/li>\n<\/ol>\n<p>\u041c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043c\u0435\u0440\u0436\u0438\u0442\u044c: \u0434\u0435\u0440\u0436\u0438\u043c \u043a\u043e\u0434 \u0432 master \u0438 \u043d\u0430 \u043d\u0435\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f code coverage, \u0447\u0442\u043e\u0431\u044b \u0443\u0436\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 MP \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u043b\u0438 \u0432 master \u0441 \u043f\u043e\u043d\u0438\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441 Gitlab CI, \u0430 \u043d\u0430\u043c \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u0440\u0430\u0441\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0431\u043e\u0440\u043a\u0438.<\/p>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 CI\/CD, \u043d\u0430\u0443\u0447\u0438\u0442\u0435 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043c, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0439\u0442\u0435 \u0438\u0434\u0435\u0438 \u043f\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0438 \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0439\u0442\u0435 \u0432\u0430\u0448\u0438\u0445 \u043a\u043e\u043b\u043b\u0435\u0433 \u043e \u0431\u043e\u043b\u044f\u0445. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u0430\u0440\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0432 CI\/CD, \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u044f\u0442 \u0434\u0435\u043d\u044c\u0433\u0438 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430 \u0438\u043b\u0438 \u043d\u0435\u0440\u0432\u044b \u0432\u0430\u0448\u0438\u0445 \u043a\u043e\u043b\u043b\u0435\u0433.<\/p>\n<p>\u0417\u0430\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0432\u043e\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/583532\/\"> https:\/\/habr.com\/ru\/articles\/583532\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u0434\u0435\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f CI\/CD \u0434\u043b\u044f iOS, \u0434\u0430 \u0438 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c, \u2014 \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0443\u0442\u0438\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c, \u043c\u043e\u0436\u0435\u043c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442. \u041d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0440\u0430\u0441\u0442\u0451\u0442, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0435\u0435, \u0447\u0435\u043c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043b\u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c, \u0447\u0442\u043e \u0436\u0435 \u0442\u0430\u043c \u0441 Code-signing \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c. <\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u0441\u0430\u043c\u043e\u0435 \u0440\u0443\u0442\u0438\u043d\u043d\u043e\u0435 \u0438 \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u0437\u0430\u043d\u044f\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0435\u0440\u0451\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f CI, \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432. \u041d\u0435\u0442 \u0437\u0435\u043b\u0451\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432? \u0412 master \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0451\u0448\u044c. \u0410 \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043a\u0442\u043e-\u0442\u043e \u0432\u043e\u043b\u044c\u0451\u0442 \u0432 master \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434, \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u041d\u0443\u0436\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u043f\u0443\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Gitlab CI + Fastlane + Firebase + Testflight. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438 10 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u044b \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c, \u0438 \u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f \u043a\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u044d\u0442\u043e\u0442 \u043e\u043f\u044b\u0442? \u0414\u043b\u044f \u0432\u0441\u0435\u0445, \u043a\u043e\u043c\u0443 \u043d\u0443\u0436\u0435\u043d CI\/CD \u0438 \u043a\u0442\u043e \u0441\u0438\u0434\u0438\u0442 \u043d\u0430 Gitlab. \u0414\u043b\u044f Github \u0431\u0443\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0432\u044f\u0437\u043a\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441 Travis, \u2014 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u044b. \u0412 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0432\u0441\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 Gitlab CI, Fastlane \u0432\u043c\u0435\u0441\u0442\u043e \u0433\u043e\u043b\u043e\u0433\u043e xcodebuild \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0442\u044b \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, Firebase \u0438 Testflight.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 Gitlab \u0438 \u043c\u044b \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u0432 \u043b\u0438\u043c\u0438\u0442 Firebase, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 CI\/CD.<\/p>\n<h3>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/h3>\n<p><strong>Gitlab CI<\/strong> \u2014 \u044d\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438. \u041e\u043d\u0430 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u0447\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0446\u0435\u043b\u0435\u0439. \u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u043a \u043d\u0435\u043c\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 <em>.gitlab-ci.yml. <\/em>\u041e\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0431\u043e\u0442\u0430 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u043d\u0430 \u043d\u043e\u0443\u0442\u0431\u0443\u043a\u0430\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0435\u0441\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0448\u0438\u043d\u044b \u043d\u0430 MacOS \u2014 \u0438\u0445 \u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0432 Gitlab CI.<\/p>\n<p><strong>Fastlane <\/strong>\u2014 \u0432\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434 \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435. \u0414\u043b\u044f \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c <a href=\"https:\/\/docs.fastlane.tools\/plugins\/available-plugins\/\">\u043c\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: \u043e\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 AppIcon \u0434\u043e \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 AppStore. \u041f\u043b\u0430\u0433\u0438\u043d\u044b, \u043a\u0430\u043a \u0438 \u0441\u0430\u043c Fastlane, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 ruby, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u044d\u0442\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043d\u0430 ruby.<\/p>\n<p>Gitlab CI \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0432 \u0432\u0438\u0434\u0435 shell-\u043a\u043e\u043c\u0430\u043d\u0434 \u043d\u0430 \u0440\u0430\u043d\u043d\u0435\u0440, \u0432 \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043c\u0430\u043d\u0434 \u0432\u0445\u043e\u0434\u0438\u0442 Fastlane. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043e\u043d\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0432\u043e\u0438 \u0437\u0430\u0434\u0430\u0447\u0438.<\/p>\n<p><strong>Firebase<\/strong> \u2014 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u044c\u044e\u0442\u0438\u043d\u0433\u0430 \u0441\u0431\u043e\u0440\u043e\u043a, \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u0431\u043e\u0440\u043e\u043a \u0434\u043e \u0432\u0430\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Firebase App Distribution \u2014 \u043e\u043d \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0438 \u0431\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e.<\/p>\n<p><strong>Code coverage<\/strong> \u2014 \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u0434\u0430 \u0442\u0435\u0441\u0442\u0430\u043c\u0438. \u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0444\u043e\u0440\u043c\u0443\u043b\u0435:<\/p>\n<p><em>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \/ \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430) * 100%<\/em><\/p>\n<h3>[Gitlab CI] Gitlab-runner<\/h3>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430 \u043f\u0443\u0442\u0438 \u0441\u0430\u043c\u0443\u0440\u0430\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u2014 \u044d\u0442\u043e \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c \u043d\u0430\u0448 mac \u0441 CI. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u043c\u0430\u043a\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043a\u043e\u043c\u0430\u043d\u0434:<\/p>\n<ol>\n<li>\n<p><a href=\"https:\/\/docs.gitlab.com\/runner\/install\/osx.html\">\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c<\/a> \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 gitlab-runner      \u043d\u0430 mac (\u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Homebrew). <a href=\"https:\/\/brew.sh\/index_ru\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 Homebrew<\/a>. <\/p>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b:<\/p>\n<p><em>brew install gitlab-runner<\/em><\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0434\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 mac \u043a\u0430\u043a \u0440\u0430\u043d\u043d\u0435\u0440 \u0434\u043b\u044f CI:<\/p>\n<p><em>gitlab-runner register<\/em><\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0432\u0435\u0441\u0442\u0438 URL \u0434\u043e \u0433\u0438\u0442\u043b\u0430\u0431\u0430, \u0433\u0434\u0435 \u0445\u043e\u0441\u0442\u0438\u043c\u0441\u044f.<\/p>\n<p>\u0415\u0449\u0451 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f CI. \u0415\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u0434\u0443\u0447\u0438 Owner\u2019\u043e\u043c \u0438\u043b\u0438 Maintainer\u2019\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 Settings \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b CI\/CD. \u0420\u0430\u0437\u0434\u0435\u043b Runners.<\/p>\n<figure class=\"full-width\"><figcaption>\u0420\u0430\u0437\u0434\u0435\u043b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 CI\/CD<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u0442\u0443\u0434\u0430.<\/p>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0440\u0430\u043d\u043d\u0435\u0440\u0430 \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442, \u043e\u043d\u043e \u0434\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0438.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u0435\u0433\u0438 \u0440\u0430\u043d\u043d\u0435\u0440\u0430. \u0411\u0435\u0437 \u0442\u0435\u0433\u043e\u0432 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u0443\u0436\u0435\u043d \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u0438\u043d. \u041f\u043e \u0442\u0435\u0433\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0430\u043d\u043d\u0435\u0440\u044b: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u0438\u043d \u0431\u0443\u0434\u0435\u0442 \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u0441\u0435\u0442\u0438 \u0438 \u0441\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0438, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043d\u0435\u0442. \u0422\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0435\u0433\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0432\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u0433\u0438 ios_tests,ios_firebase, \u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u2014 \u0442\u043e\u043b\u044c\u043a\u043e ios_tests. \u0418 \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439 \u043f\u043e \u0442\u0438\u043f\u0443. <\/p>\n<p>\u0422\u0438\u043f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 shell.<\/p>\n<figure class=\"full-width\"><figcaption>gitlab-runner register<\/figcaption><\/figure>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430\u0448 \u0440\u0430\u043d\u043d\u0435\u0440. \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0436\u0435 \u0441\u043f\u0438\u0441\u043a\u0435 Runners \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u043e\u0441\u043a\u043b\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0437\u043d\u0430\u043a \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0440\u0430\u043d\u043d\u0435\u0440 \u0435\u0449\u0451 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0438 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435. \u0418\u0434\u0451\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0448\u0430\u0433\u0443.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0440\u0430\u043d\u043d\u0435\u0440. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435:<\/p>\n<pre><code>gitlab-runner install gitlab-runner start<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u0440\u0430\u043d\u043d\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0433\u043e\u0440\u0435\u0442\u044c\u0441\u044f \u0437\u0435\u043b\u0451\u043d\u044b\u043c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0423 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043b\u043e\u0433\u0430\u043c\u0438. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043b\u043e\u0433\u043e\u0432, \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u043f\u0443\u0442\u0438 \u201c<strong><em>~\/.gitlab-runner\/<\/em><\/strong>\u201d. \u0422\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0444\u0430\u0439\u043b <strong><em>config.toml<\/em><\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u043d\u043d\u0435\u0440\u0430\u0445, \u0432 \u043d\u0451\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <strong><em>output_limit<\/em><\/strong>, \u2014 \u044d\u0442\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0432 \u0431\u0430\u0439\u0442\u0430\u0445 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u043b\u043e\u0433\u043e\u0432 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445. \u0414\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0435\u0441\u0442\u044c <a href=\"https:\/\/docs.gitlab.com\/runner\/configuration\/advanced-configuration.html#the-runners-section\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>, \u0434\u043b\u044f output_limit \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e: \u201cMaximum build log size in kilobytes. Default is 4096 (4MB)\u201d. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u2014 4 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u0430. <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 IOS-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0442\u043e \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e. \u0417\u043d\u0430\u0447\u0438\u0442, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0451\u043c \u043b\u043e\u0433\u043e\u0432, \u043d\u0430\u0434\u043e \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435.<\/p>\n<p>\u0412\u0441\u0451, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u043e\u0440\u043e\u0433, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0434\u0436\u043e\u0431\u0430\u0445. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c:<\/p>\n<pre><code>[[runners]]   output_limit = 500000   name = \"My first runner\"   url = \"https:\/\/gitlab-01\"   token = \"7qybRaWukobUuXYoiSMc\"   executor = \"shell\"   [runners.custom_build_dir]   [runners.cache]     [runners.cache.s3]     [runners.cache.gcs]     [runners.cache.azure]<\/code><\/pre>\n<p>\u041d\u0443\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u044b\u043c \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b \u043b\u043e\u0433\u043e\u0432 \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c \u0432\u0435\u0441\u0438\u0442 37 \u041c\u0431, \u043e\u043d \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430. \u0412\u0441\u0435 \u043b\u043e\u0433\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0433\u0438\u0442\u043b\u0430\u0431\u0435 \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f. \u0413\u043e\u0442\u043e\u0432\u043e, Gitlab CI \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u043c!<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Fastlane<\/h3>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Fastlane \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 Homebrew (<a href=\"https:\/\/docs.fastlane.tools\/getting-started\/ios\/setup\/\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>). \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 ruby \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u043e\u0431\u044b\u0447\u043d\u043e \u043e\u043d \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 macos \u043f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443. \u041d\u0430\u0431\u0438\u0440\u0430\u0435\u043c:<\/p>\n<pre><code>brew install fastlane<\/code><\/pre>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>cd.\/path_to_project<\/strong> \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443<\/p>\n<pre><code>fastlane init<\/code><\/pre>\n<p>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u0441\u044f \u043f\u0430\u043f\u043a\u0430 Fastlane \u0441 \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438. \u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Fastlane \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Swift: \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043b\u0430\u0439\u043d\u044b \u043d\u0430 Swift, \u0430 \u043d\u0435 \u043d\u0430 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c DSL, \u2014 \u044d\u0442\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u0433 (<a href=\"https:\/\/docs.fastlane.tools\/getting-started\/ios\/fastlane-swift\/\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>). <\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u0432\u0430\u0436\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0434\u0435\u0441\u044c \u2014 \u044d\u0442\u043e Fastfile. \u041e\u043d \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 lane. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 Fastlane. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0430\u043c Fastlane \u043a\u0430\u043a \u043d\u0435\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 (\u0432 \u041e\u041e\u041f), \u0430 lane \u2014 \u043a\u0430\u043a \u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439. <\/p>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 lane \u0434\u043b\u044f \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u043e\u0432. \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 \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b. \u041c\u044b \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0432\u044b\u0431\u0440\u0430\u043b\u0438 scan \u043a\u0430\u043a \u0441\u0430\u043c\u044b\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434\u0430. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435, \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0438 \u0438\u0445 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0432 <a href=\"https:\/\/docs.fastlane.tools\/actions\/scan\/#parameters\">\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043f\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0443 scan<\/a>.\u00a0<\/p>\n<pre><code>desc \"\u041f\u0440\u043e\u0433\u043e\u043d \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0445\u0435\u043c. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane unit_test scheme:CoreTests\" lane :unit_test do |options|     scheme = options[:scheme]     scan(         scheme: scheme,         device: \"iPhone 11 Pro\",         fail_build: false,         clean: true,         derived_data_path: \".\/tests\/derived\",         max_concurrent_simulators: \"3\",         code_coverage: true,         output_directory: \".\/tests\/#{scheme}_report\/\",         result_bundle: true     ) end<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f lane, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f \u0441\u0445\u0435\u043c\u044b CoreTests, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0435\u0440\u0451\u043c \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432\u044b\u0437\u043e\u0432\u0430 lane. \u0415\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0440\u043c\u043b\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u0445\u0435\u043c\u044b \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432, \u0442\u0430\u043a \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0445\u0435\u043c\u044b \u043f\u043e\u0434 \u0442\u0435\u0441\u0442\u044b. \u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c, \u0430 \u043d\u0435 \u0441\u0430\u043c\u0438 \u0442\u0430\u0440\u0433\u0435\u0442\u044b.<\/p>\n<p>\u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043e\u0434\u0438\u043d \u0442\u0430\u0440\u0433\u0435\u0442, \u043e\u0434\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u2014 \u0438 \u043d\u0435\u0442 \u043f\u0443\u0442\u0430\u043d\u0438\u0446\u044b. \u041d\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 CI \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 30\u201340 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439, \u0430 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432 \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435, \u0432\u0430\u0436\u043d\u043e \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f. \u0422\u0430\u0440\u0433\u0435\u0442 \u2014 \u044d\u0442\u043e executable(buildable)-\u043f\u0440\u043e\u0435\u043a\u0442, \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441 Build Phase, Build Settings, General. \u0421\u0445\u0435\u043c\u044b \u2014 \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0435, \u043a\u0430\u043a \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u0440\u0433\u0435\u0442\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432 \u043f\u043e\u0434 \u0441\u043e\u0431\u043e\u0439. \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u044b Fastlane \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441\u043e \u0441\u0445\u0435\u043c\u0430\u043c\u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 lane \u0432\u0432\u0435\u0434\u0451\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code>fastlane unit_test scheme:CoreTests<\/code><\/pre>\n<p>\u0412 \u043e\u0442\u0432\u0435\u0442 \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u043b\u043e\u0433\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0438 \u0441\u0430\u043c\u0438 \u043b\u043e\u0433\u0438 Fastlane. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u0430\u043f\u043a\u0443 <strong><em>.\/tests\/CoreTests_report\/<\/em><\/strong> \u0441 \u043e\u0442\u0447\u0451\u0442\u043e\u043c \u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong><em>.xcresult<\/em><\/strong>. \u041f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443 \u043f\u043b\u0430\u0433\u0438\u043d scan \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u0430\u043c \u0435\u0449\u0451 \u0434\u0432\u0430 \u0444\u0430\u0439\u043b\u0430 \u2014 <strong><em>report.html &amp; report.junit<\/em><\/strong>. \u041f\u0435\u0440\u0432\u044b\u0439 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u043b\u044e\u0434\u044f\u043c, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u2014 \u0434\u043b\u044f Gitlab CI \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0447\u0451\u0442\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u2014 \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0437\u0436\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043f\u0440\u043e \u0430\u0440\u0442\u0438\u0444\u0430\u043a\u0442\u044b \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430\u0445.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u0447\u0451\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0431\u044b\u043b\u0438 \u043b\u0438 \u0437\u0430\u0444\u0435\u0439\u043b\u0435\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0438 \u0432 \u043a\u0430\u043a\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 <a href=\"https:\/\/gist.github.com\/yawillianpsb\/8773ff01cb1f9390d5a03d54de27a508\">\u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430 Swift<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 report.junit \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u0432 \u043a\u0430\u043a\u0438\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u0445. <\/p>\n<h3>Code coverage<\/h3>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043c\u0435\u0440\u0436 \u0432 master. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Fastlane. \u041e\u043d \u0443\u0436\u0435 \u0432\u044b\u0434\u0430\u043b \u043d\u0430\u043c <strong><em>.xcresult<\/em><\/strong>, \u0438 \u043d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f.<\/p>\n<p><a href=\"http:\/\/docs.fastlane.tools\/actions\/xcov\/#xcov\">\u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f Fastlane xcov<\/a> \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u043e\u0442\u0447\u0451\u0442\u043e\u0432. \u041d\u0430\u043c \u043d\u0443\u0436\u0435\u043d json, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0441\u0430\u043c \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f, \u0430 \u043f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 json.<\/p>\n<pre><code>desc \"\u0420\u0430\u0441\u0447\u0435\u0442 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0441\u0445\u0435\u043c. \u0414\u043e\u043b\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043b\u0435\u0439\u043d\u0430 unit_test. \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430: fastlane code_coverage scheme:BaseTests\" lane :code_coverage do |options|     scheme = options[:scheme]     FileUtils.mv(\"..\/tests\/#{scheme}_report\/#{scheme}.xcresult\", \"..\/tests\/derived\/Logs\/Test\/#{scheme}.xcresult\")     begin         FileUtils.rm_rf(\"..\/tests\/#{scheme}_report\/coverage_result\")     rescue         puts \"Folder alredy deleted\"     end     xcov(         workspace: \"PSB.xcworkspace\",         scheme: scheme,         derived_data_path: \".\/tests\/derived\",         output_directory: \".\/tests\/#{scheme}_report\/coverage_result\",         html_report: false,         markdown_report: false,         json_report: true     ) end<\/code><\/pre>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u043c\u0430\u0445\u0438\u043d\u0430\u0446\u0438\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c <strong><em>.xcresult<\/em><\/strong> \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e <strong><em>xcov<\/em><\/strong> \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u043b\u0441\u044f \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043f\u0430\u043f\u043a\u0438 <strong><em>derived<\/em><\/strong>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c \u0435\u0433\u043e \u0432 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u043e\u043c code coverage. \u0418 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0430\u043f\u043a\u0430 <em>output_directory<\/em> \u0431\u044b\u043b\u0430 \u043f\u0443\u0441\u0442\u0430, \u0442. \u043a. <strong><em>xcov<\/em><\/strong> \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u0442\u0438\u0440\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442\u044b, \u0430<\/p>\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-396181","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/396181","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=396181"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/396181\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=396181"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=396181"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=396181"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}