{"id":378950,"date":"2024-06-15T09:00:19","date_gmt":"2024-06-15T09:00:19","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=378950"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=378950","title":{"rendered":"<span>CI\/CD \u0437\u0430\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438? \u0418\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 CI\/CD \u043f\u043e\u0434 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e iOS \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u043c\u0438\u0442\u0440\u0438\u0439, \u0438 \u044f iOS \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Triada. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>CI\/CD<\/strong> \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e iOS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u0443\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0441 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0430 \u2013 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c.<\/p>\n<p>\u041c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c <strong>CI\/CD<\/strong> \u0434\u043b\u044f iOS \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c \u043d\u0430 <strong>GitLab<\/strong> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <strong>Fastlane<\/strong>. \u0421\u0431\u043e\u0440\u043a\u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 <strong>TestFlight<\/strong> \u0438 \u0432 <strong>Firebase<\/strong>, \u0435\u0441\u043b\u0438 \u043e\u043d \u0443 \u0432\u0430\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d. \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>. <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\"><\/p>\n<p><\/a>\u0427\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f:\u00a0<\/p>\n<ol>\n<li>\n<p>3 Gitlab \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c <strong>CI\/CD<\/strong> (<strong>PROJECT repo)<\/strong>. <br \/>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043b\u0438\u043d\u0442\u0435\u0440, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0433\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043d\u0435 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e. \u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Unit \u0442\u0435\u0441\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p>\u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c\u00a0<sub><br \/><\/sub><\/p>\n<ol>\n<li>\n<p>\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432 (<strong>CERTS repo)<\/strong><\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 <strong>CI\/CD<\/strong> (\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0442\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0438 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438)<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p>MacOS \u043c\u0430\u0448\u0438\u043d\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c <strong>CI\/CD<\/strong> (<strong>CI\/CD SERVER)<\/strong>.\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>Apple ID <\/strong>\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c, \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Firebase Service Account<\/strong> &#8212; \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c. \u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f <strong>CI\/CD<\/strong> \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. <strong>Firebase<\/strong> \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0431\u043e\u0440\u043e\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430\u043c.\u00a0<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Gitlab<\/strong> (<strong>Premium<\/strong> or <strong>Ultimate<\/strong>) \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <strong>Gitlab API<\/strong> \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Discord<\/strong> \u0441\u0435\u0440\u0432\u0435\u0440 &#8212; \u0441\u0442\u043e\u0438\u0442 \u0443\u0447\u0435\u0441\u0442\u044c, \u0447\u0442\u043e \u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0432\u0435\u0431\u0445\u0443\u043a\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Jira<\/strong> &#8212; \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f c \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>Jira<\/strong>, \u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u0432\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f &#8212; \u043e\u0434\u0438\u043d \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 <strong>CI\/CD<\/strong>. \u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <strong>CI\/CD<\/strong> \u0432 \u0446\u0435\u043b\u043e\u043c, \u0430 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u043f\u0438\u0448\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433:\u00a0<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 <strong>CI\/CD<\/strong><\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 iOS \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <strong>GitLab<\/strong><\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0448\u0438\u043d\u044b (\u0445\u043e\u0441\u0442\u0430) \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 <strong>CI\/CD<\/strong><\/p>\n<\/li>\n<\/ol>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d:<br \/>\u041f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043c\u0435\u0440\u0434\u0436 \u0440\u0435\u043a\u0432\u0435\u0441\u0442\u0430 (<strong>MR<\/strong>) \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0442\u043a\u0438 \u0438 \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432. \u041f\u043e\u0441\u043b\u0435 \u0438\u0445 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043c\u043e\u0433 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u043d\u0435\u0441\u0442\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0432 \u043a\u043e\u0434. \u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u043b\u0438\u043d\u0442\u0435\u0440\/\u0444\u043e\u0440\u043c\u0430\u0442\u0442\u0435\u0440. \u0415\u0441\u043b\u0438 \u0432 <strong>MR<\/strong> \u0432\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u043a\u0438, \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043d\u043e\u0432\u043e.<\/p>\n<p>\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430 <code>create_archive<\/code> \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 <strong>.ipa<\/strong>-\u0430\u0440\u0445\u0438\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 <strong>release notes<\/strong> \u0434\u043b\u044f <strong>Firebase<\/strong>. \u0417\u0430\u0442\u0435\u043c \u044d\u0442\u043e\u0442 \u0430\u0440\u0445\u0438\u0432 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 <strong>Firebase<\/strong> \u0438 <strong>TestFlight<\/strong> \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0438 \u0446\u0435\u043b\u043e\u043c, \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 <strong>CI\/CD<\/strong> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/403\/a66\/4c9\/403a664c9fb2e00a53df5845cd73202f.png\" alt=\"\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0420\u0438\u0441 2. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0430\u0440\u0445\u0438\u0432\u0430 \u0438 \u0442\u0435\u043f\u043b\u043e\u0439 \u0432 TestFlight \u0438 Firebase\" title=\"\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0420\u0438\u0441 2. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0430\u0440\u0445\u0438\u0432\u0430 \u0438 \u0442\u0435\u043f\u043b\u043e\u0439 \u0432 TestFlight \u0438 Firebase\" width=\"1600\" height=\"261\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/403\/a66\/4c9\/403a664c9fb2e00a53df5845cd73202f.png\"\/><\/p>\n<div><figcaption>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/362\/4fa\/9e5\/3624fa9e5022814cb13fef10ad1e9817.png\" alt=\"\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0430\u0440\u0445\u0438\u0432\u0430 \u0438 \u0442\u0435\u043f\u043b\u043e\u0439 \u0432 TestFlight \u0438 Firebase\" title=\"\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0430\u0440\u0445\u0438\u0432\u0430 \u0438 \u0442\u0435\u043f\u043b\u043e\u0439 \u0432 TestFlight \u0438 Firebase\" width=\"1600\" height=\"261\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/362\/4fa\/9e5\/3624fa9e5022814cb13fef10ad1e9817.png\"\/><\/p>\n<div><figcaption>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0430\u0440\u0445\u0438\u0432\u0430 \u0438 \u0442\u0435\u043f\u043b\u043e\u0439 \u0432 TestFlight \u0438 Firebase<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u044f \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u043b \u0440\u0430\u043d\u0435\u0435, \u0432 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432 <strong>.swift<\/strong>, \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0432 <strong>MR<\/strong>, \u0438 \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u044b \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 <strong>MR<\/strong>. \u0425\u043e\u0447\u0443 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e, \u043d\u0430\u0448\u0435\u043b \u043b\u0438 \u043b\u0438\u043d\u0442\u0435\u0440 \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438\u043b\u0438 \u043d\u0435\u0442 &#8212; \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u0415\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u0432 <strong>MR<\/strong> \u043d\u0430 <strong>GitLab<\/strong> \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0441\u044f \u0441\u0442\u0430\u0442\u0443\u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0434\u0430 \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u043c, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430, \u0438\u043d\u0430\u0447\u0435 \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043b\u044f <strong>API Gitlab.<\/strong><\/p>\n<p>\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a32\/413\/4f7\/a324134f70a7b45bc83bba5e4c9fd07a.png\" alt=\"\u0420\u0438\u0441 3. \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0432 MR\" title=\"\u0420\u0438\u0441 3. \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0432 MR\" width=\"1600\" height=\"699\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a32\/413\/4f7\/a324134f70a7b45bc83bba5e4c9fd07a.png\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441 3. \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0432 MR<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0422\u0430\u043c, \u0433\u0434\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043b\u0438\u043d\u0442\u0435\u0440 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0442\u0440\u0435\u0434 \u0432 MR.<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u0442 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0439, \u0447\u0442\u043e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430 \u043b\u0438\u0442\u0435\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0432\u0435\u0434\u0435\u043d <strong>diff<\/strong> \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0434\u0430. \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0432<strong> Gitlab API<\/strong>, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 <strong>diff<\/strong> \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0431\u043b\u043e\u043a\u043e\u0432 \u043a\u043e\u0434\u0430 \u043a\u0430\u043a \u0432 \u0441\u0442\u0430\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u0435, \u0442\u0430\u043a \u0438 \u0432 \u043d\u043e\u0432\u043e\u043c, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f <strong>sha1<\/strong> \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430. \u041d\u043e \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c\u0441\u044f \u0441 <strong>Gitlab API<\/strong>, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e <s>\u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432<\/s> \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u043a\u0443. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 <strong>Gitlab API <\/strong>\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/docs.gitlab.com\/ee\/api\/discussions.html#parameters-for-multiline-comments\" rel=\"noopener noreferrer nofollow\"><u>\u0442\u0443\u0442<\/u><\/a>.<\/p>\n<\/div>\n<\/details>\n<p>\u0428\u0430\u0433\u0438 <code>deploy_to_fb<\/code> \u0438 <code>deploy_to_tf<\/code> \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0430\u0440\u0445\u0438\u0432\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 <strong>Firebase<\/strong> \u0438 <strong>TestFlight<\/strong> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0414\u043b\u044f <strong>Firebase<\/strong> \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432 \u0438 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u044e\u0442\u0441\u044f <strong>release notes<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0432 \u043e Release notes<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u00a0<strong>Jira<\/strong>\u00a0&#8212; \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u043e\u043c\u0435\u0440 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043d\u0435\u0435. \u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0435\u0449\u0435 \u0438 \u044d\u043f\u0438\u043a &#8212; \u043e\u043d \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u043e\u043c\u0435\u0440 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u0441\u0431\u043e\u0440\u043a\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bd4\/0e5\/9d2\/bd40e59d25146337b751f88aa8817a7d.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes\" width=\"2598\" height=\"1462\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bd4\/0e5\/9d2\/bd40e59d25146337b751f88aa8817a7d.png\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c71\/f93\/bfb\/c71f93bfb737ec20798e4d4a0667eaca.png\" alt=\"\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes\" title=\"\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes\" width=\"2632\" height=\"1470\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c71\/f93\/bfb\/c71f93bfb737ec20798e4d4a0667eaca.png\"\/><\/p>\n<div><figcaption>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes<\/figcaption><\/div>\n<\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0436\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d\u0430, \u0432 <strong>release notes<\/strong> \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u043d\u043e\u043c\u0435\u0440\u0435 \u0441\u0431\u043e\u0440\u043a\u0438<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/21d\/b29\/4df\/21db294dfa08734bbf0150fc28da9a6a.png\" alt=\"\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes\" title=\"\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes\" width=\"1846\" height=\"1042\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/21d\/b29\/4df\/21db294dfa08734bbf0150fc28da9a6a.png\"\/><\/p>\n<div><figcaption>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0430\u0440\u0445\u0438\u0432\u0430, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432 <strong>TestFlight<\/strong> \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u044b.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 CI\/CD<\/h2>\n<p>\u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 <strong>CI\/CD<\/strong><\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 [CERTS repo]\u00a0<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432 \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043e\u0431\u0449\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435. <br \/>\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u043a\u0440\u0443\u0433\u0443 \u043b\u0438\u0446 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 <strong>CI\/CD<\/strong>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0435\u043f\u043e \u0432 <strong>Gitlab<\/strong> \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c.<br \/>\u0412\u0443\u0430\u043b\u044f &#8212; \u0432\u044b \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b. \u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430\u043c\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.\u00a0<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 [CI\/CD repo]<\/h3>\n<p>\u041c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c. \u0424\u0430\u0439\u043b\u044b, \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u0434\u0435\u0441\u044c, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0438. \u041f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0437\u044f\u0442\u044c \u0438\u0437 <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/a>.<a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\"><br \/><\/a><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b01\/3f3\/c9b\/b013f3c9bbb71e1b98c3e59cff214df2.png\" alt=\"\u041a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 CI\/CD\" title=\"\u041a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 CI\/CD\" width=\"858\" height=\"494\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b01\/3f3\/c9b\/b013f3c9bbb71e1b98c3e59cff214df2.png\"\/><\/p>\n<div><figcaption>\u041a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 CI\/CD<\/figcaption><\/div>\n<\/figure>\n<p>\u0433\u0434\u0435 \u043f\u043e \u043f\u0443\u0442\u0438 <code>fastlane\/<\/code> \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/db4\/e67\/e6e\/db4e67e6e0e59c9962c456c0defadfeb.png\" alt=\"\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 Fastlane\" title=\"\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 Fastlane\" width=\"1038\" height=\"242\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/db4\/e67\/e6e\/db4e67e6e0e59c9962c456c0defadfeb.png\"\/><\/p>\n<div><figcaption>\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 Fastlane<\/figcaption><\/div>\n<\/figure>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <code>.gitlab-ci-template.yml<\/code> &#8212; \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u0430\u0448\u0435\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043b\u044e\u0431\u044b\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0441 <strong>CI\/CD<\/strong>. \u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u043e\u043d \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u0438 \u0432 \u043d\u0435\u043c \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 &#8212; \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u043f\u043e\u0437\u0436\u0435 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 <strong>CI\/CD<\/strong> \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. <\/p>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u0432\u0430\u0441 \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0435\u0437\u0434\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043d\u0430 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0442\u043a\u0438, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 \u0448\u0430\u0433\u0435 <code>create_archive<\/code>, \u043b\u0438\u0431\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0432\u0441\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/394\/282\/7e8\/3942827e88bfb379f85b07ffdb915516.png\" alt=\"\u0423\u0441\u043b\u043e\u0432\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430create_archive\u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u0432\u0435\u043d\u0442\u0430 \u0438 \u0438\u043c\u0435\u043d\u0438 \u0432\u0435\u0442\u043a\u0438\" title=\"\u0423\u0441\u043b\u043e\u0432\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430create_archive\u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u0432\u0435\u043d\u0442\u0430 \u0438 \u0438\u043c\u0435\u043d\u0438 \u0432\u0435\u0442\u043a\u0438\" width=\"1566\" height=\"110\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/394\/282\/7e8\/3942827e88bfb379f85b07ffdb915516.png\"\/><\/p>\n<div><figcaption>\u0423\u0441\u043b\u043e\u0432\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430<code>create_archive<\/code>\u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u0432\u0435\u043d\u0442\u0430 \u0438 \u0438\u043c\u0435\u043d\u0438 \u0432\u0435\u0442\u043a\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435\u0441\u044c \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c <strong>Firebase<\/strong> \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>TestFlight<\/strong> \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0443\u0434\u0430\u043b\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<p>\u0414\u043b\u044f <strong>Firebase<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/089\/bf0\/def\/089bf0def6fb0b13989381294b67c0e0.png\" alt=\"\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Firebase\" title=\"\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Firebase\" width=\"946\" height=\"308\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/089\/bf0\/def\/089bf0def6fb0b13989381294b67c0e0.png\"\/><\/p>\n<div><figcaption>\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Firebase<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u043b\u044f <strong>TestFlight<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5a8\/09b\/33c\/5a809b33c164e4db13a6d1b94980d9a1.png\" alt=\"\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 TestFlight\" title=\"\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 TestFlight\" width=\"1170\" height=\"268\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5a8\/09b\/33c\/5a809b33c164e4db13a6d1b94980d9a1.png\"\/><\/p>\n<div><figcaption>\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 TestFlight<\/figcaption><\/div>\n<\/figure>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 [PROJECT repo]<\/h3>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b\u043c \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u043c, \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0435\u0441\u0442\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0430\u043d\u043d\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>Appfile<\/strong><\/p>\n<\/li>\n<\/ol>\n<h4>1. \u0423\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0445\u0435\u043c \u0438 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432<\/h3>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u043e\u043c\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0442\u0430\u0440\u0433\u0435\u0442\u0430 \u0435\u0449\u0435 \u0442\u0430\u0440\u0433\u0435\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0439 \u043a \u043d\u0435\u043c\u0443 \u0441\u0445\u0435\u043c\u0435.<br \/>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0433\u0430\u0439\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 2 \u0442\u0430\u0440\u0433\u0435\u0442\u0430\u043c\u0438:<em><br \/><\/em><\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/627\/0f6\/b9f\/6270f6b9f46f29a2fab7df11bc0a953a.jpeg\" alt=\"\u0422\u0430\u0440\u0433\u0435\u0442\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c CI\/CD\" title=\"\u0422\u0430\u0440\u0433\u0435\u0442\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c CI\/CD\" width=\"372\" height=\"336\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/627\/0f6\/b9f\/6270f6b9f46f29a2fab7df11bc0a953a.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0422\u0430\u0440\u0433\u0435\u0442\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c CI\/CD<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0440\u0430\u043d\u0435\u0435 \u0431\u044b\u043b\u043e \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e, \u0442\u0430\u0440\u0433\u0435\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 unit \u0442\u0435\u0441\u0442\u044b. \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u0443 \u0412\u0430\u0441 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438 UI \u0442\u0435\u0441\u0442\u044b, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u0430\u0440\u0433\u0435\u0442 \u0438 \u0441\u0445\u0435\u043c\u0430 \u043f\u043e\u0434 \u043d\u0435\u0433\u043e.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b <strong>CI\/CD<\/strong> \u0441 \u043d\u0430\u0448\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043f\u0435\u0440\u0432\u044b\u0435 2 \u0441\u0445\u0435\u043c\u044b:<br \/><strong>1<\/strong>. \u0421\u0445\u0435\u043c\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442<br \/><strong>2.<\/strong> \u0421\u0445\u0435\u043c\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b<br \/>3. \u0421\u0445\u0435\u043c\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u0435\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<br \/>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0438\u043c\u0435\u0435\u043c 3 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0441\u0445\u0435\u043c\u044b, \u0441\u0442\u043e\u0438\u0442 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043d\u0438\u0445 \u0441\u0442\u043e\u0438\u0442 \u0433\u0430\u043b\u043e\u0447\u043a\u0430 \u043d\u0430 shared, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#8212; \u0441\u0445\u0435\u043c\u0430 \u0432\u0438\u0434\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u043c<em>.<\/em><\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ae1\/fd4\/ec1\/ae1fd4ec1544dd0223d244960b1b8556.png\" alt=\"\u0421\u0445\u0435\u043c\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f CI\/CD\" title=\"\u0421\u0445\u0435\u043c\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f CI\/CD\" width=\"624\" height=\"112\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ae1\/fd4\/ec1\/ae1fd4ec1544dd0223d244960b1b8556.png\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f CI\/CD<\/figcaption><\/div>\n<\/figure>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Firebase<\/h3>\n<p>\u041c\u044b \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0443\u0436\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a <strong>Firebase<\/strong>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043c\u0435\u043b\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u0442\u0443 \u0441\u0435\u043a\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u0438\u043b\u0438 <strong>Firebase<\/strong> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>\u0428\u0430\u0433\u0438 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 Firebase.<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <a href=\"https:\/\/firebase.google.com\/\" rel=\"noopener noreferrer nofollow\"><u>Firebase<\/u><\/a>. <a href=\"https:\/\/firebase.google.com\/\" rel=\"noopener noreferrer nofollow\"><u><br \/><\/u><\/a>\u0415\u0441\u043b\u0438 \u0432\u044b \u0435\u0449\u0435 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442 <strong>Firebase<\/strong>, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u201c<strong>Add project<\/strong>\u201d. <br \/>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0441 \u043d\u0430\u0448\u0438\u043c iOS \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u201c<strong>Add app<\/strong>\u201d \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c <strong>iOS<\/strong> \u043f\u0440\u043e\u0435\u043a\u0442. <br \/>\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f 5 \u0448\u0430\u0433\u043e\u0432, \u0441\u0430\u043c\u044b\u043c \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u0434\u043b\u044f \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u201c<strong>Apple bundle ID<\/strong>\u201d &#8212; \u0435\u0433\u043e \u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 <strong>Xcode<\/strong>. <br \/>\u0421\u043a\u0430\u0447\u0430\u0439\u0442\u0435 <strong>GoogleService-Info.plist<\/strong> \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0435\u0433\u043e \u0432 \u043a\u043e\u0440\u0435\u043d\u044c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441 <strong>iOS<\/strong> \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Firebase.<\/strong><\/p>\n<div class=\"floating-image\">\n<figure class=\"float\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d12\/b86\/2df\/d12b862df9503fda731a8c1b790c86fb.png\" alt=\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &quot;App Distribution&quot; \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0443\u043f\u043f\" title=\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &quot;App Distribution&quot; \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0443\u043f\u043f\" width=\"510\" height=\"1426\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d12\/b86\/2df\/d12b862df9503fda731a8c1b790c86fb.png\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &#171;App Distribution&#187; \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0443\u043f\u043f<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u201c<strong>Release &amp; Monitor<\/strong>\u201d \u0438 \u0432\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u201c<strong>App Distribution<\/strong>\u201d. \u0412 \u043e\u0442\u043a\u0440\u044b\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u201c<strong>Get started<\/strong>\u201d.\u00a0<\/p>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u0447\u0442\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430. <\/p>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0442\u0430\u0431 \u201c<strong>Testers &amp; Groups<\/strong>\u201d \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0433\u0440\u0443\u043f\u043f\u0443 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0430 \u201c<strong>Add group<\/strong>\u201d (\u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043d\u0435\u0435 \u0441\u0435\u0431\u044f).<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0443\u043f\u043f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b &#8212; \u043e\u043d\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 <strong>GitLab<\/strong> <strong>CI\/CD<\/strong><\/p>\n<\/p>\n<\/div>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \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\/222\/450\/874\/222450874db045287f20915d7b14ead8.png\" alt=\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &quot;Project settings&quot;\" title=\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &quot;Project settings&quot;\" width=\"828\" height=\"226\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/222\/450\/874\/222450874db045287f20915d7b14ead8.png\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &#171;Project settings&#187;<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u0442\u0430\u0431\u0435 \u201c<strong>General<\/strong>\u201d \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u043a \u043d\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u041d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0441\u0435\u043a\u0446\u0438\u044f \u201c<strong>Your apps<\/strong>\u201d &#8212; \u0432 \u043d\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0435\u0435 \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<br \/>\u041e\u0442\u043c\u0435\u0447\u0443, \u0447\u0442\u043e <strong>Bundle ID<\/strong> \u043c\u0435\u043d\u044f\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u0440\u0430\u0439\u043d\u0435 \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e.\u00a0 \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u0443\u044e \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 &#8212; \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u201c<strong>App ID<\/strong>\u201d &#8212; \u043e\u043d\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0430\u043b\u0435\u0435 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435.<\/p>\n<\/div>\n<\/details>\n<h4>2. \u0417\u0430\u0432\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b <strong>CI\/CD<\/strong> \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 <strong>Gitlab<\/strong> \u0437\u0430\u0432\u0435\u0441\u0442\u0438 3 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435.<br \/>&#171;<strong>SETTINGS<\/strong>&#187; \u2192 &#171;<strong>CI\/CD<\/strong>&#187; \u2192 &#171;<strong>Variables<\/strong>&#187; \u2192 &#171;<strong>Expand<\/strong>&#187; \u2192 &#171;<strong>Add variable<\/strong>&#171;<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26a\/0b6\/e2e\/26a0b6e2e77b8e598bc7d28a4a455f51.png\" alt=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c CI\/CD. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 CI\/CD\" title=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c CI\/CD. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 CI\/CD\" width=\"1600\" height=\"435\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/26a\/0b6\/e2e\/26a0b6e2e77b8e598bc7d28a4a455f51.png\"\/><\/p>\n<div><figcaption>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c CI\/CD. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 CI\/CD<\/figcaption><\/div>\n<\/figure>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\"><strong>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"> PROJECT_NAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">FastlaneProject<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">PROJECT_REPO_URL<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f git clone<\/p>\n<\/td>\n<td>\n<p align=\"left\">https:\/\/gitlab.com\/XXXXXX\/YYYYYY.git \u0432\u043c\u0435\u0441\u0442\u043e XXXXXX \u0438 YYYYYY \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0432\u0430\u0448\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">XCWORKSPACE<\/p>\n<\/td>\n<td>\n<p align=\"left\">E\u0441\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043f\u043e\u0434\u044b, \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u043c\u044f .xcworkspace \u0444\u0430\u0439\u043b\u0430 \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c<\/p>\n<\/td>\n<td>\n<p align=\"left\">FastlaneProject.xcworkspace<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041a\u0430\u043a \u0438\u0442\u043e\u0433, \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435:<\/p>\n<div class=\"floating-image\">\n<figure class=\"float\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f84\/031\/145\/f840311451f9a6d356f142eb13c896b3.png\" alt=\"\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 CI\/CD \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435\" title=\"\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 CI\/CD \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435\" width=\"291\" height=\"300\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f84\/031\/145\/f840311451f9a6d356f142eb13c896b3.png\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 CI\/CD \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435<\/figcaption><\/div>\n<\/figure>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c <code>Masked<\/code> \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043b\u0438\u0448\u044c \u0434\u043b\u044f \u0441\u043a\u0440\u044b\u0442\u0438\u044f \u0430\u0434\u0440\u0435\u0441\u0430 \u0432 \u043b\u043e\u0433\u0430\u0445<\/p>\n<\/p>\n<\/div>\n<h4>3. \u0417\u0430\u0432\u043e\u0434\u0438\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c <code>\/.gitlab-ci.yml<\/code><strong> <\/strong>\u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<strong> <\/strong>\u0438 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0432 \u043d\u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code class=\"yaml\">include: - project: 'cicdXXXXXX\/cicd'   file: '\/.gitlab-ci-template.yml'<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <code>.gitlab-ci-template.yml<\/code> \u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <code>cicdXXXXXX\/cicd<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a <strong>[CI\/CD repo]<\/strong>, \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0438\u043c\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043b\u044f <strong>CI\/CD<\/strong>.<\/p>\n<h4>4. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0440\u0430\u043d\u043d\u0435\u0440\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u0412 Gitlab \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u201c<strong>Settings<\/strong>\u201d -> \u201c<strong>CI\/CD<\/strong>\u201d \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u0435\u043a\u0446\u0438\u044e \u201c<strong>Runners<\/strong>\u201d<em><br \/><\/em><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6b9\/1aa\/6e4\/6b91aa6e4f9a36e711d38b2c65f83ed7.png\" alt=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c CI\/CD. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0430\u043d\u043d\u0435\u0440\u044b\" title=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c CI\/CD. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0430\u043d\u043d\u0435\u0440\u044b\" width=\"1600\" height=\"473\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6b9\/1aa\/6e4\/6b91aa6e4f9a36e711d38b2c65f83ed7.png\"\/><\/p>\n<div><figcaption>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c CI\/CD. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0430\u043d\u043d\u0435\u0440\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043a\u0430 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0439\u0442\u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u043c \u0440\u0430\u043d\u043d\u0435\u0440\u044b \u0441 \u0442\u0435\u0433\u0430\u043c\u0438 &#8212; \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u0445, \u043d\u0430\u0436\u043c\u0435\u043c \u043d\u0430 \u201c<strong>New project runner<\/strong>\u201d. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0435\u0433\u0438 \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0440\u0430.<br \/>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043d\u043e\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0438\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438: <strong>PROJECT_NAME\/JOB_NAME\/NUMBER<\/strong>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a57\/680\/7ac\/a576807acbc268008f93cd185b8f4007.png\" alt=\"\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Gitlab \u0440\u0430\u043d\u043d\u0435\u0440\u0430 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\" title=\"\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Gitlab \u0440\u0430\u043d\u043d\u0435\u0440\u0430 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\" width=\"1600\" height=\"997\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a57\/680\/7ac\/a576807acbc268008f93cd185b8f4007.png\"\/><\/p>\n<div><figcaption>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Gitlab \u0440\u0430\u043d\u043d\u0435\u0440\u0430 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f Create runner \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0432 \u0441\u0440\u0435\u0434\u0435, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0440\u0430\u043d\u043d\u0435\u0440 &#8212; \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u0442\u043e\u0442 \u0448\u0430\u0433 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f.<br \/>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430 <strong>[CI\/CD SERVER]<\/strong>.<br \/>\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u0432\u0430\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043f\u043e\u0434 sudo &#8212; \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0420\u0430\u043d\u043d\u0435\u0440\u0430. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 executor \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c <code>shell<\/code>.<br \/>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0440\u0430\u043d\u043d\u0435\u0440\u044b, \u0444\u0430\u0439\u043b \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0442\u0443\u0442:<\/p>\n<pre><code class=\"bash\">\u279c  ~ ls -ltrh ~\/.gitlab-runner\/config.toml -rw-------@ 1 User  staff   900B May  4 19:55 \/Users\/CICDUser\/.gitlab-runner\/config.toml<\/code><\/pre>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 <strong>config.toml<\/strong> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u043c \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u043c, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<pre><code class=\"yaml\">concurrent = 1 check_interval = 0   [[runners]]   name = \"Runner_name\"   limit = 1   id = XXXXXXXX   url = \"https:\/\/gitlab.com\/\"   token = \"xxxx-XXXXXXXXXXXXXXXXXXXX\"   executor = \"shell\"   [runners.custom_build_dir]     enabled = true   [runners.cache]     [runners.cache.s3]     [runners.cache.gcs]     [runners.cache.azure]<\/code><\/pre>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<pre><code class=\"yaml\">[[runners]]  name = \"FastlaneProject\/create_archive\/1\"   limit = 1   url = \"https:\/\/gitlab.com\"   id = 36354822   token = \"XXXXXXXXXXXXX\"   token_obtained_at = 2024-05-07T14:48:23Z   token_expires_at = 0001-01-01T00:00:00Z   executor = \"shell\"   builds_dir = \"\/Users\/CICDUser\/YYYYYY\/ZZZZZZZ\/cicd\/builds\"   cache_dir = \"\/Users\/CICDUser\/YYYYYY\/ZZZZZZZ\/cicd\/cache\"   [runners.custom_build_dir]     enabled = true<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0441\u0442\u043e\u0438\u0442 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\"><strong>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">concurrent = 1<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">limit = 1<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0440\u0430 \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0437\u0430\u0434\u0430\u0447<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">builds_dir = &#171;\/Users\/CICDUser\/YYYYYY\/ZZZZZZZ\/cicd\/builds&#187;<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043f\u0443\u0442\u044c, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u0440\u0430\u043d\u043d\u0435\u0440\u0430. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0435\u043c\u0443 \u043f\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f cicd &#8212; \u044d\u0442\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 <strong>CI\/CD<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">cache_dir = &#171;\/Users\/CICDUser\/YYYYYY\/ZZZZZZZ\/cicd\/cache&#187;<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043a\u044d\u0448 \u0440\u0430\u043d\u043d\u0435\u0440\u0430<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>5. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Appfile<\/h4>\n<p>\u0414\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0448\u0430\u0433\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043f\u0435\u0440\u0432\u0430 \u0434\u043e\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>[CI\/CD SERVER]<\/strong>.<br \/>\u041a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>Appfile<\/strong> \u0431\u0443\u0434\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0438\u0436\u0435 \u0432 \u0441\u0435\u043a\u0446\u0438\u0438 \u201c\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 <strong>[CI\/CD SERVER]<\/strong>&#171;.<br \/>\u041d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 <strong>Appfile<\/strong> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 <strong>Secure Files<\/strong> <strong>[PROJECT repo]<\/strong><\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 [CI\/CD SERVER]<\/h3>\n<h4>1. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Gitlab \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u043a\u0435 (\u0441\u0435\u0440\u0432\u0435\u0440\u0435)<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 <a href=\"https:\/\/docs.gitlab.com\/runner\/configuration\/macos_setup.html\" rel=\"noopener noreferrer nofollow\"><u>GitLab<\/u><\/a>. \u041f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0443\u044e \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 \u043d\u0430 <code>bash<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430 <code>zsh<\/code><strong> GitLab <\/strong>\u043d\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442<strong>. <\/strong>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 <code>shell<\/code>:<\/p>\n<pre><code class=\"bash\">echo $SHELL<\/code><\/pre>\n<p>E\u0441\u043b\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0442\u043b\u0438\u0447\u0435\u043d \u043e\u0442 <strong>\/bin\/bash<\/strong>, \u0442\u043e \u043c\u0435\u043d\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b:<\/p>\n<pre><code class=\"bash\">chsh -s \/bin\/bash<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 <strong>brew<\/strong> \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u0442\u043e \u0441\u0442\u0430\u0432\u0438\u043c:<\/p>\n<pre><code class=\"bash\">\/bin\/bash -c \"$(curl \"https:\/\/raw.githubusercontent.com\/Homebrew\/install\/HEAD\/install.sh\")\"<\/code><\/pre>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c rbenv \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0448\u0430\u0433\u0430\u043c, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043a \u0440\u0435\u043f\u043e: <a href=\"https:\/\/github.com\/rbenv\/rbenv\" rel=\"noopener noreferrer nofollow\"><u>\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 rbenv<br \/><\/u><\/a>\u0421\u0442\u0430\u0432\u0438\u043c <strong>rbenv<\/strong>, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e <strong>ruby<\/strong>:<\/p>\n<pre><code class=\"bash\">brew install rbenv gitlab-runner  brew services start gitlab-runner<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c <strong>rbenv<\/strong> \u0432 \u043f\u0440\u043e\u0444\u0430\u0439\u043b:<\/p>\n<pre><code class=\"bash\">echo 'if which rbenv > \/dev\/null; then eval \"$(rbenv init -)\"; fi' >> ~\/.bash_profile source ~\/.bash_profile<\/code><\/pre>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u0438 <strong>ruby<\/strong>:<\/p>\n<pre><code class=\"bash\">rbenv install -l <\/code><\/pre>\n<p>\u0418 \u0441\u0442\u0430\u0432\u0438\u043c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e <strong>ruby<\/strong>, \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 &#8212; \u044d\u0442\u043e \u0432\u0435\u0440\u0441\u0438\u044f 3.3.1:<\/p>\n<pre><code class=\"bash\">rbenv install 3.3.1 rbenv global 3.3.1 <\/code><\/pre>\n<p>\u041a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c <strong>.bashrc<\/strong> \u0444\u0430\u0439\u043b, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0432 \u043d\u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438. \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0443 <strong>CICDUser<\/strong> \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c:<\/p>\n<pre><code class=\"bash\">export PATH=\"\/bin:\/usr\/bin:\/usr\/local\/bin\" export LANG=en_US.UTF-8 export LANGUAGE=en_US.UTF-8 export LC_ALL=en_US.UTF-8 eval \"$(rbenv init -)\"   PATH=$PATH:\/Users\/CICDUser\/bin:\/usr\/local\/homebrew PATH=$PATH:\/Users\/CICDUser\/.rbenv\/shims\/ export PATH<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d <strong>Xcode<\/strong> &#8212; \u0441\u0442\u0430\u0432\u0438\u043c \u0435\u0433\u043e.<br \/>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <strong>JSON<\/strong> \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0441\u0442\u0430\u0432\u0438\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u0443 <strong>jq <\/strong><a href=\"https:\/\/github.com\/jqlang\/jq\/wiki\/Installation\" rel=\"noopener noreferrer nofollow\"><u>(\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 jq)<\/u><\/a>.<\/p>\n<pre><code class=\"bash\">brew install jq<\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 gitlab runner \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043f\u0443\u043d\u043a\u0442\u0443 3 \u0438\u0437 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 <strong>[PROJECT repo]<\/strong><\/p>\n<h4>2. Fastlane<\/h4>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <strong>fastlane<\/strong>:<\/p>\n<pre><code class=\"bash\">brew install fastlane<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u043f\u0443\u0442\u0438, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432\u0441\u044f \u043c\u0430\u0433\u0438\u044f <strong>CI\/CD<\/strong> &#8212; \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f <strong>[CI\/CD repo]<\/strong>. \u041c\u044b \u0435\u0433\u043e \u0443\u0436\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 &#8212; \u044d\u0442\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0430\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f \u043a\u044d\u0448\u0430 \u0438 \u0431\u0438\u043b\u0434\u0430 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432:<br \/><strong>&#171;\/Users\/XXXXXX\/YYYYYY\/ZZZZZZZ\/cicd\/&#187;<\/strong>. \u0422\u0443\u0442 \u0434\u0435\u043b\u0430\u0435\u043c \u043a\u043b\u043e\u043d \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<strong> [CI\/CD repo]<\/strong> \u0438 \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c fastlane <a href=\"https:\/\/github.com\/boytpcm123\/gitlab-ci-fastlane\" rel=\"noopener noreferrer nofollow\"><u>(\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 fastlane)<\/u><\/a>. <\/p>\n<pre><code class=\"bash\">cd \/Users\/CICDUser\/YYYYYY\/ZZZZZZZ\/cicd\/ git clone https:\/\/gitlab.com\/AAAAAA\/BBBBBB.git ... fastlane init ...<\/code><\/pre>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0435\u0442 \u0435\u0449\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"bash\">[\u2714] ? [\u2714] Looking for iOS and Android projects in current directory... [13:51:43]: Created new folder '.\/fastlane'. [13:51:43]: No iOS or Android projects were found in directory '\/Users\/WWWW\/XXXX\/YYYY\/ZZZZ' [13:51:43]: Make sure to `cd` into the directory containing your iOS or Android app [13:51:43]: Alternatively, would you like to manually setup a fastlane config in the current directory instead? (y\/n)<\/code><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0448\u0430\u0435\u043c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b:<\/p>\n<pre><code class=\"bash\">MBP-Workstation:ZZZZ cicd$ ls -la total 24 drwxr-xr-x@  5 CICDUser  staff   160 May 14 13:51 . drwxr-xr-x@ 17 CICDUser  staff   544 May 14 13:51 .. -rw-r--r--@  1 CICDUser  staff    46 May 14 13:51 Gemfile -rw-r--r--@  1 CICDUser  staff  5992 May 14 13:51 Gemfile.lock drwxr-xr-x@  4 CICDUser  staff   128 May 14 13:51 fastlane MBP-Workstation:ZZZZ cicd$ ls -la fastlane\/ total 16 drwxr-xr-x@ 4 CICDUser  staff  128 May 14 13:51 . drwxr-xr-x@ 5 CICDUser  staff  160 May 14 13:51 .. -rw-r--r--@ 1 CICDUser  staff  242 May 14 13:51 Appfile -rw-r--r--@ 1 CICDUser  staff  598 May 14 13:51 Fastfile<\/code><\/pre>\n<h3>GEMFILE<\/h3>\n<p>\u0421\u0442\u0430\u0432\u0438\u043c<strong> ruby gems<\/strong> \u0438 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0438\u043c <strong>dotenv<\/strong> <a href=\"https:\/\/github.com\/bkeepers\/dotenv\" rel=\"noopener noreferrer nofollow\"><u>(\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 dotenv)<\/u><\/a>. \u042d\u0442\u043e \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442 \u043d\u0430\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 <strong>fastlane<\/strong>. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c <strong>Gemfile<\/strong> \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code class=\"bash\">gem \"dotenv\" gem \"fastlane\"<\/code><\/pre>\n<p>\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">gem install bundler gem install dotenv<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c:<\/p>\n<pre><code class=\"bash\">bundle install Bundle complete! 3 Gemfile dependencies, 92 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.<\/code><\/pre>\n<p>\u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b <strong>fastlane<\/strong> \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0441 <strong>Firebase<\/strong> \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">fastlane add_plugin firebase_app_distribution<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <strong>Firebase CLI<\/strong><br \/>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0442\u044f\u043d\u0443\u043b\u0441\u044f \u043d\u0443\u0436\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 &#8212; \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c <strong>Firebase CLI<\/strong> \u0438 \u0437\u0430\u043b\u043e\u0433\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442:<\/p>\n<pre><code class=\"bash\">curl -sL https:\/\/firebase.tools | bash firebase login<\/code><\/pre>\n<h3>Appfile<\/h3>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u043d \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<br \/>\u0414\u0435\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e \u043f\u043e \u043f\u043e\u043b\u044f\u043c Appfile \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0442\u0443\u0442: <a href=\"https:\/\/docs.fastlane.tools\/advanced\/Appfile\/#appfile\" rel=\"noopener noreferrer nofollow\"><u>\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e Appfile<\/u><\/a>. <a href=\"https:\/\/docs.fastlane.tools\/advanced\/Appfile\/#appfile\" rel=\"noopener noreferrer nofollow\"><u><br \/><\/u><\/a><u><br \/><\/u>\u0414\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c\u0441\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0433\u043e \u0442\u0440\u0435\u0445 \u043f\u043e\u043b\u0435\u0439: <strong>app_identifier<\/strong>, <strong>app_id<\/strong>, <strong>team_id<\/strong>, <strong>itc_team_id<\/strong>. \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f &#8212; \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u043c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043a\u0430\u043a Secure File \u0432<strong> [PROJECT repo]: <\/strong>&#171;<strong>SETTINGS<\/strong>&#187; \u2192 &#171;<strong>CI\/CD<\/strong>&#187; \u2192 &#171;<strong>Secure Files<\/strong>&#187; \u2192 &#171;<strong>Expand<\/strong>&#187; \u2192 &#171;<strong>Upload File<\/strong>&#171;.<br \/>\u041f\u043e \u0438\u0442\u043e\u0433\u0443, Appfile \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u0432 Gitlab \u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <strong>CI\/CD<\/strong> \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ab4\/cc6\/1a2\/ab4cc61a258471aebec81942bf5ef955.png\" alt=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Appfile \u043a\u0430\u043a Secure File \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\" title=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Appfile \u043a\u0430\u043a Secure File \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\" width=\"1600\" height=\"330\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ab4\/cc6\/1a2\/ab4cc61a258471aebec81942bf5ef955.png\"\/><\/p>\n<div><figcaption>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Appfile \u043a\u0430\u043a Secure File \u0432 \u043f\u0440\u043e\u0435\u043a\u0442<\/figcaption><\/div>\n<\/figure>\n<h3>Fastfile<\/h3>\n<p>\u0421\u0435\u0440\u0434\u0446\u0435\u043c \u043d\u0430\u0448\u0435\u0433\u043e CI\/CD \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Fastfile &#8212; \u0438\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b <strong>CI\/CD<\/strong>.<br \/>\u041f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 Fastfile \u043f\u043e \u043f\u0443\u0442\u0438 <strong>fastlane\/Fastfile<\/strong> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 Fastfile <\/summary>\n<div class=\"spoiler__content\">\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0444\u0430\u0439\u043b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0431\u044a\u0435\u043c\u043d\u044b\u0439, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u0438\u0437 <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\/-\/blob\/main\/fastlane\/Fastfile\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/a>. <br \/>\u0417\u0434\u0435\u0441\u044c \u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"ruby\"># This file contains the fastlane.tools configuration # You can find the documentation at https:\/\/docs.fastlane.tools # # For a list of all available actions, check out # #     https:\/\/docs.fastlane.tools\/actions # # For a list of all available plugins, check out # #     https:\/\/docs.fastlane.tools\/plugins\/available-plugins #  # Uncomment the line if you want fastlane to automatically update itself # update_fastlane require 'fileutils'  default_platform(:ios) xcode_select \"\/Applications\/Xcode.app\"  platform :ios do   desc \"Build step\"   desc \"### Example:\"   desc \"```\\n[bundler exec] fastlane build_before_tests [--env FASTLANE_ENVIRONMENT]\\n```\"   lane :build_before_tests do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['CICD_CLONE_PATH', 'BUILD_SCHEME', 'CICD_LOGS_HOME', 'CICD_DERIVED_DATA_PATH', 'DESTINATION', 'CICD_BUILD_RESULTS_PATH'])      # Perform linting     perform_linting()      # Define project location based on Xcode project or workspace     project_location = ENV['CICD_CLONE_PATH'] + (ENV['XCWORKSPACE'].empty? ? ENV['XCODEPROJ'] : ENV['XCWORKSPACE'])     puts \"Project location:\\t #{ project_location}\"      # Prepare build with fastlane scan     scan(       project: ENV['XCWORKSPACE'].empty? ? project_location : nil,       workspace: ENV['XCWORKSPACE'].empty? ? nil : project_location,       scheme: ENV['BUILD_SCHEME'],       configuration: \"Release\",       buildlog_path: ENV['CICD_LOGS_HOME'],       derived_data_path: ENV['CICD_DERIVED_DATA_PATH'],       destination: ENV['DESTINATION'],       code_coverage: true,       output_directory: ENV['CICD_BUILD_RESULTS_PATH'],       skip_build: false,       build_for_testing: true,       clean: false     )   end     desc \"Prepare tests for project\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane run_unit_tests [--env FASTLANE_ENVIRONMENT]\\n```\"   lane :run_unit_tests do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['CICD_CLONE_PATH', 'TEST_SCHEME', 'CICD_LOGS_HOME', 'CICD_DERIVED_DATA_PATH', 'DESTINATION', 'CICD_TEST_RESULTS_PATH'])      # Define project location based on Xcode project or workspace     project_location = ENV['CICD_CLONE_PATH'] + (ENV['XCWORKSPACE'].empty? ? ENV['XCODEPROJ'] : ENV['XCWORKSPACE'])     puts \"Project location:\\t #{ project_location}\"      # Perform test with fastlane scan     scan(       project: ENV['XCWORKSPACE'].empty? ? project_location : nil,       workspace: ENV['XCWORKSPACE'].empty? ? nil : project_location,       scheme: ENV['TEST_SCHEME'],       configuration: \"Debug\",       buildlog_path: ENV['CICD_LOGS_HOME'],       derived_data_path: ENV['CICD_DERIVED_DATA_PATH'],       destination: ENV['DESTINATION'],        test_without_building: false,       output_directory: ENV['CICD_TEST_RESULTS_PATH'],       clean: false,       include_simulator_logs: false      )   end     desc \"Prepare IPA archive\"   desc \"The lane to run by developers or CI\/CD\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane build_archive type:\\\"development\\\" export_method:\\\"development\\\" [--env FASTLANE_ENVIRONMENT]\\n```\"   desc \"```\\n[bundler exec] fastlane build_archive type:\\\"adhoc\\\" export_method:\\\"ad-hoc\\\" [--env FASTLANE_ENVIRONMENT]\\n```\"   desc \"### Options:\"   desc \" * **`type`**: must be: [\\\"appstore\\\", \\\"adhoc\\\", \\\"development\\\", \\\"enterprise\\\", \\\"developer_id\\\", \\\"mac_installer_distribution\\\", \\\"developer_id_installer\\\"]\"   desc \" * **`export_method`**: export_method must be: [\\\"app-store\\\", \\\"validation\\\", \\\"ad-hoc\\\", \\\"package\\\", \\\"enterprise\\\", \\\"development\\\", \\\"developer-id\\\", \\\"mac-application\\\"]\"   lane :build_archive do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['CICD_ARCHIVES_LOCATION', 'CICD_RELEASE_NOTES_FILE_PATH', 'CICD_CLONE_PATH', 'XCODEPROJ', 'BUILD_SCHEME', 'PROJECT_NAME', 'CICD_IPA_ARCHIVE_NAME', 'APP_BUNDLE_ID', 'APP_CERTIFICATES_STORE'])      # Prepare paths for archive and release notes     archive_location = ENV['CICD_ARCHIVES_LOCATION']     release_notes_path = ENV['CICD_RELEASE_NOTES_FILE_PATH']      if File.exist?(release_notes_path)       sh \"cat \/dev\/null > #{release_notes_path}\"     else       FileUtils.mkdir_p(archive_location)       FileUtils.touch(release_notes_path)     end       # Sync code signing     sync_code_signing(           type: options[:type],           app_identifier: ENV['APP_BUNDLE_ID'],           readonly: true,           git_url: ENV['APP_CERTIFICATES_STORE']     )          # Preparing release notes     current_branch_name = git_current_branch(ENV['CICD_CLONE_PATH'])     ticket_number = current_branch_name.match(\/(?:\\\/)([A-Z]+-\\d+)\/)[1]     prepare_release_notes(       ticket_number: \"#{ticket_number}\"     )     parsed_version, parsed_build = parse_version_and_build(\"#{release_notes_path}\")     new_build = parsed_build.to_i     new_version = parsed_version.to_i      # Incrementing build number for archive     increment_build_number(       xcodeproj: ENV['CICD_CLONE_PATH'] + ENV['XCODEPROJ'],       build_number: \"#{new_build}\"     )      # Define project location based on Xcode project or workspace     project_location = ENV['CICD_CLONE_PATH'] + (ENV['XCWORKSPACE'].empty? ? ENV['XCODEPROJ'] : ENV['XCWORKSPACE'])     puts \"Project location:\\t #{ project_location}\"           # Determine configuration     configuration = options[:type] == \"appstore\" ? \"Release\" : \"Debug\"       # Preparing ipa archive with fastlane gym     gym(       project: ENV['XCWORKSPACE'].empty? ? project_location : nil,       workspace: ENV['XCWORKSPACE'].empty? ? nil : project_location,       scheme: ENV['BUILD_SCHEME'],       configuration: configuration,       clean: true,       output_directory: archive_location,       output_name: ENV['CICD_IPA_ARCHIVE_NAME'],       export_method: options[:export_method],       skip_package_dependencies_resolution: true     )   end       desc \"Send IPA archive to Testflight\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane deploy_tf skip_submission:true [--env FASTLANE_ENVIRONMENT]\\n```\"   desc \"### Options:\"   desc \" * **`skip_submission`**: skip the distributing action of pilot and only upload the ipa file true|false(by default)\"   lane :deploy_tf do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['CICD_ARCHIVES_LOCATION', 'PROJECT_NAME', 'CICD_IPA_FULL_PATH', 'APP_BUNDLE_ID', 'APP_CERTIFICATES_STORE'])      # Sync code signing     sync_code_signing(       type: \"development\",       app_identifier: ENV['APP_BUNDLE_ID'],       readonly: true,       git_url: ENV['APP_CERTIFICATES_STORE']     )          # Get credentials for App Store Connect     apiKey = app_store_connect_api_key(       is_key_content_base64: true,       duration: 1200,       in_house: false # if it is enterprise or not     )          # Send .ipa archive to the Testflight silently     testflight(       app_identifier: options[:appIdentifier],       skip_waiting_for_build_processing: options[:skip_submission],       skip_submission: options[:skip_submission],       ipa: ENV['CICD_IPA_FULL_PATH'],       api_key: apiKey,       changelog: \"\"     )   end     desc \"Send Archive to Firebase\"    desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane deploy_firebase [--env FASTLANE_ENVIRONMENT]\\n```\"   desc \"### Options:\"   desc \" * **`fb_groups`**: testers groups created in firebase concole app distribution tab\"   desc \" * **`fb_release_notes`**: release notes for the specified project archive\"   lane :deploy_firebase do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['FB_APP_KEY', 'FB_TEST_GROUPS', 'CICD_RELEASE_NOTES_FILE_PATH', 'CICD_IPA_FULL_PATH'])      # Push ipa archive with specified release notes to the Firebase App Distribution with notification to the specified test groups     release = firebase_app_distribution(       app: ENV['FB_APP_KEY'],       testers: ENV['FB_TEST_GROUPS'],       release_notes_file: ENV['CICD_RELEASE_NOTES_FILE_PATH'],       ipa_path: ENV['CICD_IPA_FULL_PATH']     )   end     desc \"Get certificates for specified project\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane certificates [--env FASTLANE_ENVIRONMENT]\\n```\"   lane :certificates do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['APP_BUNDLE_ID', 'APP_CERTIFICATES_STORE'])      sync_code_signing(       type: \"development\",       app_identifier: ENV['APP_BUNDLE_ID'],       force_for_new_devices: true,       git_url: ENV['APP_CERTIFICATES_STORE'],       readonly: true     )     sync_code_signing(       type: \"adhoc\",       app_identifier: ENV['APP_BUNDLE_ID'],       force_for_new_devices: true,       git_url: ENV['APP_CERTIFICATES_STORE'],       readonly: true     )     sync_code_signing(       type: \"appstore\",       app_identifier: ENV['APP_BUNDLE_ID'],       git_url: ENV['APP_CERTIFICATES_STORE'],       readonly: true     )   end     desc \"Generate new certificates for specified project\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane generate_new_certificates [--env FASTLANE_ENVIRONMENT]\\n```\"   lane :generate_new_certificates do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['APP_BUNDLE_ID', 'APP_CERTIFICATES_STORE'])      sync_code_signing(       type: \"development\",       app_identifier: ENV['APP_BUNDLE_ID'],       git_url: ENV['APP_CERTIFICATES_STORE'],       force_for_new_devices: true,       readonly: false     )     sync_code_signing(       type: \"adhoc\",       app_identifier: ENV['APP_BUNDLE_ID'],       git_url: ENV['APP_CERTIFICATES_STORE'],       force_for_new_devices: true,       readonly: false     )     sync_code_signing(       type: \"appstore\",       app_identifier: ENV['APP_BUNDLE_ID'],       git_url: ENV['APP_CERTIFICATES_STORE'],       force_for_new_devices: true,       readonly: false     )     end     desc \"Lint step\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane perform_linting [--env FASTLANE_ENVIRONMENT]\\n```\"   lane :perform_linting do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['CICD_CLONE_PATH', 'CICD_LINTER_LOCK_FILE', 'CICD_LINTER_RESULTS_FILE'])        # Frist three variables - just for readability     cicd_clone_path = ENV['CICD_CLONE_PATH']     linter_lock_file = ENV['CICD_LINTER_LOCK_FILE']     linter_result_file = ENV['CICD_LINTER_RESULTS_FILE']     previous_merge_commit = git_last_merge_commit(cicd_clone_path)     current_commit = git_current_commit(cicd_clone_path)     current_branch_name = git_current_branch(cicd_clone_path)      puts \"Previous merge commit hash:\\t #{previous_merge_commit}\"     puts \"Last commit hash:\\t\\t #{current_commit}\"     puts \"Swiftlint lock file:\\t  #{linter_lock_file}\"          # Reading installed lock or prepareing linter internal files      linter_commit = read_linter_commit(linter_lock_file)      if linter_commit == current_commit       puts \"Linting was already performed for the current commit. Skipping lint steps.\"     else       files_to_lint = git_diff_swift_files(previous_merge_commit, current_commit, cicd_clone_path)       puts \"Files to lint: #{files_to_lint}\"        if files_to_lint.empty?         puts \"No swift files changed. Skipping lint\"       else          lint_swift_files(files_to_lint, linter_result_file, cicd_clone_path, current_branch_name)       end        File.open(linter_lock_file, \"w\") { |file| file.write(current_commit) }     end   end       desc \"Send message to Gitlab\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane send_message commit_ref:\\\"BRANCH_NAME\\\" file_to_comment:\\\"FILEPATH\\\" line_to_comment:\\\"\\\"  gitlab_message:\\\"MESSAGE_TO_POST\\\" [--env FASTLANE_ENVIRONMENT]\\n```\"   desc \"### Options:\"   desc \"* **`commit_ref`**: current brnach name. This will be used to detect opened MR\"   desc \"* **`gitlab_message`**: message to post in the new MR thread\"   desc \"* **`file_to_comment`**: file to add comment to. Note that all subpaths of the project should be included, providing just file name is not sufficient.\"   desc \"* **`line_to_comment`**: line in the file that should be comented\"   lane :send_message do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['GIT_PROJECT_ID', 'CI_API_TOKEN'])      merge_request_iid = get_merge_request_iid(options[:commit_ref])     if merge_request_iid       json_data = prepare_json_data(options, merge_request_iid)       post_comment_to_merge_request(options, merge_request_iid, json_data)     else       UI.error(\"Failed to retrieve merge request IID\")     end   end     desc \"Get project information from JIRA\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane get_jira_info ticket_number:\\\"TICKET_NUMBER\\\" [--env FASTLANE_ENVIRONMENT]\\n```\"   desc \"### Options:\"   desc \" * **`ticket_number`**: ticket number usually corresponds to branch_name in project\"   lane :get_jira_info do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['CICD_RELEASE_NOTES_FILE_PATH', 'JIRA_API_KEY','JIRA_HOST_NAME', 'JIRA_TICKET_URL'])      # Gather ticket related data     ticket_summary = execute_jira_api_get_request(\"\/issue\/#{options[:ticket_number]}\/?fields=summary\")     if ticket_summary.include?('errorMessages') || ticket_summary.include?('Not Found')       puts \"Couldn't find relevant ticket information in JIRA. Skipping all steps.\"     else       ticket_link=\"#{ENV['JIRA_TICKET_URL']}\/#{options[:ticket_number]}\"       ticket_notes=\"Ticket:\\t#{options[:ticket_number]}\\t#{ticket_link}\\n\"        # Gather Epic related information       editmeta_response = execute_jira_api_get_request(\"\/issue\/#{options[:ticket_number]}\/editmeta\")       epic_custom_field_id = `echo '#{editmeta_response}' | jq -r '.fields | to_entries[] | select(.value.name == \"Epic Link\") | .value.fieldId' | tr -d '\\n'`       epic_ticket_response = execute_jira_api_get_request(\"\/issue\/#{options[:ticket_number]}?fields=#{epic_custom_field_id}\")       epic_ticket_number = `echo '#{epic_ticket_response}' | jq -r '.fields.#{epic_custom_field_id}' | tr -d '\\n'`       if epic_ticket_number &amp;&amp; !epic_ticket_number.strip.empty? &amp;&amp; epic_ticket_number != \"null\"         epic_ticket_link=\"#{ENV['JIRA_TICKET_URL']}\/#{epic_ticket_number}\"         ticket_notes+=\"Epic:\\t#{epic_ticket_number}\\t#{epic_ticket_link}\\n\"       end                # Write ticket information to release notes file       File.open(ENV['CICD_RELEASE_NOTES_FILE_PATH'], \"a\") { |file| file.puts ticket_notes }     end   end      desc \"Saves version and build info to the release notes\"   desc \"### Examples:\"   desc \"```\\n[bundler exec] fastlane prepare_release_notes ticket_number:\\\"TICKET_NUMBER\\\"  [--env FASTLANE_ENVIRONMENT]\\n```\"   desc \"### Options:\"   desc \" * **`ticket_number`**: ticket number usually corresponds to branch_name in project\"   lane :prepare_release_notes do |options|     # Checks if all ENV variables were defined in the .env.PROJECT_NAME file     verify_env_variables(['CICD_CLONE_PATH', 'XCODEPROJ'])      # Gathering current version and build of the project     project_location = ENV['CICD_CLONE_PATH'] + ENV['XCODEPROJ']     version_number = get_version_number(xcodeproj: project_location)     build_number = latest_testflight_build_number()     puts \"Local Version Number:\\t\\t#{version_number}\"     puts \"Current Testflight Build Number:\\t#{build_number}\"      # Adding ticket relevant information to the release notes     if options[:ticket_number]       ticket_number = options[:ticket_number]&amp;.upcase       puts \"Ticket number: #{ticket_number}\"       get_jira_info(ticket_number: ticket_number)     end      # Adding version info to the release notes     build_number += 1     new_build_info = \"Version and build: #{version_number}.#{build_number}\"     File.open(ENV['CICD_RELEASE_NOTES_FILE_PATH'], \"a\") do |file|       file.puts \"\" if file.size > 0       file.puts new_build_info     end   end    # Methods    # \"Method to get last merge commit\"   def git_last_merge_commit(clone_path)     `cd #{clone_path} &amp;&amp; git log --merges --oneline --format=\"%H\" | head -n1 | tr -d '\\n'`   end    # \"Method to get current commit\"   def git_current_commit(clone_path)     `cd #{clone_path} &amp;&amp; git rev-parse HEAD | tr -d '\\n'`   end    # \"Method to get current branch\"   def git_current_branch(clone_path)     `cd #{clone_path} &amp;&amp; git branch --show-current | tr -d '\\n'`   end    # \"Method to get changed files\"   def git_diff_swift_files(previous_commit, current_commit, clone_path)   `cd #{clone_path} &amp;&amp; git diff #{previous_commit} #{current_commit} --name-only | grep .swift`.split(\"\\n\")   end    # \"Method to read current lock or create linter lock and result files if no lock deteted\"   desc \"this prevents on running linter on already processed iteration of pipeline\"   def read_linter_commit(lock_file)     if File.exist?(lock_file)       File.read(lock_file).strip     else       FileUtils.mkdir_p(File.dirname(lock_file))       FileUtils.touch(lock_file)       FileUtils.touch(ENV['CICD_LINTER_RESULTS_FILE'])       nil     end   end    # \"Method to lint specified file\"   def lint_swift_files(files_to_lint, result_file, clone_path, current_branch_name)     files_to_lint.each do |file|       swiftlint(         mode: :lint,         output_file: result_file,         config_file: \"#{clone_path}.swiftlint.yml\",         files: [\"#{clone_path}#{file}\"],         raise_if_swiftlint_error: false,         ignore_exit_status: true       )        parse_linter_results(ENV['CICD_LINTER_RESULTS_FILE'], file, current_branch_name)     end   end    # \"Method to parse swiftlint result file\"   def parse_linter_results(result_file, filename, current_branch_name)     File.open(result_file, \"r\") do |file|       file.each_line do |line|         parsed_data = parse_line(line.chomp)         if parsed_data           prepared_string = \"**`#{filename}`**  \\nSwiftlint #{parsed_data[:issue_level]} at line `#{parsed_data[:line_number]}`  \\nlinter rule violated: `#{parsed_data[:rule_name]}`  \\n#{parsed_data[:issue_long_description]}\"           send_message(             commit_ref: \"#{current_branch_name}\",             gitlab_message: \"#{prepared_string}\",             file_to_comment: \"#{filename}\",             line_to_comment: parsed_data[:line_number]           )         else           puts \"Failed to parse line.\"         end       end     end   end    # \"Method to parse swiftlint result line\"   def parse_line(line)     pattern = \/^(.*\\\/)*(.+):(\\d+):(\\d+): (\\w+): (.+): (.+) \\((\\w+)\\)$\/     match = line.match(pattern)      if match       full_filename = line[\"#{ENV['CICD_CLONE_PATH']}\".length..-1].split(':')[0]       puts full_filename       filename = full_filename.sub(\/^#{Regexp.escape(\"#{ENV['CICD_CLONE_PATH']}\")}\/, '')       line_number = match[3]       column_number = match[4]       issue_level = match[5]       issue_short_description = match[6]       issue_long_description = match[7]       rule_name = match[8]        return {         filename: filename,         line_number: line_number.to_i,         column_number: column_number.to_i,         issue_level: issue_level,         issue_short_description: issue_short_description,         issue_long_description: issue_long_description,         rule_name: rule_name       }     else       return nil     end   end    # \"Method to parse release notes\"   def parse_version_and_build(file_path)     version_line = File.readlines(file_path).find { |line| line.start_with?('Version and build:') }     if version_line       version_build = version_line.split(':').last.strip       version, build = version_build.split('.').first(2).join('.'), version_build.split('.').last       return version, build     else       put \"Version line not found in file\"     end   end    # \"Method to get MR id related to the branch\"   def get_merge_request_iid(commit_ref)     response = execute_gitlab_api_get_request(\"\/merge_requests?scope=all&amp;state=opened&amp;source_branch=#{commit_ref}\")     merge_request_iid = JSON.parse(response).first['iid'] if response &amp;&amp; !response.empty?     merge_request_iid   end    #\"Method to prepare data for MR comment in Gitlab\"   def prepare_json_data(options, merge_request_iid)     merge_request_info = execute_gitlab_api_get_request(\"\/projects\/#{ENV['GIT_PROJECT_ID']}\/merge_requests\/#{merge_request_iid}\")     json_data = JSON.parse(merge_request_info)     diff_refs = json_data['diff_refs']     base_sha = diff_refs['base_sha']     start_sha = diff_refs['start_sha']     head_sha = diff_refs['head_sha']      characters_to_escape = ['\"', \"'\", '\\\\', '$', '(', ')', '\\\\\\\\']     escaped_gitlab_message = options[:gitlab_message].gsub(\/(#{characters_to_escape.map { |c| Regexp.escape(c) }.join('|')})\/, '\\\\\\\\\\1').gsub(\"\\n\", \"\\\\n\")     escaped_gitlab_filepath = options[:file_to_comment].gsub(\/(#{characters_to_escape.map { |c| Regexp.escape(c) }.join('|')})\/, '\\\\\\\\\\1')      \"{\\\"body\\\": \\\"#{escaped_gitlab_message}\\\", \\\"position\\\": {\\\"base_sha\\\":\\\"#{base_sha}\\\", \\\"start_sha\\\":\\\"#{start_sha}\\\", \\\"head_sha\\\": \\\"#{head_sha}\\\", \\\"new_path\\\": \\\"#{escaped_gitlab_filepath}\\\", \\\"position_type\\\": \\\"text\\\", \\\"new_line\\\": #{options[:line_to_comment]}}}\"   end    # \"Method to send comment to Gitlab MR\"   def post_comment_to_merge_request(options, merge_request_iid, json_data)     response = execute_gitlab_api_post_request(\"\/projects\/#{ENV['GIT_PROJECT_ID']}\/merge_requests\/#{merge_request_iid}\/discussions?body=comment\", json_data)     status_code = response.strip.to_i     if (200..299).include?(status_code)       UI.success(\"Diff comment posted successfully\")     else       UI.error(\"Failed to apply comment to a code block. Status code: #{status_code}\")       UI.message(\"Trying to send a simple note to...\")       note_comment_response = execute_gitlab_api_post_request(\"\/projects\/#{ENV['GIT_PROJECT_ID']}\/merge_requests\/#{merge_request_iid}\/notes\", json_data)       note_comment_status_code = note_comment_response.strip.to_i       UI.error(\"Issue with sending messages to the MR request. Status code: #{note_comment_status_code}\") unless (200..299).include?(note_comment_status_code)     end   end    # \"Method to execute GET request with Gitlab API\"   def execute_gitlab_api_get_request(endpoint)     url = \"#{ENV['FASTLANE_GITLAB_API_URL']}#{endpoint}\"     `curl -s --request GET --header 'PRIVATE-TOKEN: #{ENV['CI_API_TOKEN']}' '#{url}'`   end    # \"Method to execute POST request with Gitlab API\"   def execute_gitlab_api_post_request(endpoint, json_data)     url = \"#{ENV['FASTLANE_GITLAB_API_URL']}#{endpoint}\"     `curl -s -o \/dev\/null --request POST --header \"PRIVATE-TOKEN: #{ENV['CI_API_TOKEN']}\" --header \"Content-Type: application\/json\" --data '#{json_data}' -w \"%{http_code}\\n\" '#{url}'`   end     # \"Method to execute GET request with JIRA API\"   def execute_jira_api_get_request(endpoint)     url = \"#{ENV['JIRA_HOST_NAME']}#{endpoint}\"     `curl -s --header 'Authorization: Bearer #{ENV['JIRA_API_KEY']}' '#{url}'`   end    # \"Method to check if ENV variable was defined\"   def verify_env_variables(variables)     variables.each do |var|       unless ENV[var]         puts \"Environment variable #{var} is not defined.\"         error_message = \"Please make sure that #{var} was properly defined in your environment.\"         UI.user_error!(error_message)       end     end   end end  <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 <strong>Fastfile<\/strong> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b <strong>lane<\/strong> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0430\u0439\u043f\u043b\u0430\u043d\u043e\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u043e \u043d\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u0444\u0430\u0439\u043b\u0430 \u0441\u043e\u043f\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e <strong>lane<\/strong> \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b, \u0441\u043f\u043e\u0441\u043e\u0431 \u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e \u0432\u0441\u0435\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439\u00a0 \u043c\u043e\u0436\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0432 <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\/-\/blob\/main\/fastlane\/README.md\" rel=\"noopener noreferrer nofollow\"><strong>README.md<\/strong><\/a> \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <strong>fastlane<\/strong>.<br \/>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <strong>ENV[&#8216;XXXXX&#8217;] <\/strong>&#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0432 <strong>env<\/strong> \u0444\u0430\u0439\u043b\u0435 \u043f\u043e \u043f\u0443\u0442\u0438 <strong>fastlane\/.env.YYYYYYYYY<\/strong>, \u0433\u0434\u0435\u00a0 <strong>YYYYYYYYY<\/strong> = <strong>[&#8216;default&#8217;,&#8217;PROJECT_NAME&#8217;]<\/strong>. <br \/><strong>PROJECT_NAME<\/strong> &#8212; \u0431\u0435\u0440\u0435\u0442\u0441\u044f \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 CI\/CD <strong>[PROJECT repo]<\/strong>, <strong>default<\/strong> &#8212; <strong>env<\/strong> \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<br \/><strong>options[:file_to_comment] <\/strong>&#8212; \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 <strong>lane<\/strong> \u0438\u0437\u0432\u043d\u0435<br \/>\u0412\u0441\u0435 <strong>lane<\/strong> \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u044b \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c <strong>env<\/strong>, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"bash\">bundler exec fastlane iOS build_before_tests --env YourProject # YourProject - \u0438\u043c\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0435\u043c\u0443 \u0437\u0430\u0432\u0435\u0434\u0435\u043d \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0443\u044e\u0449\u0438\u0439 env .env.YourProject<\/code><\/pre>\n<h4>3. \u0417\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0435 env \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u00a0<\/h4>\n<h3>fastlane\/.env.default\u00a0<\/h3>\n<p><strong>.env.default <\/strong>&#8212; \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 <strong>env<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <strong>Fastlane<\/strong>, \u0435\u0441\u043b\u0438 \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f <strong>env<\/strong>. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u043b <strong>.env.default<\/strong>, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0435\u0433\u043e <strong>CI\/CD<\/strong>:<\/p>\n<pre><code class=\"bash\">MATCH_PASSWORD=\"XXXXXXXXXXXX\" MATCH_KEYCHAIN_PASSWORD=\"YYYYYYYYYY\"  CICD_HOME_DIR=\"\/Users\/CICDUser\/YYYYYY\/ZZZZZZ\/cicd\/builds\"  DESTINATION=\"platform=iOS Simulator,name=iPhone 15,OS=17.2\"  APP_STORE_CONNECT_API_KEY_KEY_ID=\"XXXXXXXX\" APP_STORE_CONNECT_API_KEY_ISSUER_ID=\"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\" APP_STORE_CONNECT_API_KEY_KEY=\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"  # Fastlane env FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT=15 FASTLANE_XCODEBUILD_SETTINGS_RETRIES=6 FASTLANE_GITLAB_API_URL=\"https:\/\/gitlab.com\/api\/v4\"<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\"><strong>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">MATCH_PASSWORD<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0430\u0440\u043e\u043b\u044c \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">MATCH_KEYCHAIN_PASSWORD<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0430\u0440\u043e\u043b\u044c \u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 keychain<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CICD_HOME_DIR<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0443\u0442\u044c, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0440\u0430\u043d\u043d\u0435\u0440\u044b. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043a\u043e\u043b\u043b\u0438\u0437\u0438\u044f. \u041f\u043e\u0447\u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u043a\u0430\u043a <strong>CICD_HOME_DIR<\/strong>, \u0430 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0431\u0438\u043b\u0434\u043e\u0432 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432. \u0412\u0441\u0435 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0445\u043e\u0442\u044c \u0441\u0435\u0440\u0434\u0446\u0435\u043c <strong>CI\/CD<\/strong> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <strong>Fastfile<\/strong>, \u043e\u0434\u043d\u0430\u043a\u043e \u0435\u0433\u043e \u0440\u0443\u043a\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0440\u0430\u043d\u043d\u0435\u0440\u044b.<\/p>\n<p align=\"left\">\u0412\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0443\u0442\u044c, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u043d \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0435\u0439 \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432.<\/p>\n<p align=\"left\">\u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043d\u0438\u0442\u044c, \u043d\u043e \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0441\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">DESTINATION<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b iOS \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u0423\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">APP_STORE_CONNECT_API_KEY_KEY_ID<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>API KEY ID<\/strong>. \u0414\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 <strong>App Store Connect<\/strong> \u0441\u0435\u043a\u0446\u0438\u044f <strong>&#171;Users and Access<\/strong>&#187; , \u0442\u0430\u0431 &#171;<strong>Integrations<\/strong>&#187; \u043f\u043e\u0434\u0442\u0430\u0431 &#171;<strong>App Store Connect API<\/strong>&#171;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">APP_STORE_CONNECT_API_KEY_ISSUER_ID<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>API KEY ISSUER ID<\/strong>. \u0414\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 <strong>App Store Connect<\/strong> \u0441\u0435\u043a\u0446\u0438\u044f &#171;<strong>Users and Access<\/strong>&#171;, \u0442\u0430\u0431 &#171;<strong>Integrations<\/strong>&#187; \u043f\u043e\u0434\u0442\u0430\u0431 &#171;<strong>App Store Connect API<\/strong>&#171;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">APP_STORE_CONNECT_API_KEY_KEY<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>API KEY<\/strong>. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430\u0434 \u043a\u043b\u044e\u0447\u043e\u043c, \u0441\u043a\u0430\u0447\u0435\u043d\u043d\u044b\u043c \u0438\u0437 <strong>App Store<\/strong>:<\/p>\n<p align=\"left\"><code>'openssl base64 &lt; path\/to\/key.p8 | tr -d '\\n' | pbcopy'<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u0430\u0439\u043c\u0430\u0443\u0442 \u0434\u043b\u044f \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0431\u0438\u043b\u0434\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">FASTLANE_XCODEBUILD_SETTINGS_RETRIES<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0431\u0438\u043b\u0434\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">FASTLANE_GITLAB_API_URL<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>Gitlab\u00a0 API<\/strong><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h3>fastlane\/.env.PROJECT_NAME<\/h3>\n<p><strong>.env.PROJECT_NAME<\/strong> &#8212; \u044d\u0442\u043e <strong>env<\/strong> \u0444\u0430\u0439\u043b \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432 \u043d\u0435\u043c \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b <strong>CI\/CD<\/strong>.<\/p>\n<pre><code class=\"bash\"># Certificate store APP_CERTIFICATES_STORE=\"https:\/\/gitlab.com\/XXXXXX\/YYYYYY.git\" APP_BUNDLE_ID=\"XXXXXXXXXXXXXXXXXXXXXXXXX\"  # Xcode Project specific variables XCODEPROJ=\"XXXXXXXXXX.xcodeproj\" XCWORKSPACE=\"XXXXXXXXXX.xcworkspace\" BUILD_SCHEME=\"YYYYYYYYYY\" TEST_SCHEME=\"ZZZZZZZZZ\" PROJECT_NAME=\"XXXXXXXXXX\"  # Firebase variables FB_APP_KEY=\"1:XXXXXXXXXXXX:ios:YYYYYYYYYYYY\" FB_TEST_GROUPS=\"TEST_GROUP_NAME\"  # Runner folders CICD_ARTIFACTS_HOME=\"$CICD_HOME_DIR\/$PROJECT_NAME\/artifacts\" CICD_CLONE_PATH=\"$CICD_HOME_DIR\/clones\/$PROJECT_NAME\/\" CICD_LINTER_HOME=\"$CICD_ARTIFACTS_HOME\/swiftlint\" CICD_LOGS_HOME=\"$CICD_ARTIFACTS_HOME\/logs\" CICD_ARCHIVES_LOCATION=\"$CICD_ARTIFACTS_HOME\/archives\/\" CICD_RELEASE_NOTES_FILE_PATH=\"$CICD_ARCHIVES_LOCATION\/release_notes\" CICD_DERIVED_DATA_PATH=\"$CICD_ARTIFACTS_HOME\/derived_data\/\" CICD_BUILD_RESULTS_PATH=\"$CICD_ARTIFACTS_HOME\/build_results\/$(date '+%Y-%m-%d_%H:%M:%S')\/\" CICD_TEST_RESULTS_PATH=\"$CICD_ARTIFACTS_HOME\/test_results\/$(date '+%Y-%m-%d_%H:%M:%S')\/\" CICD_LINTER_RESULTS_FILE=\"$CICD_LINTER_HOME\/swiftlint_results\" CICD_LINTER_LOCK_FILE=\"$CICD_LINTER_HOME\/swiftlint.lock\" CICD_IPA_ARCHIVE_NAME=\"$PROJECT_NAME.ipa\" CICD_IPA_FULL_PATH=\"$CICD_ARCHIVES_LOCATION\/$CICD_IPA_ARCHIVE_NAME\"  # Gitlab variables GIT_PROJECT_ID=XXXXXXXX # Message Agent for GitLab (Only for Premium or Ultimate Gitlab plans) CI_API_TOKEN=\"xxxxx-xxxxxxxxxxxxxxxxxxxx\"  # JIRA variables JIRA_URL=\"https:\/\/jira.ZZZZZZ.ru\" JIRA_TICKET_URL=\"$JIRA_URL\/browse\" JIRA_HOST_NAME=\"$JIRA_URL\/rest\/api\/latest\" JIRA_SEARCH_URL=\"$JIRA_HOST_NAME\/search\" JIRA_API_KEY=\"yyyyyyyyyyyyyyyyyyyy\"<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432\u044b\u0448\u0435:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\"><strong>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">APP_CERTIFICATES_STORE<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u0433\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b. \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0437\u0430\u0432\u043e\u0434\u0438\u043b\u0441\u044f \u0432 \u0448\u0430\u0433\u0435 &#171;\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 <strong>[CERTS repo]<\/strong>&#171;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">APP_BUNDLE_ID<\/p>\n<\/td>\n<td>\n<p align=\"left\">Bundle ID \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <strong>[PROJECT repo]<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">XCODEPROJ<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f <strong>Xcodeproj<\/strong> \u0444\u0430\u0439\u043b\u0430 \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">XCWORKSPACE<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f <strong>Xcworkspace<\/strong> \u0444\u0430\u0439\u043b\u0430 \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">BUILD_SCHEME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f \u0441\u0445\u0435\u043c\u044b, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">TEST_SCHEME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f \u0441\u0445\u0435\u043c\u044b, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f <strong>Unit<\/strong> \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">PROJECT_NAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 <strong>CI\/CD<\/strong>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a <strong>env<\/strong> \u0444\u0430\u0439\u043b\u0443<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">FB_APP_KEY<\/p>\n<\/td>\n<td>\n<p align=\"left\">A<strong>PP KEY<\/strong> \u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 Firebase. \u041c\u043e\u0436\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0438\u0437 &#171;<strong>Firebase Console<\/strong>&#187; -> &#171;<strong>Project overview<\/strong>&#187; -> &#171;<strong>Project Settings<\/strong>&#187; -> \u0441\u0435\u043a\u0446\u0438\u044f &#171;<strong>Your apps<\/strong>&#187; -> &#171;<strong>App ID<\/strong>&#171;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">FB_TEST_GROUPS<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0413\u0440\u0443\u043f\u043f\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0437\u0430\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 <strong>Firebase Console<\/strong>. \u041c\u043e\u0436\u0435\u043c \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0438\u0437\u00a0 &#171;<strong>Firebase Console<\/strong>&#187; -> <strong>Project Shortcuts<\/strong> &#171;<strong>App Distribution<\/strong>&#187; \u2192 &#171;<strong>Testers &amp; Groups<\/strong>&#187; \u2192 <strong>Tester groups<\/strong>&#171;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">GIT_PROJECT_ID<\/p>\n<\/td>\n<td>\n<p align=\"left\">ID \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 <strong>Gitlab<\/strong> \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. \u041c\u043e\u0436\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0438\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430 &#171;<strong>Settings<\/strong>&#187; -> &#171;<strong>General<\/strong>&#171;, \u0432 \u0441\u0435\u043a\u0446\u0438\u0438 &#171;<strong>Naming, topics, avatar<\/strong>&#187; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 &#171;<strong>Project ID<\/strong>&#171;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">CI_API_TOKEN<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u0430\u043d\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u0435\u043b\u0435\u043c <strong>Premium<\/strong> \u0438\u043b\u0438 <strong>Ultimate<\/strong> \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 <strong>Gitlab<\/strong>. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 &#171;<strong>Settings<\/strong>&#187; -> &#171;<strong>Access Tokens<\/strong>&#187; -> \u043d\u0430\u0436\u0430\u0442\u044c &#171;<strong>Add new token<\/strong>&#171;. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0438\u043c\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 <strong>Gitlab<\/strong> <strong>MR<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">JIRA_URL<\/p>\n<\/td>\n<td>\n<p align=\"left\">URL \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 JIRA<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">JIRA_API_KEY<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u043e\u043a\u0435\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u043f\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0434\u0442\u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a <strong>JIRA API<\/strong>. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u2192 &#171;<strong>\u041f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430<\/strong>&#187; \u2192 &#171;<strong>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d<\/strong>&#171;.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u0442\u0438\u0445 \u0434\u0432\u0443\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0441\u0447\u0438\u0442\u0430\u0435\u043c, \u0447\u0442\u043e \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 <strong>CI\/CD<\/strong> &#8212; \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043e, \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u043a\u0438\u0441\u043b\u0430\u044f \u0432\u0438\u0448\u0435\u043d\u043a\u0430 \u043d\u0430 \u0442\u043e\u0440\u0442\u0435 &#8212; \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 <strong>Discord<\/strong>.<br \/>\u041f\u043e\u0447\u0435\u043c\u0443 \u043a\u0438\u0441\u043b\u0430\u044f? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043c \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0441\u0431\u043e\u0440\u043e\u043a<\/p>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Discord<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u043d\u0430\u0448 <strong>Discord<\/strong> \u0441\u0435\u0440\u0432\u0435\u0440, \u0433\u0434\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0414\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0432\u0435\u0441\u0442\u0438 <strong>Webhook. <\/strong>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u043a \u043a\u0430\u043d\u0430\u043b\u0443.\u00a0<\/p>\n<p>\u041a\u043b\u0430\u0446\u0430\u0435\u043c &#171;<strong>Edit Channel<\/strong>&#171;<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2ab\/afc\/566\/2abafc56655bbcc6a4f82dc72565dcbb.png\" alt=\"Discord \u0441\u0435\u0440\u0432\u0435\u0440. \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u0430\u043d\u0430\u043b \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\" title=\"Discord \u0441\u0435\u0440\u0432\u0435\u0440. \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u0430\u043d\u0430\u043b \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\" width=\"536\" height=\"144\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2ab\/afc\/566\/2abafc56655bbcc6a4f82dc72565dcbb.png\"\/><\/p>\n<div><figcaption>Discord \u0441\u0435\u0440\u0432\u0435\u0440. \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u0430\u043d\u0430\u043b \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c &#171;<strong>New Webhook<\/strong>&#187; \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e <strong>URL<\/strong> \u0432 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0438\u043c\u0441\u044f \u043f\u043e\u043b\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/44c\/d1a\/24c\/44cd1a24c3ec1af6c84030c604852784.png\" alt=\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Webhook \u043d\u0430 \u043a\u0430\u043d\u0430\u043b \u0432 Discord \u0441\u0435\u0440\u0432\u0435\u0440\u0435\" title=\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Webhook \u043d\u0430 \u043a\u0430\u043d\u0430\u043b \u0432 Discord \u0441\u0435\u0440\u0432\u0435\u0440\u0435\" width=\"1600\" height=\"629\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/44c\/d1a\/24c\/44cd1a24c3ec1af6c84030c604852784.png\"\/><\/p>\n<div><figcaption>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Webhook \u043d\u0430 \u043a\u0430\u043d\u0430\u043b \u0432 Discord \u0441\u0435\u0440\u0432\u0435\u0440\u0435<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6f9\/690\/8c6\/6f96908c63cf190bb58d7b138f685f68.png\" alt=\"Discord \u0441\u0435\u0440\u0432\u0435\u0440, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Webhook, \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c Webhook URL\" title=\"Discord \u0441\u0435\u0440\u0432\u0435\u0440, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Webhook, \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c Webhook URL\" width=\"1600\" height=\"959\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6f9\/690\/8c6\/6f96908c63cf190bb58d7b138f685f68.png\"\/><\/p>\n<div><figcaption>Discord \u0441\u0435\u0440\u0432\u0435\u0440, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Webhook, \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c Webhook URL<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 <strong>[PROJECT repo]<\/strong> \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &#171;<strong>Settings<\/strong>&#187; -> &#171;<strong>Integrations<\/strong>&#187; -> &#171;<strong>Discord Notifications<\/strong>&#171;. \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9cb\/96b\/0f2\/9cb96b0f22e3bf8ec4aafcccbf01fbfb.png\" width=\"1600\" height=\"1385\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9cb\/96b\/0f2\/9cb96b0f22e3bf8ec4aafcccbf01fbfb.png\"\/><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <strong>Gitlab CI\/CD<\/strong> + <strong>Firebase<\/strong> + <strong>Fastlane<\/strong> + <strong>Jira<\/strong> \u0438 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435\u043c \u0432 <strong>Discord<\/strong>. \u041f\u043e\u0434\u0432\u043e\u0434\u044f \u0438\u0442\u043e\u0433, \u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <strong>CI\/CD<\/strong>-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0448\u0430\u0433\u0438, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 <strong>CI\/CD<\/strong> \u043a \u043d\u043e\u0432\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043f\u0443\u0441\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0435\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442<code>.gitlab-ci.yml<\/code> \u0441 \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u043d\u0430 <code>.gitlab-ci-template.yml<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 <strong>GitLab<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 <strong>.env.NewProject<\/strong> \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c <strong>Appfile<\/strong>.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0443\u0439\u0434\u0435\u0442 \u043d\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0447\u0430\u0441\u0430<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0431\u0443\u0434\u0435\u0442 \u0412\u0430\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c. \u041f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u0432\u0430\u043c \u043a\u043e\u0434\u0438\u043d\u0433\u0430!<br \/>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u0430\u0432\u0442\u043e\u0440\u0430\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 \u0438 \u043c\u043e\u0438\u043c \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c.<\/p>\n<p><strong>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<br \/><\/strong><a href=\"https:\/\/firebase.google.com\/docs\/app-distribution\/authenticate-service-account?platform=ios\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/firebase.google.com\/docs\/app-distribution\/authenticate-service-account?platform=ios<br \/><\/u><\/a><a href=\"https:\/\/medium.com\/google-cloud\/gitlab-and-workload-identity-federation-on-google-cloud-a0795091e404\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/medium.com\/google-cloud\/gitlab-and-workload-identity-federation-on-google-cloud-a0795091e404<br \/><\/u><\/a><a href=\"https:\/\/docs.gitlab.com\/ee\/user\/project\/integrations\/discord_notifications.html\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/docs.gitlab.com\/ee\/user\/project\/integrations\/discord_notifications.html<br \/><\/u><\/a><a href=\"https:\/\/medium.com\/@sky.tienyu\/how-to-deploy-firebase-in-gitlab-ci-using-a-service-account-key-b2a459b63db9\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/medium.com\/@sky.tienyu\/how-to-deploy-firebase-in-gitlab-ci-using-a-service-account-key-b2a459b63db9<br \/><\/u><\/a><a href=\"https:\/\/about.gitlab.com\/blog\/2020\/03\/16\/gitlab-ci-cd-with-firebase\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/about.gitlab.com\/blog\/2020\/03\/16\/gitlab-ci-cd-with-firebase\/<br \/><\/u><\/a><a href=\"https:\/\/www.andrewhoog.com\/post\/how-to-export-ad-hoc-ios-ipa-xcode\/#export-ipa\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/www.andrewhoog.com\/post\/how-to-export-ad-hoc-ios-ipa-xcode\/#export-ipa<br \/><\/u><\/a><a href=\"https:\/\/www.andrewhoog.com\/post\/how-to-build-an-ios-app-archive-via-command-line\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/www.andrewhoog.com\/post\/how-to-build-an-ios-app-archive-via-command-line\/<\/u><\/a><\/p>\n<\/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\/821981\/\"> https:\/\/habr.com\/ru\/articles\/821981\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u043c\u0438\u0442\u0440\u0438\u0439, \u0438 \u044f iOS \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Triada. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>CI\/CD<\/strong> \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e iOS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u0443\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0441 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0430 \u2013 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c.<\/p>\n<p>\u041c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c <strong>CI\/CD<\/strong> \u0434\u043b\u044f iOS \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c \u043d\u0430 <strong>GitLab<\/strong> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <strong>Fastlane<\/strong>. \u0421\u0431\u043e\u0440\u043a\u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 <strong>TestFlight<\/strong> \u0438 \u0432 <strong>Firebase<\/strong>, \u0435\u0441\u043b\u0438 \u043e\u043d \u0443 \u0432\u0430\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d. \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>. <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\"><\/p>\n<p><\/a>\u0427\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f:\u00a0<\/p>\n<ol>\n<li>\n<p>3 Gitlab \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c <strong>CI\/CD<\/strong> (<strong>PROJECT repo)<\/strong>. <br \/>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043b\u0438\u043d\u0442\u0435\u0440, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0433\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043d\u0435 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e. \u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Unit \u0442\u0435\u0441\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p>\u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c\u00a0<sub><br \/><\/sub><\/p>\n<ol>\n<li>\n<p>\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432 (<strong>CERTS repo)<\/strong><\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 <strong>CI\/CD<\/strong> (\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u0442\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0438 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438)<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p>MacOS \u043c\u0430\u0448\u0438\u043d\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c <strong>CI\/CD<\/strong> (<strong>CI\/CD SERVER)<\/strong>.\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>Apple ID <\/strong>\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c, \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Firebase Service Account<\/strong> &#8212; \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c. \u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f <strong>CI\/CD<\/strong> \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. <strong>Firebase<\/strong> \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0431\u043e\u0440\u043e\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430\u043c.\u00a0<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Gitlab<\/strong> (<strong>Premium<\/strong> or <strong>Ultimate<\/strong>) \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <strong>Gitlab API<\/strong> \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Discord<\/strong> \u0441\u0435\u0440\u0432\u0435\u0440 &#8212; \u0441\u0442\u043e\u0438\u0442 \u0443\u0447\u0435\u0441\u0442\u044c, \u0447\u0442\u043e \u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0432\u0435\u0431\u0445\u0443\u043a\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) <strong>Jira<\/strong> &#8212; \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f c \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>Jira<\/strong>, \u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u0432\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f &#8212; \u043e\u0434\u0438\u043d \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 <strong>CI\/CD<\/strong>. \u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <strong>CI\/CD<\/strong> \u0432 \u0446\u0435\u043b\u043e\u043c, \u0430 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u043f\u0438\u0448\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433:\u00a0<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 <strong>CI\/CD<\/strong><\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 iOS \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <strong>GitLab<\/strong><\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0448\u0438\u043d\u044b (\u0445\u043e\u0441\u0442\u0430) \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0440\u043e\u0432 <strong>CI\/CD<\/strong><\/p>\n<\/li>\n<\/ol>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d:<br \/>\u041f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043c\u0435\u0440\u0434\u0436 \u0440\u0435\u043a\u0432\u0435\u0441\u0442\u0430 (<strong>MR<\/strong>) \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0442\u043a\u0438 \u0438 \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432. \u041f\u043e\u0441\u043b\u0435 \u0438\u0445 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043c\u043e\u0433 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u043d\u0435\u0441\u0442\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0432 \u043a\u043e\u0434. \u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u043b\u0438\u043d\u0442\u0435\u0440\/\u0444\u043e\u0440\u043c\u0430\u0442\u0442\u0435\u0440. \u0415\u0441\u043b\u0438 \u0432 <strong>MR<\/strong> \u0432\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u043a\u0438, \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043d\u043e\u0432\u043e.<\/p>\n<p>\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430 <code>create_archive<\/code> \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 <strong>.ipa<\/strong>-\u0430\u0440\u0445\u0438\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 <strong>release notes<\/strong> \u0434\u043b\u044f <strong>Firebase<\/strong>. \u0417\u0430\u0442\u0435\u043c \u044d\u0442\u043e\u0442 \u0430\u0440\u0445\u0438\u0432 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 <strong>Firebase<\/strong> \u0438 <strong>TestFlight<\/strong> \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0438 \u0446\u0435\u043b\u043e\u043c, \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 <strong>CI\/CD<\/strong> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\">\n<div><figcaption>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430: \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0430\u0440\u0445\u0438\u0432\u0430 \u0438 \u0442\u0435\u043f\u043b\u043e\u0439 \u0432 TestFlight \u0438 Firebase<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u044f \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u043b \u0440\u0430\u043d\u0435\u0435, \u0432 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432 <strong>.swift<\/strong>, \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0432 <strong>MR<\/strong>, \u0438 \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u044b \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 <strong>MR<\/strong>. \u0425\u043e\u0447\u0443 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e, \u043d\u0430\u0448\u0435\u043b \u043b\u0438 \u043b\u0438\u043d\u0442\u0435\u0440 \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438\u043b\u0438 \u043d\u0435\u0442 &#8212; \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u0415\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u0432 <strong>MR<\/strong> \u043d\u0430 <strong>GitLab<\/strong> \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0441\u044f \u0441\u0442\u0430\u0442\u0443\u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0434\u0430 \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u043c, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430, \u0438\u043d\u0430\u0447\u0435 \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043b\u044f <strong>API Gitlab.<\/strong><\/p>\n<p>\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0420\u0438\u0441 3. \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0432 MR<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0422\u0430\u043c, \u0433\u0434\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043b\u0438\u043d\u0442\u0435\u0440 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0442\u0440\u0435\u0434 \u0432 MR.<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u0442 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0439, \u0447\u0442\u043e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430 \u043b\u0438\u0442\u0435\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0432\u0435\u0434\u0435\u043d <strong>diff<\/strong> \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u0434\u0430. \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0432<strong> Gitlab API<\/strong>, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 <strong>diff<\/strong> \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0431\u043b\u043e\u043a\u043e\u0432 \u043a\u043e\u0434\u0430 \u043a\u0430\u043a \u0432 \u0441\u0442\u0430\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u0435, \u0442\u0430\u043a \u0438 \u0432 \u043d\u043e\u0432\u043e\u043c, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f <strong>sha1<\/strong> \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430. \u041d\u043e \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c\u0441\u044f \u0441 <strong>Gitlab API<\/strong>, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e <s>\u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432<\/s> \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u043a\u0443. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 <strong>Gitlab API <\/strong>\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/docs.gitlab.com\/ee\/api\/discussions.html#parameters-for-multiline-comments\" rel=\"noopener noreferrer nofollow\"><u>\u0442\u0443\u0442<\/u><\/a>.<\/p>\n<\/div>\n<\/details>\n<p>\u0428\u0430\u0433\u0438 <code>deploy_to_fb<\/code> \u0438 <code>deploy_to_tf<\/code> \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0430\u0440\u0445\u0438\u0432\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 <strong>Firebase<\/strong> \u0438 <strong>TestFlight<\/strong> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0414\u043b\u044f <strong>Firebase<\/strong> \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432 \u0438 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u044e\u0442\u0441\u044f <strong>release notes<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0432 \u043e Release notes<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u00a0<strong>Jira<\/strong>\u00a0&#8212; \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u043e\u043c\u0435\u0440 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043d\u0435\u0435. \u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0435\u0449\u0435 \u0438 \u044d\u043f\u0438\u043a &#8212; \u043e\u043d \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u043e\u043c\u0435\u0440 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u0441\u0431\u043e\u0440\u043a\u0438.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\">\n<div><figcaption>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes<\/figcaption><\/div>\n<\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0436\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d\u0430, \u0432 <strong>release notes<\/strong> \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u043d\u043e\u043c\u0435\u0440\u0435 \u0441\u0431\u043e\u0440\u043a\u0438<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f release notes<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0430\u0440\u0445\u0438\u0432\u0430, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432 <strong>TestFlight<\/strong> \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u044b.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 CI\/CD<\/h2>\n<p>\u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 <strong>CI\/CD<\/strong><\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 [CERTS repo]\u00a0<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432 \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043e\u0431\u0449\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435. <br \/>\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u043a\u0440\u0443\u0433\u0443 \u043b\u0438\u0446 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 <strong>CI\/CD<\/strong>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0435\u043f\u043e \u0432 <strong>Gitlab<\/strong> \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c.<br \/>\u0412\u0443\u0430\u043b\u044f &#8212; \u0432\u044b \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b. \u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430\u043c\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.\u00a0<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 [CI\/CD repo]<\/h3>\n<p>\u041c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c. \u0424\u0430\u0439\u043b\u044b, \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u0434\u0435\u0441\u044c, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0438. \u041f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0437\u044f\u0442\u044c \u0438\u0437 <a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/a>.<a href=\"https:\/\/gitlab.com\/cicd6840819\/cicd\" rel=\"noopener noreferrer nofollow\"><br \/><\/a><\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 CI\/CD<\/figcaption><\/div>\n<\/figure>\n<p>\u0433\u0434\u0435 \u043f\u043e \u043f\u0443\u0442\u0438 <code>fastlane\/<\/code> \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 Fastlane<\/figcaption><\/div>\n<\/figure>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <code>.gitlab-ci-template.yml<\/code> &#8212; \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u0430\u0448\u0435\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043b\u044e\u0431\u044b\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0441 <strong>CI\/CD<\/strong>. \u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u043e\u043d \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u0438 \u0432 \u043d\u0435\u043c \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 &#8212; \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u043f\u043e\u0437\u0436\u0435 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 <strong>CI\/CD<\/strong> \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. <\/p>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u0432\u0430\u0441 \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0435\u0437\u0434\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043d\u0430 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0442\u043a\u0438, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 \u0448\u0430\u0433\u0435 <code>create_archive<\/code>, \u043b\u0438\u0431\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0432\u0441\u0435:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0423\u0441\u043b\u043e\u0432\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430<code>create_archive<\/code>\u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u0432\u0435\u043d\u0442\u0430 \u0438 \u0438\u043c\u0435\u043d\u0438 \u0432\u0435\u0442\u043a\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435\u0441\u044c \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c <strong>Firebase<\/strong> \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>TestFlight<\/strong> \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0443\u0434\u0430\u043b\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<p>\u0414\u043b\u044f <strong>Firebase<\/strong>:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Firebase<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u043b\u044f <strong>TestFlight<\/strong>:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041a\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 TestFlight<\/figcaption><\/div>\n<\/figure>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 [PROJECT repo]<\/h3>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b\u043c \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u043c, \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0435\u0441\u0442\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0430\u043d\u043d\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>Appfile<\/strong><\/p>\n<\/li>\n<\/ol>\n<h4>1. \u0423\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0445\u0435\u043c \u0438 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432<\/h3>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u043e\u043c\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0442\u0430\u0440\u0433\u0435\u0442\u0430 \u0435\u0449\u0435 \u0442\u0430\u0440\u0433\u0435\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0439 \u043a \u043d\u0435\u043c\u0443 \u0441\u0445\u0435\u043c\u0435.<br \/>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0433\u0430\u0439\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 2 \u0442\u0430\u0440\u0433\u0435\u0442\u0430\u043c\u0438:<em><br \/><\/em><\/p>\n<figure class=\"\">\n<div><figcaption>\u0422\u0430\u0440\u0433\u0435\u0442\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c CI\/CD<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0440\u0430\u043d\u0435\u0435 \u0431\u044b\u043b\u043e \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e, \u0442\u0430\u0440\u0433\u0435\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 unit \u0442\u0435\u0441\u0442\u044b. \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u0443 \u0412\u0430\u0441 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438 UI \u0442\u0435\u0441\u0442\u044b, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u0430\u0440\u0433\u0435\u0442 \u0438 \u0441\u0445\u0435\u043c\u0430 \u043f\u043e\u0434 \u043d\u0435\u0433\u043e.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b <strong>CI\/CD<\/strong> \u0441 \u043d\u0430\u0448\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043f\u0435\u0440\u0432\u044b\u0435 2 \u0441\u0445\u0435\u043c\u044b:<br \/><strong>1<\/strong>. \u0421\u0445\u0435\u043c\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442<br \/><strong>2.<\/strong> \u0421\u0445\u0435\u043c\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b<br \/>3. \u0421\u0445\u0435\u043c\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u0435\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<br \/>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0438\u043c\u0435\u0435\u043c 3 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0441\u0445\u0435\u043c\u044b, \u0441\u0442\u043e\u0438\u0442 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043d\u0438\u0445 \u0441\u0442\u043e\u0438\u0442 \u0433\u0430\u043b\u043e\u0447\u043a\u0430 \u043d\u0430 shared, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#8212; \u0441\u0445\u0435\u043c\u0430 \u0432\u0438\u0434\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u043c<em>.<\/em><\/p>\n<figure class=\"\">\n<div><figcaption>\u0421\u0445\u0435\u043c\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f CI\/CD<\/figcaption><\/div>\n<\/figure>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Firebase<\/h3>\n<p>\u041c\u044b \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0443\u0436\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a <strong>Firebase<\/strong>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043c\u0435\u043b\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u0442\u0443 \u0441\u0435\u043a\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u0438\u043b\u0438 <strong>Firebase<\/strong> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>\u0428\u0430\u0433\u0438 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 Firebase.<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <a href=\"https:\/\/firebase.google.com\/\" rel=\"noopener noreferrer nofollow\"><u>Firebase<\/u><\/a>. <a href=\"https:\/\/firebase.google.com\/\" rel=\"noopener noreferrer nofollow\"><u><br \/><\/u><\/a>\u0415\u0441\u043b\u0438 \u0432\u044b \u0435\u0449\u0435 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442 <strong>Firebase<\/strong>, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u201c<strong>Add project<\/strong>\u201d. <br \/>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0441 \u043d\u0430\u0448\u0438\u043c iOS \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u201c<strong>Add app<\/strong>\u201d \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c <strong>iOS<\/strong> \u043f\u0440\u043e\u0435\u043a\u0442. <br \/>\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f 5 \u0448\u0430\u0433\u043e\u0432, \u0441\u0430\u043c\u044b\u043c \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u0434\u043b\u044f \u043d\u0430\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u201c<strong>Apple bundle ID<\/strong>\u201d &#8212; \u0435\u0433\u043e \u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 <strong>Xcode<\/strong>. <br \/>\u0421\u043a\u0430\u0447\u0430\u0439\u0442\u0435 <strong>GoogleService-Info.plist<\/strong> \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0435\u0433\u043e \u0432 \u043a\u043e\u0440\u0435\u043d\u044c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441 <strong>iOS<\/strong> \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 Firebase.<\/strong><\/p>\n<div class=\"floating-image\">\n<figure class=\"float\">\n<div><figcaption>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &#171;App Distribution&#187; \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0443\u043f\u043f<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u201c<strong>Release &amp; Monitor<\/strong>\u201d \u0438 \u0432\u044b\u0431\u0435\u0440\u0435\u0442\u0435 \u201c<strong>App Distribution<\/strong>\u201d. \u0412 \u043e\u0442\u043a\u0440\u044b\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u201c<strong>Get started<\/strong>\u201d.\u00a0<\/p>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u0447\u0442\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430. <\/p>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0442\u0430\u0431 \u201c<strong>Testers &amp; Groups<\/strong>\u201d \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0433\u0440\u0443\u043f\u043f\u0443 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0430 \u201c<strong>Add group<\/strong>\u201d (\u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043d\u0435\u0435 \u0441\u0435\u0431\u044f).<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0443\u043f\u043f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b &#8212; \u043e\u043d\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 <strong>GitLab<\/strong> <strong>CI\/CD<\/strong><\/p>\n<\/p>\n<\/div>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 &#171;Project settings&#187;<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u0442\u0430\u0431\u0435 \u201c<strong>General<\/strong>\u201d \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u043a \u043d\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u041d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0441\u0435\u043a\u0446\u0438\u044f \u201c<strong>Your apps<\/strong>\u201d &#8212; \u0432 \u043d\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0435\u0435 \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<br \/>\u041e\u0442\u043c\u0435\u0447\u0443, \u0447\u0442\u043e <strong>Bundle ID<\/strong> \u043c\u0435\u043d\u044f\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u0440\u0430\u0439\u043d\u0435 \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e.\u00a0 \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u0443\u044e \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 &#8212; \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u201c<strong>App ID<\/strong>\u201d &#8212; \u043e\u043d\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0430\u043b\u0435\u0435 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435.<\/p>\n<\/div>\n<\/details>\n<h4>2. \u0417\u0430\u0432\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b <strong>CI\/CD<\/strong> \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 <strong>Gitlab<\/strong> \u0437\u0430\u0432\u0435\u0441\u0442\u0438 3 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435.<br \/>&#171;<strong>SETTINGS<\/strong>&#187; \u2192 &#171;<strong>CI\/CD<\/strong>&#187; \u2192 &#171;<strong>Variables<\/strong>&#187; \u2192 &#171;<strong>Expand<\/strong>&#187; \u2192 &#171;<strong>Add variable<\/strong>&#171;<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c CI\/CD. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 CI\/CD<\/figcaption><\/div>\n<\/figure>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\"><strong>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"> PROJECT_NAME<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">FastlaneProject<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">PROJECT_REPO_URL<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f git clone<\/p>\n<\/td>\n<td>\n<p align=\"left\">https:\/\/gitlab.com\/XXXXXX\/YYYYYY.git \u0432\u043c\u0435\u0441\u0442\u043e XXXXXX \u0438 YYYYYY \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0432\u0430\u0448\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">XCWORKSPACE<\/p>\n<\/td>\n<td>\n<p align=\"left\">E\u0441\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043f\u043e\u0434\u044b, <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\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-378950","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/378950","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=378950"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/378950\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=378950"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=378950"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=378950"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}