{"id":427991,"date":"2024-08-01T03:00:19","date_gmt":"2024-08-01T03:00:19","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=427991"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=427991","title":{"rendered":"<span>Gradle + GitLab: \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448<\/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<h2>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442<\/h2>\n<p>\u042d\u0442\u0430 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u043c-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0433\u0430\u0439\u0434\u0430 \u043f\u043e \u0431\u044e\u0434\u0436\u0435\u0442\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 GitLab \u043a\u044d\u0448\u0435\u0439 \u0434\u043b\u044f Gradle \u0432 Android \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Gradle Enterprise \u0438 Remote Build Cache. \u0412 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043c\u0430\u043b\u043e\u0432\u0430\u0442\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043a\u044d\u0448\u0438 Gradle \u043d\u0430 CI, \u0438 \u0435\u0449\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u0412 \u043f\u0440\u0438\u0434\u0430\u0447\u0443, \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e-\u0442\u043e \u0437\u0430\u0434\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432 Gradle Slack, \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435 Gradle \u0438\u043b\u0438 \u043d\u0430 StackOverflow, \u043f\u0440\u0438\u0431\u0435\u0433\u0430\u044e\u0442 \u0443\u0432\u043b\u0430\u0436\u043d\u044f\u0435\u043c\u044b\u0435 \u0438\u0437 Gradle \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e\u0442 \u043d\u0435 \u043a\u043e\u043f\u0430\u0442\u044c \u0432 \u043d\u0443\u0436\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443, \u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0443\u043f\u0438\u0442\u044c Gradle Enterprise (\u0438\u043b\u0438 \u043a\u0430\u043a \u043e\u043d \u0442\u0430\u043c \u0449\u0430\u0441 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f).<\/p>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u043e\u043f\u044b\u0442 \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u044f \u0431\u0438\u043b\u0434-\u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0432 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u043e\u043c Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0418 \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043b\u0430\u0439\u0444\u0445\u0430\u043a\u0430\u043c\u0438 \u0441 \u0442\u0435\u043c\u0438, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438 \u0431\u0438\u043b\u0434\u0430 \u043d\u0430 CI \u0432 \u0441\u0432\u043e\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h2>\n<blockquote>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e Gradle \u0433\u043e\u0432\u043d\u043e <br \/> \u2014 \u0414\u0436\u0435\u0439\u0441\u043e\u043d \u0421\u0442\u044d\u0442\u0445\u044d\u043c<\/p>\n<\/blockquote>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0443\u0432\u0430\u0436\u0430\u044e\u0449\u0438\u0439 \u0441\u0435\u0431\u044f \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043c\u0435\u0435\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 CI\/CD, \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0432 GitLab. \u0421 \u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u043e\u0432 \u0441\u0431\u043e\u0440\u043e\u043a\/\u0442\u0435\u0441\u0442\u043e\u0432\/\u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0438 \u0442.\u0434. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0430\u0448\u0435\u0433\u043e \u041c\u0420 \u043f\u0435\u0440\u0435\u0432\u0430\u043b\u0438\u0432\u0430\u0435\u0442 \u0437\u0430 \u0432\u0441\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0447\u0442\u043e-\u0442\u043e \u0441 \u044d\u0442\u0438\u043c \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<h2>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435 \u043c\u043d\u043e\u044e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u043e\u0439 \u0434\u043e 500 \u043c\u043e\u0434\u0443\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0431\u043e\u043b\u044c\u0448\u0435, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435 \u043b\u0443\u0447\u0448\u0435 \u043c\u0435\u043d\u044f \u043a\u0430\u043a \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u043b\u0434\u044b.<\/p>\n<p>\u0413\u043e\u0432\u043e\u0440\u044f &#171;500 \u043c\u043e\u0434\u0443\u043b\u0435\u0439&#187; \u044f \u0438\u043c\u0435\u044e \u0432\u0432\u0438\u0434\u0443 500 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438\u0437 <a href=\"https:\/\/www.youtube.com\/watch?v=oAQlKiF91Ks\" rel=\"noopener noreferrer nofollow\">\u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0421\u0442\u0435\u043f\u0430\u043d\u0430 \u0413\u043e\u043d\u0447\u0430\u0440\u043e\u0432\u0430<\/a>.<\/p>\n<h3>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e<\/h3>\n<h4>\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043f\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e<\/h4>\n<blockquote>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u043a\u044d\u0448 \u0432 \u043e\u0434\u043d\u0438\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u0432 \u0434\u0440\u0443\u0433\u0438\u0445.<\/p>\n<\/blockquote>\n<p>\u0412 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430\u0434\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043a\u044d\u0448\u0430 \u0432 GitLab, \u044d\u0442\u043e \u043d\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0435\u0441\u0438\u0442 \u043a\u044d\u0448, \u0442\u0435\u043c \u0434\u043e\u043b\u044c\u0448\u0435 \u043e\u043d \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0430\u0440\u0445\u0438\u0432 \u0438 \u043e\u0442\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u043b\u0430\u043a\u043e. \u0414\u0430\u0436\u0435 Gradle Remote Build Cache \u043d\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0430\u044f \u0448\u0442\u0443\u043a\u0430, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 Remote Build Cache \u043f\u043b\u0430\u0433\u0438\u043d \u0438 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e Docker \u043d\u043e\u0434\u0443. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435 \u0432\u0441\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u044d\u0448.<\/p>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u0430\u044f \u043c\u043d\u043e\u044e \u0441\u0445\u0435\u043c\u0430 \u0442\u0430\u043a\u0430\u044f:<\/p>\n<ul>\n<li>\n<p>\u0423 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0435\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0432\u0435\u0442\u043a\u0430, \u043f\u0443\u0441\u0442\u044c \u043e\u043d\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>master<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u0442\u044c <code>feature<\/code>-\u0432\u0435\u0442\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0432\u043e\u0435\u0439 \u0436\u0438\u0437\u043d\u0438 \u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 <code>master<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u0438 \u0432 <code>master<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0430\u0439\u043f, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0431\u0438\u043b\u0434 \u043a\u044d\u0448. \u0415\u0441\u043b\u0438 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u0438, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u043d\u0430 <code>feature<\/code>-\u0432\u0435\u0442\u043a\u0430\u0445, \u043e\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043a\u044d\u0448 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0432\u0435\u0442\u043a\u0435 <code>master<\/code>.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c3c\/154\/397\/c3c154397fa7ebf5e6d473b9cb426168.png\" alt=\"Different pipeline purposes\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c3c\/154\/397\/c3c154397fa7ebf5e6d473b9cb426168.png\"\/><\/p>\n<div><figcaption>Different pipeline purposes<\/figcaption><\/div>\n<\/figure>\n<h4>\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 GitLab \u043a\u044d\u0448\u0435\u0439 \u043f\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e<\/h4>\n<blockquote>\n<p>\u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 Gradle Wrapper \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438<\/p>\n<\/blockquote>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0434 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0436\u0435 \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0438 \u0435\u0449\u0435 \u0440\u0435\u0436\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u0441\u0438\u044f Gradle. \u042f \u0441\u0447\u0438\u0442\u0430\u044e \u0447\u0442\u043e \u043a\u044d\u0448 \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439. \u0421\u0443\u043c\u043c\u0430\u0440\u043d\u044b\u0439 \u0432\u0435\u0441 \u0430\u0440\u0445\u0438\u0432\u0430 \u0441 \u043e\u0431\u0449\u0438\u043c \u043a\u044d\u0448\u043e\u043c \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u0442 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e s3 \u043b\u0438\u043c\u0438\u0442\u044b. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435 \u0434\u0436\u043e\u0431\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0443\u0436\u043d\u044b \u043d\u0435 \u0432\u0441\u0435 \u0432\u0438\u0434\u044b \u043a\u044d\u0448\u0430, \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043b\u0438\u0448\u043d\u0435\u0433\u043e.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/83d\/a73\/2e6\/83da732e692a5172b51dea520892441e.png\" alt=\"Different types of Gradle cache\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/83d\/a73\/2e6\/83da732e692a5172b51dea520892441e.png\"\/><\/p>\n<div><figcaption>Different types of Gradle cache<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0441\u0435 \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 CI, Gradle \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>$GRADLE_USER_HOME<\/code>. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0434\u0436\u043e\u0431:<\/p>\n<pre><code class=\"yaml\">some job:   variables:     GRADLE_USER_HOME: $CI_PROJECT_DIR\/.gradle <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u044f \u0431\u0443\u0434\u0443 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0447\u0442\u043e <code>$GRADLE_USER_HOME<\/code> \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u043e\u0439.<\/p>\n<pre><code>$GRADLE_USER_HOME\/ \u251c\u2500\u2500 caches\/ \u2502   \u251c\u2500\u2500 build-cache-1\/ &lt;- \u0411\u0438\u043b\u0434-\u043a\u044d\u0448 \u2502   \u2514\u2500\u2500 modules-2\/ &lt;- \u043a\u044d\u0448 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u251c\u2500\u2500 notifications\/ &lt;- \u043c\u0443\u0441\u043e\u0440 \u0434\u043b\u044f wrapper \u2514\u2500\u2500 wrapper\/ &lt;- \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b wrapper <\/code><\/pre>\n<h4>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 GitLab \u043a\u044d\u0448 \u0434\u043b\u044f Gradle Wrapper<\/h4>\n<p>\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b Gradle \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 <code>$GRADLE_USER_HOME\/wrapper\/<\/code>, \u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0443\u0441\u043e\u0440 \u043e\u0442 \u043d\u0435\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <code>$GRADLE_USER_HOME\/notifications\/<\/code>. \u0425\u043e\u0440\u043e\u0448\u043e \u0431\u044b \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 GitLab cache key:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-wrapper-cache:   - key: cache-wrapper     policy: pull     unprotect: true     paths:       - .gradle\/wrapper\/       - .gradle\/notifications\/  .pull-push-wrapper-cache:   - key: cache-wrapper     policy: pull-push     unprotect: true     paths:       - .gradle\/wrapper\/       - .gradle\/notifications\/ <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">cache build:   ...   cache:     - !reference [ .pull-push-wrapper-cache ] <\/code><\/pre>\n<p>\u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Gradle \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0447\u0442\u043e \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u043e\u0432 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f. \u041f\u043e\u0432\u0435\u0440\u0438\u043c \u0438\u043c \u043d\u0430 \u0441\u043b\u043e\u0432\u043e. \u041a\u044d\u0448 \u0441 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0430\u043c\u0438 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0437\u0440\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u0438\u043b\u044c\u043d\u043e.<\/p>\n<p>\u0412 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">lint:   ...   cache:     - !reference [ .pull-wrapper-cache ] <\/code><\/pre>\n<p>\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b Gradle \u043d\u0435 \u0432\u0435\u0441\u044f\u0442 \u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0430\u0440\u0445\u0438\u0432\u044b \u0441 \u043d\u0438\u043c\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0436\u043e\u0431\u0443 \u0431\u044b\u0441\u0442\u0440\u043e.<\/p>\n<h4>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 GitLab \u043a\u044d\u0448 \u0434\u043b\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h4>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u044d\u0442\u043e AAR \u0438 JAR \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0432\u0441\u0435\u0445 \u043b\u0438\u0431 \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435. Gradle \u0438\u0445 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 <code>$GRADLE_USER_HOME\/caches\/modules-2\/<\/code>. \u0412\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u044d\u0448\u0430\u043c\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-deps-cache:   - key: cache-deps     policy: pull     unprotect: true     paths:       - .gradle\/caches\/modules-2\/  .push-deps-cache:   - key: cache-deps     policy: push     unprotect: true     paths:       - .gradle\/caches\/modules-2\/ <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">cache build:   ...   cache:     - !reference [ .push-deps-cache ] <\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043a\u0430\u0447\u0430\u0435\u0442 \u0438\u0445 \u0437\u0430\u043d\u043e\u0432\u043e. \u041e\u0431\u044a\u044f\u0441\u043d\u044f\u044e \u044d\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u0412 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">lint:   ...   cache:     - !reference [ .pull-deps-cache ] <\/code><\/pre>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u0435\u0441\u044f\u0442 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b gradle, \u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u0447\u0435\u043c \u0431\u0438\u043b\u0434 \u043a\u044d\u0448.<\/p>\n<h4>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 GitLab \u043a\u044d\u0448 \u0434\u043b\u044f Gradle build cache<\/h4>\n<p>\u0421\u0430\u043c\u0430\u044f \u0442\u044f\u0436\u0435\u043b\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a\u044d\u0448\u0430 \u2014 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448.<\/p>\n<p>\u0411\u0438\u043b\u0434-\u043a\u044d\u0448 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <code>$GRADLE_USER_HOME\/caches\/build-cache-1\/<\/code>. \u0412\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0442, \u0442\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0433\u0440\u043e\u043c\u043d\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043d\u044f \u0441 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448\u043e\u043c:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-build-cache:   - key: cache-build     policy: pull     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/  .push-build-cache:   - key: cache-build     policy: push     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/ <\/code><\/pre>\n<p>\u0414\u0436\u043e\u0431\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"yaml\">cache build:   ...   cache:     - !reference [ .push-build-cache ] <\/code><\/pre>\n<p>\u0418 \u0441\u043d\u043e\u0432\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0447\u0442\u043e \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u044d\u0448\u0430 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442. \u041e\u0431\u044a\u044f\u0441\u043d\u044f\u044e \u044d\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u0414\u0436\u043e\u0431\u044b \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0449\u0438\u0435 \u0431\u0438\u043b\u0434 \u043a\u044d\u0448 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c:<\/p>\n<pre><code class=\"yaml\">test:   ...   cache:     - !reference [ .pull-build-cache ] <\/code><\/pre>\n<h4>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u043e\u0435\u0434\u0438\u043d\u043e, \u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"yaml\">.base:   variables:     GRADLE_USER_HOME: $CI_PROJECT_DIR\/.gradle   # \u0422\u0443\u0442 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0435\u0449\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043b   before_script:     - ...   after_script:     - ...  # \u042d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u041c\u0420\u0435 build:   stage: check   extends: .base   script:     - .\/gradlew :app:assembleDebug   cache:     - !reference [ .pull-wrapper-cache ]     - !reference [ .pull-deps-cache ]     - !reference [ .pull-build-cache ]   rules:     - if: $CI_PIPELINE_SOURCE = \"merge_request_event\"  # \u042d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u044f \u041c\u0420\u0430 cache build:   stage: post-check   extends: .base   script:     - .\/gradlew :app:assembleDebug   cache:     - !reference [ .pull-push-wrapper-cache ]     - !reference [ .push-deps-cache ]     - !reference [ .push-build-cache ]   rules:     - if: $CI_PIPELINE_SOURCE = \"push\" &amp;&amp; $CI_COMMIT_BRANCH == \"master\" <\/code><\/pre>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0441\u0431\u043e\u0440\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u0445 \u041c\u0420\u0430 \u0431\u0443\u0434\u0435\u0442 \u0443\u0436\u0435 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0430. \u041d\u043e \u043a\u0430\u043a \u043b\u044e\u0431\u044f\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u0441\u043e\u0435\u0432\u044b\u0435 \u0430\u0439\u0442\u0438\u0448\u043d\u0438\u043a\u0438, &#171;\u0442\u0443\u0442 \u0435\u0441\u0442\u044c \u0442\u043e\u0447\u043a\u0438 \u0440\u043e\u0441\u0442\u0430&#187;.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/846\/e10\/465\/846e10465f1761c15bdadb1f3282c46f.png\" alt=\"Build cache isn't reused\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/846\/e10\/465\/846e10465f1761c15bdadb1f3282c46f.png\"\/><\/p>\n<div><figcaption>Build cache isn&#8217;t reused<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0434\u0436\u043e\u0431\u0435 <code>cache build<\/code> \u043d\u0435 \u0434\u0430\u0435\u0442\u0441\u044f \u043a\u044d\u0448 \u043e\u0442 \u0435\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432. \u0422\u043e \u0435\u0441\u0442\u044c \u0431\u0438\u043b\u0434 \u0438 \u0437\u0430\u043a\u0430\u0447\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0432 \u044d\u0442\u043e\u0439 \u0434\u0436\u043e\u0431\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441 \u043d\u0443\u043b\u044f. \u0412\u0441\u0435 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e Gradle \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435 \u043e\u0447\u0438\u0449\u0430\u0435\u0442 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043a\u044d\u0448 \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u044d\u0448\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u043f\u0440\u043e\u0433\u043e\u043d\u043e\u0432, \u0442\u043e \u043a\u044d\u0448 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u0441 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e. \u041e\u043d \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u0432\u0430\u043b\u0438\u0442 \u0437\u0430 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043e\u0442\u043c\u0435\u0442\u043a\u0443 \u0432 5 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0432\u044b \u0434\u0430\u0436\u0435 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 s3. \u041a\u043e\u0440\u043e\u0447\u0435, \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043d\u0435\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u0440\u043e\u0441\u0442\u0430 GitLab \u043a\u044d\u0448\u0430.<\/p>\n<p>\u041f\u043e\u043b\u043d\u043e\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0434\u043e\u043b\u0433\u0438\u043c \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u043c. \u041d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u043b\u0433\u0438\u043c, \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u0434\u0443\u043c\u0430\u0442\u044c\u0441\u044f, \u0430 \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e \u043b\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043a\u044d\u0448 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u0438 \u0432 <code>master<\/code>, \u0438\u043b\u0438 \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e?<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0433\u043b\u0438 \u0441\u0430\u043c\u0438 \u043e\u0447\u0438\u0449\u0430\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 cache entry \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>$GRADLE_USER_HOME\/caches\/build-cache-1\/<\/code>, \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u0443\u043f\u0435\u0440 \u0443\u0434\u043e\u0431\u043d\u043e, \u043c\u043c\u043c\u043c?<\/p>\n<h4>\u0423\u043f\u0441, \u043a\u0443\u043f\u0438\u0442\u0435 Gradle Enterprise<\/h4>\n<p>\u041d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 Gradle Enterprise, \u043d\u043e \u0437\u0430 \u043d\u0435\u0433\u043e \u0443 \u0432\u0430\u0441 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0434\u0435\u043d\u044f\u043a. \u0410 \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u0411\u043e\u0433\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043c\u043e\u0439, \u0442\u043e \u0432\u0430\u043c \u0434\u0430\u0436\u0435 \u043d\u0435 \u043f\u0440\u043e\u0434\u0430\u0434\u0443\u0442. \u0412\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438 Gradle \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u043f\u0446\u0438\u0438 <code>--scan<\/code>. \u041d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440 \u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 CI \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u041f\u0440\u043e \u0442\u043e \u043a\u0430\u043a \u0441\u043b\u043e\u043c\u0430\u0442\u044c Gradle Enterprise \u043f\u043b\u0430\u0433\u0438\u043d \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0431\u0438\u043b\u0434 \u0441\u043a\u0430\u043d\u0430\u043c\u0438 \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u043c\u0435\u0442\u043a\u0443. \u0414\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438 \u043d\u0430\u0448\u0435\u043b \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/991\/dd3\/f4a\/991dd3f4a439d809feda4e176d700a47.png\" alt=\"POV: You dig down into Gradle\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/991\/dd3\/f4a\/991dd3f4a439d809feda4e176d700a47.png\"\/><\/p>\n<div><figcaption>POV: You dig down into Gradle<\/figcaption><\/div>\n<\/figure>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441-\u043c\u043e\u0434\u0435\u043b\u044c Gradle \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043d\u0430 \u043d\u0435\u043d\u0430\u0432\u0438\u0441\u0442\u0438 \u043a \u043b\u044e\u0434\u044f\u043c, \u043c\u044b \u0442\u0430\u043a\u043e\u0435 \u043e\u0441\u0443\u0436\u0434\u0430\u0435\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0435\u043d\u044f\u043a \u0438\u043c \u043d\u0435 \u0434\u0430\u0434\u0438\u043c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0431\u0435\u0437 Enterprise \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438 \u043e\u0442 \u0431\u0438\u043b\u0434\u043e\u0432 \u043d\u0430 CI.<\/p>\n<h3>\u0412\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u043c \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438<\/h3>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0435\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0431\u0438\u043b\u0434\u0430, \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c gradle internal api. \u0425\u043e\u0440\u043e\u0448\u0435\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u0434\u0430\u043b\u044c\u0448\u0435 \u0434\u0435\u043b\u0430\u0435\u043c, \u0435\u0441\u0442\u044c \u0432 <a href=\"https:\/\/mobiusconf.com\/en\/archive\/2024%20Spring\/talks\/f9f7e56446a7462eb8e3e4ba6cc64770\/?referer=%2Fen%2Farchive%2F2024%2520Spring%2Fpartners%2F42a2ee1c-85c9-4ceb-ba77-a0fe87f91cec%2F\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u043e\u0442 \u0422\u0438\u043d\u044c\u043a\u043e\u0444\u0444 \u043d\u0430 Mobius Spring 2024<\/a>.<\/p>\n<h4>\u041f\u0438\u0448\u0435\u043c BuildService<\/h4>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0441\u0435 \u0431\u0438\u043b\u0434-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0431\u0438\u043b\u0434\u0430 \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0435\u0439 \u0432 \u0444\u0430\u0439\u043b:<\/p>\n<pre><code class=\"kotlin\">internal abstract class CacheKeysHandlerService :     BuildService&lt;CacheKeysHandlerService.Params&gt;,     BuildOperationListener,     AutoCloseable {      interface Params : BuildServiceParameters {         val cacheKeysFile: RegularFileProperty     }      private val cacheKeys: MutableSet&lt;String&gt; = ConcurrentHashMap.newKeySet()      override fun started(descriptor: BuildOperationDescriptor, event: OperationStartEvent) {         \/* no-op *\/     }      override fun progress(identifier: OperationIdentifier, event: OperationProgressEvent) {         \/* no-op *\/     }      override fun finished(descriptor: BuildOperationDescriptor, event: OperationFinishEvent) {         when (val details = descriptor.details) {             \/\/ c\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0432 \u043a\u044d\u0448 (\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438 remote)             is StoreOperationDetails -&gt; cacheKeys += details.cacheKey             \/\/ \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0437 \u043a\u044d\u0448\u0430 (\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438 remote)             is LoadOperationDetails -&gt; cacheKeys += details.cacheKey             \/\/ \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u044d\u0448\u0430             is PackOperationDetails -&gt; cacheKeys += details.cacheKey             \/\/ \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u044d\u0448\u0430             is UnpackOperationDetails -&gt; cacheKeys += details.cacheKey         }     }      override fun close() {         parameters.cacheKeysFile.get().asFile.bufferedWriter().use { writer -&gt;             for (key in cacheKeys) {                 writer.appendLine(key)             }         }     } } <\/code><\/pre>\n<p>\u041e\u0431\u044a\u044f\u0441\u043d\u044f\u044e \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:<\/p>\n<ol>\n<li>\n<p>\u0412\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b Gradle \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u043d\u0430 \u0444\u043e\u043d\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0431\u0438\u043b\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>BuildService&lt;*&gt;<\/code>. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>Params<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f &#171;\u0432\u043d\u0435\u0448\u043d\u0438\u043c API&#187; \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p><code>BuildOperationListener<\/code> \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0441\u0435 \u0431\u0438\u043b\u0434-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Gradle. \u042d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u0437 \u043f\u0430\u043a\u0435\u0442\u0430 <code>internal<\/code>. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 &#171;listener&#187; \u0438\u0437 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e API \u043d\u0435 \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>AutoCloseable<\/code> \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>close()<\/code>. \u041e\u043d \u0432\u044b\u0437\u043e\u0432\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0446\u0435 \u0431\u0438\u043b\u0434\u0430. \u0418\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043c \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0437\u0430 \u0432\u0441\u0435 \u0432\u0440\u0435\u043c\u044f \u0431\u0438\u043b\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0435 <code>cacheKeys: MutableSet&lt;String&gt;<\/code>. \u0422\u0443\u0442 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438. \u0412\u0430\u0436\u043d\u043e \u0447\u0442\u043e <code>BuildOperationListener<\/code> \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u043c, \u043d\u0430\u043c \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u043b\u043e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443, \u0438 \u043d\u0443\u0436\u043d\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>cacheKeys<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0438\u0437 <code>java.util.concurrent<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0437 \u0432\u0441\u0435\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043a\u043e\u043b\u0431\u0435\u043a\u0430 <code>BuildOperationListener<\/code> \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e <code>finished<\/code>. \u0412 \u043d\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0435\u0439. \u041a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 Set. \u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043c \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 convention-\u043f\u043b\u0430\u0433\u0438\u043d\u0430:<\/p>\n<pre><code class=\"kotlin\">@Suppress(\"unused\", \"UnstableApiUsage\") internal abstract class CacheKeysHandlerPlugin @Inject constructor(     providers: ProviderFactory,     layout: BuildLayout,     private val registryInternal: BuildEventListenerRegistryInternal, ) : Plugin&lt;Settings&gt; {      \/** \u041f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043b\u0430\u0433\u0438\u043d \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d, \u0432\u0440\u0443\u0431\u0430\u0435\u043c \u0435\u0433\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 CI *\/     private val enabled = providers         .gradleProperty(\"com.example.build.cache-keys.enabled\")         .map { it.toBoolean() }         .getOrElse(false)      \/** \u041c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043e output-\u0444\u0430\u0439\u043b\u0430 \u0441 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0430\u043c\u0438 *\/     private val cacheKeysFile = providers         .gradleProperty(\"com.example.build.cache-keys.file-name\")         .orElse(\"cache-keys.txt\")         \/\/ \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u0447\u0435\u0440\u0435\u0437 layout, \u0430 \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 java.io.File,         \/\/ Gradle \u0441\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0444\u0430\u0439\u043b \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u0431\u0438\u043b\u0434\u0430.         .map { layout.rootDirectory.file(it) }      override fun apply(target: Settings): Unit = with(target) {         if (!enabled) return          val serviceProvider = gradle.sharedServices.registerIfAbsent(             \"cache-keys-handler-service\",             CacheKeysHandlerService::class.java,         ) { spec -&gt;             with(spec) {                 parameters.cacheKeysFile.set(cacheKeysFile)             }         }         registryInternal.onOperationCompletion(serviceProvider)     } } <\/code><\/pre>\n<blockquote>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u044b \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432: <a href=\"https:\/\/docs.gradle.org\/current\/userguide\/service_injection.html\" rel=\"noopener noreferrer nofollow\">Understanding Services and Service Injection<\/a>.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u044d\u0442\u043e\u0442 convention-\u043f\u043b\u0430\u0433\u0438\u043d \u0432 <code>settings.gradle<\/code> \u0444\u0430\u0439\u043b\u0435 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041d\u0430 \u044d\u0442\u043e\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0430\u0441\u044c.<\/p>\n<blockquote>\n<p>\u0412\u0430\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430 100% \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0434\u0432\u0443\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u0439:<\/p>\n<ol>\n<li>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043d\u0435\u0442 \u0442\u0430\u0441\u043e\u043a UP-TO-DATE. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0442\u0430\u0441\u043a\u0430 UP-TO-DATE, Gradle \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c build caching \u0438 \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043d\u0430 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043b\u043e\u0436\u043d\u0435\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d Configuration Cache.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 CI \u0432 \u0447\u0438\u0441\u0442\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u0445 \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043d\u0435\u0442 \u0438 configuration cache \u0442\u0430\u043c \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d (\u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d \u0436\u0435, \u0434\u0430?).<\/p>\n<p>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c <code>.\/gradlew clean<\/code>, \u0447\u0442\u043e\u0431\u044b \u0443\u0434\u0430\u043b\u0438\u0442\u044c <code>build<\/code> \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <code>--no-configuration-cache<\/code>.<br \/> \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e <a href=\"https:\/\/stackoverflow.com\/questions\/65101472\/what-is-the-difference-between-from-cache-and-up-to-date-in-gradle\" rel=\"noopener noreferrer nofollow\">\u043e\u0442\u043b\u0438\u0447\u0438\u044f UP-TO-DATE \u0438 FROM-CACHE<\/a>.<\/p>\n<\/blockquote>\n<h3>\u0414\u043e\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<h4>\u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0438\u043b\u0434 \u043a\u044d\u0448 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u044d\u0448\u0430<\/h4>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a\u0438\u0435 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438\u043a\u0438 \u0431\u044b\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0431\u0438\u043b\u0434\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0434\u0440\u043e\u043f\u0430\u0442\u044c \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435. \u0422\u0430\u043a \u043c\u044b \u0432 \u0440\u0430\u0437\u044b \u0443\u0441\u043a\u043e\u0440\u044f\u0435\u043c \u043f\u0440\u043e\u0433\u043e\u043d \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/77f\/80e\/00e\/77f80e00ec88f33d156611cb0001b4c5.png\" alt=\"Intersection between old and new cache key sets\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/77f\/80e\/00e\/77f80e00ec88f33d156611cb0001b4c5.png\"\/><\/p>\n<div><figcaption>Intersection between old and new cache key sets<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u0432\u0441\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0440\u0430\u0441\u0438\u0432\u043e, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u043f\u0438\u043b\u0438\u043c \u043d\u0430\u0448 <code>CacheKeysHandlerService<\/code> \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0438\u043b\u0434-\u043a\u044d\u0448\u0430:<\/p>\n<pre><code class=\"kotlin\">internal abstract class CacheKeysHandlerService @Inject constructor(     gradle: Gradle, \/\/ \u044d\u0442\u043e \u0442\u043e\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c ) :     BuildService&lt;CacheKeysHandlerService.Params&gt;,     BuildOperationListener,     AutoCloseable {      \/\/ \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 \u043a\u043e\u0434...      private val buildCacheDir: File = checkNotNull(gradle.gradleHomeDir)         .resolve(\"caches\/build-cache-1\")      override fun close() {         \/\/ \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 \u043a\u043e\u0434...                  \/\/ \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438, \u043d\u0435 \u0432\u043e\u0448\u0435\u0434\u0448\u0438\u0435 \u0432 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0431\u0438\u043b\u0434         val unusedCacheKeys = iterateBuildCache { it !in cacheKeys }         for (key in unusedCacheKeys) {             check(buildCacheDir.resolve(key).delete()) {                 \"Unable to delete cache key file: $key\"             }         }     }      private fun iterateBuildCache(selector: (String) -&gt; Boolean): Array&lt;out File&gt; =         buildCacheDir             .listFiles { file -&gt; selector(file.name) }             .orEmpty() } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448 GitLab Yaml \u043a\u043e\u043d\u0444\u0438\u0433. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433 \u0434\u043b\u044f \u043a\u044d\u0448\u0430:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-push-build-cache:   - key: cache-build     policy: pull-push     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/ <\/code><\/pre>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043a\u043e\u043d\u0444\u0438\u0433 \u0432 \u0434\u0436\u043e\u0431\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430:<\/p>\n<pre><code class=\"yaml\">...  # \u042d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u044f \u041c\u0420\u0430 cache build:   stage: post-check   extends: .base   script:     - .\/gradlew :app:assembleDebug   cache:     - !reference [ .pull-push-wrapper-cache ]     - !reference [ .push-deps-cache ]     - !reference [ .pull-push-build-cache ]   rules:     - if: $CI_PIPELINE_SOURCE = \"push\" &amp;&amp; $CI_COMMIT_BRANCH == \"master\" <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0431\u043e\u044f\u0442\u044c\u0441\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043a\u044d\u0448 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u0438 \u0432 <code>master<\/code>, \u0438\u0431\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e. \u0427\u0435\u043c \u0447\u0430\u0449\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u044d\u0448, \u0442\u0435\u043c \u0432\u044b\u0448\u0435 cache-hit \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430\u0445 \u043d\u0430\u0448\u0438\u0445 \u041c\u0420\u043e\u0432. \u041f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u0445 \u0440\u0435\u0431\u0435\u0439\u0437\u0438\u0442\u044c \u0438 \u0434\u0435\u0440\u0436\u0430\u0442\u044c up-to-date \u0441 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u043e\u0439.<\/p>\n<h3>\u0410 \u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u0442\u0430\u043a \u0436\u0435 \u0441 \u043a\u044d\u0448\u043e\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439?<\/h3>\n<p>\u0414\u0430 \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u044d\u0442\u043e \u0442\u0435\u043c\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438.<\/p>\n<p>\u0415\u0441\u0442\u044c \u043b\u0430\u0439\u0444\u0445\u0430\u043a, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f &#171;\u041f\u0435\u0440\u0447\u0430\u0442\u043a\u0430 \u0422\u0430\u043d\u043e\u0441\u0430&#187;. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>policy: pull-push<\/code> \u0434\u043b\u044f GitLab \u043a\u044d\u0448\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439; \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u0434\u0436\u043e\u0431\u044b <strong>cache build<\/strong> \u0443\u0434\u0430\u043b\u044f\u0435\u043c 50% \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0432 <code>$GRADLE_USER_HOME\/caches\/modules-2\/<\/code>. \u041e\u0442\u043b\u0438\u0447\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0441\u043f\u043e\u0441\u043e\u0431.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/post_images\/21e\/c79\/602\/21ec796029b3091e65f67750af911799.jpg\" alt=\"Thanos Pepe meme\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/21e\/c79\/602\/21ec796029b3091e65f67750af911799.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>Thanos Pepe meme<\/figcaption><\/div>\n<\/figure>\n<h4>\u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0438\u043b\u0434 \u043a\u044d\u0448 MR-\u043e\u0432 \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430\u0445 MR-\u043e\u0432<\/h4>\n<blockquote>\n<p>\u042d\u0442\u043e \u0443\u0436\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u043e \u0437\u0432\u0435\u0437\u0434\u043e\u0447\u043a\u043e\u0439.<\/p>\n<\/blockquote>\n<p>\u041c\u043e\u0436\u043d\u043e \u0435\u0449\u0435 \u0441\u0438\u043b\u044c\u043d\u0435\u0435 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u043e\u043d \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u0432 \u041c\u0420\u0430\u0445, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043d\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0433\u043e\u043d\u0435 \u043a\u044d\u0448, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c.<br \/> \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u0435\u0436\u0434\u0443 \u0434\u0436\u043e\u0431\u0430\u043c\u0438 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u0430 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0443 \u043a\u044d\u0448\u0430 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0443\u0445\u043e\u0434\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0435\u043c \u043d\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0436\u043e\u0431\u044b.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/5ba\/861\/123\/5ba8611231f31b041be728cae6014397.png\" alt=\"Branch specific cache keys set\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/5ba\/861\/123\/5ba8611231f31b041be728cae6014397.png\"\/><\/p>\n<div><figcaption>Branch specific cache keys set<\/figcaption><\/div>\n<\/figure>\n<p>\u0413\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0434\u0436\u043e\u0431\u044b \u043d\u0430 \u041c\u0420\u0435 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b:<\/p>\n<ol>\n<li>\n<p>\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 <strong>\u0415\u0421\u0422\u042c<\/strong> \u0432 \u0432\u0435\u0442\u043a\u0435 master. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u043c\u044b \u0441\u043d\u043e\u0432\u0430 \u0438\u0445 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u043f\u043e\u0434\u0442\u044f\u043d\u0435\u043c \u0438\u0437 master.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c <strong>\u041d\u0415 \u0417\u0410\u0414\u0415\u0419\u0421\u0422\u0412\u041e\u0412\u0410\u041d\u042b<\/strong> \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0431\u0438\u043b\u0434\u0435. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u0445 \u043d\u0435 \u044e\u0437\u0430\u043b\u0438, \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u043e\u043d\u0438 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/907\/769\/d3d\/907769d3d70a9c4a5a0ccf7c1f5e6213.svg\"\/><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u0430\u043a\u043e\u0439 \u0447\u0438\u0441\u0442\u043a\u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>caches\/build-cache-1<\/code> <s><sup>\u043d\u0430\u0447\u0430\u043b\u0441\u044f \u0441\u0443\u0449\u0438\u0439 \u043a\u043e\u0448\u043c\u0430\u0440<\/sup><\/s> \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0434\u0438\u0441\u0442\u0438\u043b\u043b\u044f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u0438\u043c \u0434\u043b\u044f \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438\/\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 GitLab \u0440\u0430\u043d\u043d\u0435\u0440\u0430. \u041d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u0435\u043d \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u0442\u043d\u043e\u0433\u043e \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u0430.<\/p>\n<h3>\u0412\u0430\u043a\u0443\u0443\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u044d\u0448\u0430 (\u0434\u0438\u0441\u0442\u0438\u043b\u043b\u044f\u0442)<\/h3>\n<p>\u0414\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0432\u044b\u0448\u0435 \u0441\u0445\u0435\u043c\u044b \u0447\u0438\u0441\u0442\u043a\u0438 \u043a\u044d\u0448\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0435\u0439 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0448\u0430\u0433\u043e\u0432, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u043f\u0438\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>close()<\/code> \u0432 <code>CacheKeysHandlerService<\/code>:<\/p>\n<pre><code class=\"kotlin\">internal abstract class CacheKeysHandlerService @Inject constructor(     gradle: Gradle, ) :     BuildService&lt;CacheKeysHandlerService.Params&gt;,     BuildOperationListener,     AutoCloseable {      \/\/ \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 \u043a\u043e\u0434...      override fun close() {         val cacheKeysFile = parameters.cacheKeysFile.asFile.get()          \/\/ \u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0441 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439, \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0441\u0443\u043d\u0443\u043b\u0438 \u0435\u0433\u043e \u043d\u0430 CI         \/\/ \u0412 \u0444\u0430\u0439\u043b\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043b\u044e\u0447\u0435\u0439 \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u0432\u0448\u0438\u0445 \u0441 master \u0432\u0435\u0442\u043a\u0438, \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0438\u0445         cacheKeysFile.useLines { snapshotCacheKeys -&gt;             for (key in snapshotCacheKeys) {                 check(buildCacheDir.resolve(key).delete()) {                     \"Unable to delete cache key file: $key\"                 }             }         }          \/\/ \u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 \u0444\u0430\u0439\u043b \u043d\u043e\u0432\u044b\u0435 \u043a\u043b\u044e\u0447\u0438\u043a\u0438, \u0434\u0430\u043b\u044c\u0448\u0435 \u043d\u0430 CI \u0440\u0430\u0437\u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0447\u0442\u043e \u0441 \u043d\u0438\u043c\u0438 \u0434\u0435\u043b\u0430\u0442\u044c         cacheKeysFile.bufferedWriter().use { writer -&gt;             for (key in cacheKeys) {                 writer.appendLine(key)             }         }          \/\/ \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438, \u043d\u0435 \u0432\u043e\u0448\u0435\u0434\u0448\u0438\u0435 \u0432 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0431\u0438\u043b\u0434         val unusedCacheKeys = iterateBuildCache { it !in cacheKeys }         for (key in unusedCacheKeys) {             check(buildCacheDir.resolve(key).delete()) {                 \"Unable to delete cache key file: $key\"             }         }     } } <\/code><\/pre>\n<h3>\u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0435\u0439 \u0438\u0437 master \u0432 \u041c\u0420\u044b<\/h3>\n<p>\u0414\u0436\u043e\u0431\u0430, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0430\u044f \u043a\u044d\u0448 \u043d\u0430 CI, \u0447\u0442\u043e \u0433\u043e\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043c\u0435\u0440\u0436\u0435 \u0432 \u043c\u0430\u0441\u0442\u0435\u0440, \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0432 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>$GRADLE_USER_HOME\/caches\/build-cache-1<\/code>, \u043d\u043e \u0438 \u0444\u0430\u0439\u043b\u0438\u043a <code>cache-keys.txt<\/code>. \u0414\u0436\u043e\u0431\u044b, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0435 \u0432 \u041c\u0420\u0430\u0445, \u0431\u0443\u0434\u0443\u0442 \u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u0432\u043e\u0439 \u043a\u044d\u0448 \u043e\u0442 \u043b\u0438\u0448\u043d\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u0443\u044f\u0441\u044c \u043d\u0430 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b. \u0422\u043e, \u0447\u0442\u043e \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f, \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u043f\u0440\u043e\u0433\u043e\u043d\u043e\u0432:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c17\/42e\/1f7\/c1742e1f743366a0a2b22a6c15cc57cb.svg\"\/><\/figure>\n<p>\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448\u0430 \u0432 GitLab:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-build-cache:   - key: cache-build     policy: pull     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/       - cache-keys.txt  # &lt;-- \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438  # \u0423\u0434\u0430\u043b\u044f\u0435\u043c .push-build-cache # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u043e\u0442 \u044d\u0442\u043e: .pull-push-build-cache:   - key: cache-build     policy: pull-push     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/       - cache-keys.txt  # &lt;-- \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438  # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \"branch specific cache\" .pull-push-branch-specific-cache:   - key: \"$CI_JOB_NAME-$CI_COMMIT_REF_SLUG\"     policy: pull-push     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/       # \u0410 \u0432\u043e\u0442 \u0442\u0443\u0442 \u043d\u0435\u0442 `cache-keys.txt`, \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e  <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0435 \u043a\u044d\u0448\u0438 \u043a \u043d\u0430\u0448\u0438\u043c \u0434\u0436\u043e\u0431\u0430\u043c:<\/p>\n<pre><code class=\"yaml\">.base:   variables:     GRADLE_USER_HOME: $CI_PROJECT_DIR\/.gradle   # \u0422\u0443\u0442 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0435\u0449\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043b   before_script:     # \u0412\u0440\u0443\u0431\u0430\u0435\u043c \u043d\u0430\u0448 \u043f\u043b\u0430\u0433\u0438\u043d! \u0410 \u0442\u043e \u043d\u0438\u0447\u043e \u043d\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442     - mkdir -p $GRADLE_USER_HOME     - echo \"com.example.build.cache-keys.enabled=true\" &gt;&gt; $GRADLE_USER_HOME\/gradle.properties     - ...   after_script:     - ...  # \u042d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u041c\u0420\u0435 build:   stage: check   extends: .base   script:     - .\/gradlew :app:assembleDebug   cache:     - !reference [ .pull-wrapper-cache ]     - !reference [ .pull-deps-cache ]     - !reference [ .pull-build-cache ]     - !reference [ .pull-push-branch-specific-cache ]  # &lt;-- \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438   rules:     - if: $CI_PIPELINE_SOURCE = \"merge_request_event\"  # \u042d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u044f \u041c\u0420\u0430 cache build:   stage: post-check   extends: .base   script:     - .\/gradlew :app:assembleDebug   cache:     - !reference [ .pull-push-wrapper-cache ]     - !reference [ .push-deps-cache ]     - !reference [ .push-push-build-cache ]  # &lt;-- \u0418\u0437\u043c\u0435\u043d\u0438\u043b\u0438   rules:     - if: $CI_PIPELINE_SOURCE = \"push\" &amp;&amp; $CI_COMMIT_BRANCH == \"master\" <\/code><\/pre>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u0443\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u041c\u0420\u0430, \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0433\u043e\u043d \u0434\u0436\u043e\u0431\u044b build \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u044d\u0448 \u0438\u0437 \u0432\u0435\u0442\u043a\u0438 master. \u0427\u0435\u043c \u0431\u043b\u0438\u0436\u0435 \u0432\u0430\u0448\u0430 \u0432\u0435\u0442\u043a\u0430 \u043a \u0432\u0435\u0442\u043a\u0435 master, \u0442\u0435\u043c \u0432\u044b\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 cache-hit.<\/p>\n<p>\u041f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0445 \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u0445 \u041c\u0420\u0430 \u0432 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a \u043a\u044d\u0448\u0443 \u0438\u0437 master \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0438 \u043a\u044d\u0448 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u0430.<\/p>\n<h3>\u041a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u0431\u0430\u0436\u0438\u0442\u044c?<\/h3>\n<p>\u041d\u0435\u043b\u044c\u0437\u044f \u0432\u0435\u0440\u0438\u0442\u044c \u043c\u043d\u0435 \u043d\u0430 \u0441\u043b\u043e\u0432\u043e. \u0415\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0436\u0433\u0443\u0447\u0435\u0435 \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u043e\u0442\u0441\u044e\u0434\u0430, \u043d\u043e \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c \u0447\u0442\u043e \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. \u0414\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code>$GRADLE_USER_HOME<\/code>. \u041f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043d\u0435 \u0443\u043a\u0430\u0437\u043d\u0430, Gradle \u0445\u0440\u0430\u043d\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 <code>$USER_HOME\/.gradle<\/code>, \u0438 \u043f\u0440\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u0442\u044b \u0431\u0443\u0434\u0435\u0448\u044c \u0434\u0440\u043e\u043f\u0430\u0442\u044c \u0431\u0438\u043b\u0434 \u043a\u044d\u0448 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0443 \u0442\u0435\u0431\u044f \u043d\u0430 \u043a\u043e\u043c\u043f\u0443\u043a\u0442\u0435\u0440\u0435.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u044e, \u0447\u0442\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0442\u044c configuration cache \u0438 \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0437\u0430\u043c\u0435\u0440\u043e\u043c \u0447\u0438\u0441\u0442\u0438\u0442\u044c build \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0442\u0432\u043e\u0439 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 bash \u0441\u043a\u0440\u0438\u043f\u0442 \u043b\u0438\u0431\u043e \u0447\u0435\u0440\u0435\u0437 <code>.\/gradlew clean<\/code>.<\/p>\n<p>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043f\u0435\u0440\u0435\u0434 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0435\u043c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f:<\/p>\n<ol start=\"0\">\n<li>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0448\u044c \u043f\u043b\u0430\u0433\u0438\u043d \u0447\u0435\u0440\u0435\u0437 <code>gradle.properties<\/code>:<\/p>\n<pre><code>com.example.build.cache-keys.enabled=true <\/code><\/pre>\n<\/li>\n<li>\n<p>\u0423\u0434\u0430\u043b\u044f\u0435\u0448\u044c \u0444\u0430\u0439\u043b\u0438\u043a <code>cache-keys.txt<\/code>, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0441\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u0448\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043e\u043f\u0446\u0438\u0435\u0439 <code>--scan<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u0430\u043b\u044f\u0435\u0448\u044c \u0444\u0430\u0439\u043b\u0438\u043a <code>cache-keys.txt<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0441\u0442\u0438\u0448\u044c build \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u0430\u043b\u044f\u0435\u0448\u044c \u0444\u0430\u0439\u043b\u0438\u043a <code>cache-keys.txt<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u0438\u0445 \u0448\u0430\u0433\u043e\u0432 \u0443 \u0442\u0435\u0431\u044f \u0431\u0443\u0434\u0435\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u044b \u0412\u0421\u0415 \u043a\u043b\u044e\u0447\u0438, \u043a\u0440\u043e\u043c\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 \u0431\u0438\u043b\u0434\u0435. \u0424\u0430\u0439\u043b\u0438\u043a \u0441 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u043c\u044b \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0447\u0442\u043e\u0431\u044b \u0432 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0431\u0438\u043b\u0434\u0435 \u043d\u0430\u0448 \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0435 \u0434\u0440\u043e\u043f\u0430\u043b \u043a\u043b\u044e\u0447\u0438 \u0438\u0437 \u043d\u0435\u0433\u043e, \u0434\u0443\u043c\u0430\u044f \u0447\u0442\u043e \u044d\u0442\u043e \u043a\u043b\u044e\u0447\u0438 \u0438\u0437 master \u0432\u0435\u0442\u043a\u0438.<\/p>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u0448\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043e\u043f\u0446\u0438\u0435\u0439 <code>--scan<\/code>. \u041d\u0430 \u0442\u043e\u043c \u043a\u044d\u0448\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0447\u0438\u0441\u0442\u043a\u0438 \u0441 \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0431\u0438\u043b\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c BuildScan \u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u0448\u044c Cache Hit. \u041e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c 100% (\u043b\u0438\u0431\u043e \u0431\u043e\u043b\u0435\u0435 95%, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043a\u044d\u0448-\u043c\u0438\u0441\u0441\u0430\u043c\u0438).<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0439 \u0432 \u043a\u044d\u0448 \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u0430, \u043d\u043e \u044d\u0442\u043e \u0442\u0435\u043c\u0430 \u0443\u0436\u0435 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0430 \u0432 <a href=\"https:\/\/mobiusconf.com\/en\/archive\/2024%20Spring\/talks\/f9f7e56446a7462eb8e3e4ba6cc64770\/?referer=%2Fen%2Farchive%2F2024%2520Spring%2Fpartners%2F42a2ee1c-85c9-4ceb-ba77-a0fe87f91cec%2F\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u043e\u0442 \u0422\u0438\u043d\u044c\u043a\u043e\u0444\u0444 \u043d\u0430 Mobius Spring 2024<\/a>.<\/p>\n<h2>\u0418\u0442\u043e\u0433\u0438<\/h2>\n<h3>\u041a\u0430\u043a\u0438\u0435 \u0435\u0441\u0442\u044c \u043c\u0438\u043d\u0443\u0441\u044b \u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438 \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c?<\/h3>\n<h4>\u041d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u0447\u0438\u0441\u0442\u043a\u0430 \u043a\u044d\u0448\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h4>\n<p>\u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u043d\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0438 \u0447\u0438\u0441\u0442\u043a\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0441 \u043d\u0438\u043c\u0438 \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u0434\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u044f \u0442\u043e\u0436\u0435 \u043d\u0430\u043f\u0438\u0448\u0443 \u0437\u0430\u043c\u0435\u0442\u043a\u0443 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e:<\/strong> \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0443\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u0430\u0436\u0435 \u0434\u043b\u044f \u0441\u0440\u0435\u0434\u043d\u0438\u0445 \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432.<\/p>\n<h4>\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0438 gradle \u043b\u043e\u043c\u0430\u044e\u0442 \u043b\u043e\u0433\u0438\u043a\u0443<\/h4>\n<p>\u042f \u0445\u043e\u0442\u0435\u043b \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0442\u044c \u0441\u0432\u043e\u0435\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0434\u043e\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.<\/p>\n<h4>\u041d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438<\/h4>\n<p>\u042d\u0442\u043e \u043f\u0440\u0430\u0432\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0441\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0435\u0441\u043b\u0438 \u043a\u043b\u044e\u0447\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e. \u041d\u043e \u044f \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0448\u0435\u043b \u043d\u0430 \u044d\u0442\u043e\u0442 \u0448\u0430\u0433 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0442\u0430\u0441\u043e\u043a \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 build cache. \u041f\u043e \u043c\u043e\u0438\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0435\u0439 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u0437 500 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c \u0434\u043e 200 \u043a\u0438\u043b\u043e\u0431\u0430\u0439\u0442 \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043c\u044b\u0441\u043b\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u0442.<\/p>\n<h4>\u0421\u043b\u043e\u0436\u043d\u0430<\/h4>\n<p>\u0410 \u043a\u043e\u043c\u0443 \u0449\u0430\u0441 \u043b\u0435\u0433\u043a\u043e&#8230;<\/p>\n<h3>\u041e \u0445\u043e\u0440\u043e\u0448\u0435\u043c<\/h3>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0435 \u0437\u0434\u0435\u0441\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0431\u0438\u043b\u0434-\u0442\u0430\u0439\u043c \u043d\u0430 CI, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u043d\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u044f\u0441\u044c \u0432 impact-\u0430\u043d\u0430\u043b\u0438\u0437. \u0412 \u043e\u0431\u0449\u0435\u043c, \u0442\u043e\u043f \u0437\u0430 \u0441\u0432\u043e\u0438 \u0434\u0435\u043d\u044c\u0433\u0438.<\/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\/832976\/\"> https:\/\/habr.com\/ru\/articles\/832976\/<\/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<h2>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442<\/h2>\n<p>\u042d\u0442\u0430 \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u043c-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0433\u0430\u0439\u0434\u0430 \u043f\u043e \u0431\u044e\u0434\u0436\u0435\u0442\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 GitLab \u043a\u044d\u0448\u0435\u0439 \u0434\u043b\u044f Gradle \u0432 Android \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Gradle Enterprise \u0438 Remote Build Cache. \u0412 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043c\u0430\u043b\u043e\u0432\u0430\u0442\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043a\u044d\u0448\u0438 Gradle \u043d\u0430 CI, \u0438 \u0435\u0449\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u0412 \u043f\u0440\u0438\u0434\u0430\u0447\u0443, \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e-\u0442\u043e \u0437\u0430\u0434\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432 Gradle Slack, \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435 Gradle \u0438\u043b\u0438 \u043d\u0430 StackOverflow, \u043f\u0440\u0438\u0431\u0435\u0433\u0430\u044e\u0442 \u0443\u0432\u043b\u0430\u0436\u043d\u044f\u0435\u043c\u044b\u0435 \u0438\u0437 Gradle \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e\u0442 \u043d\u0435 \u043a\u043e\u043f\u0430\u0442\u044c \u0432 \u043d\u0443\u0436\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443, \u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0443\u043f\u0438\u0442\u044c Gradle Enterprise (\u0438\u043b\u0438 \u043a\u0430\u043a \u043e\u043d \u0442\u0430\u043c \u0449\u0430\u0441 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f).<\/p>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u043e\u043f\u044b\u0442 \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u044f \u0431\u0438\u043b\u0434-\u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0432 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u043e\u043c Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0418 \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043b\u0430\u0439\u0444\u0445\u0430\u043a\u0430\u043c\u0438 \u0441 \u0442\u0435\u043c\u0438, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438 \u0431\u0438\u043b\u0434\u0430 \u043d\u0430 CI \u0432 \u0441\u0432\u043e\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h2>\n<blockquote>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e Gradle \u0433\u043e\u0432\u043d\u043e <br \/> \u2014 \u0414\u0436\u0435\u0439\u0441\u043e\u043d \u0421\u0442\u044d\u0442\u0445\u044d\u043c<\/p>\n<\/blockquote>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0443\u0432\u0430\u0436\u0430\u044e\u0449\u0438\u0439 \u0441\u0435\u0431\u044f \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043c\u0435\u0435\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 CI\/CD, \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0432 GitLab. \u0421 \u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u043e\u0432 \u0441\u0431\u043e\u0440\u043e\u043a\/\u0442\u0435\u0441\u0442\u043e\u0432\/\u043b\u0438\u043d\u0442\u0435\u0440\u0430 \u0438 \u0442.\u0434. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0430\u0448\u0435\u0433\u043e \u041c\u0420 \u043f\u0435\u0440\u0435\u0432\u0430\u043b\u0438\u0432\u0430\u0435\u0442 \u0437\u0430 \u0432\u0441\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0447\u0442\u043e-\u0442\u043e \u0441 \u044d\u0442\u0438\u043c \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<h2>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435 \u043c\u043d\u043e\u044e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u043e\u0439 \u0434\u043e 500 \u043c\u043e\u0434\u0443\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0431\u043e\u043b\u044c\u0448\u0435, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435 \u043b\u0443\u0447\u0448\u0435 \u043c\u0435\u043d\u044f \u043a\u0430\u043a \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u043b\u0434\u044b.<\/p>\n<p>\u0413\u043e\u0432\u043e\u0440\u044f &#171;500 \u043c\u043e\u0434\u0443\u043b\u0435\u0439&#187; \u044f \u0438\u043c\u0435\u044e \u0432\u0432\u0438\u0434\u0443 500 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438\u0437 <a href=\"https:\/\/www.youtube.com\/watch?v=oAQlKiF91Ks\" rel=\"noopener noreferrer nofollow\">\u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0421\u0442\u0435\u043f\u0430\u043d\u0430 \u0413\u043e\u043d\u0447\u0430\u0440\u043e\u0432\u0430<\/a>.<\/p>\n<h3>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e<\/h3>\n<h4>\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043f\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e<\/h4>\n<blockquote>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u043a\u044d\u0448 \u0432 \u043e\u0434\u043d\u0438\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u0432 \u0434\u0440\u0443\u0433\u0438\u0445.<\/p>\n<\/blockquote>\n<p>\u0412 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430\u0434\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043a\u044d\u0448\u0430 \u0432 GitLab, \u044d\u0442\u043e \u043d\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0435\u0441\u0438\u0442 \u043a\u044d\u0448, \u0442\u0435\u043c \u0434\u043e\u043b\u044c\u0448\u0435 \u043e\u043d \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0430\u0440\u0445\u0438\u0432 \u0438 \u043e\u0442\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u043b\u0430\u043a\u043e. \u0414\u0430\u0436\u0435 Gradle Remote Build Cache \u043d\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0430\u044f \u0448\u0442\u0443\u043a\u0430, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 Remote Build Cache \u043f\u043b\u0430\u0433\u0438\u043d \u0438 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e Docker \u043d\u043e\u0434\u0443. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435 \u0432\u0441\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u044d\u0448.<\/p>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u0430\u044f \u043c\u043d\u043e\u044e \u0441\u0445\u0435\u043c\u0430 \u0442\u0430\u043a\u0430\u044f:<\/p>\n<ul>\n<li>\n<p>\u0423 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0435\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0432\u0435\u0442\u043a\u0430, \u043f\u0443\u0441\u0442\u044c \u043e\u043d\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>master<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u0442\u044c <code>feature<\/code>-\u0432\u0435\u0442\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0432\u043e\u0435\u0439 \u0436\u0438\u0437\u043d\u0438 \u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 <code>master<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u0438 \u0432 <code>master<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0430\u0439\u043f, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0431\u0438\u043b\u0434 \u043a\u044d\u0448. \u0415\u0441\u043b\u0438 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u0438, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u043d\u0430 <code>feature<\/code>-\u0432\u0435\u0442\u043a\u0430\u0445, \u043e\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043a\u044d\u0448 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0432\u0435\u0442\u043a\u0435 <code>master<\/code>.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"\">\n<div><figcaption>Different pipeline purposes<\/figcaption><\/div>\n<\/figure>\n<h4>\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 GitLab \u043a\u044d\u0448\u0435\u0439 \u043f\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e<\/h4>\n<blockquote>\n<p>\u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 Gradle Wrapper \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438<\/p>\n<\/blockquote>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0434 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0436\u0435 \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0438 \u0435\u0449\u0435 \u0440\u0435\u0436\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u0441\u0438\u044f Gradle. \u042f \u0441\u0447\u0438\u0442\u0430\u044e \u0447\u0442\u043e \u043a\u044d\u0448 \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439. \u0421\u0443\u043c\u043c\u0430\u0440\u043d\u044b\u0439 \u0432\u0435\u0441 \u0430\u0440\u0445\u0438\u0432\u0430 \u0441 \u043e\u0431\u0449\u0438\u043c \u043a\u044d\u0448\u043e\u043c \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u0442 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e s3 \u043b\u0438\u043c\u0438\u0442\u044b. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435 \u0434\u0436\u043e\u0431\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0443\u0436\u043d\u044b \u043d\u0435 \u0432\u0441\u0435 \u0432\u0438\u0434\u044b \u043a\u044d\u0448\u0430, \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043b\u0438\u0448\u043d\u0435\u0433\u043e.<\/p>\n<figure class=\"\">\n<div><figcaption>Different types of Gradle cache<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0441\u0435 \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 CI, Gradle \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>$GRADLE_USER_HOME<\/code>. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0434\u0436\u043e\u0431:<\/p>\n<pre><code class=\"yaml\">some job:   variables:     GRADLE_USER_HOME: $CI_PROJECT_DIR\/.gradle <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u044f \u0431\u0443\u0434\u0443 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0447\u0442\u043e <code>$GRADLE_USER_HOME<\/code> \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u043e\u0439.<\/p>\n<pre><code>$GRADLE_USER_HOME\/ \u251c\u2500\u2500 caches\/ \u2502   \u251c\u2500\u2500 build-cache-1\/ &lt;- \u0411\u0438\u043b\u0434-\u043a\u044d\u0448 \u2502   \u2514\u2500\u2500 modules-2\/ &lt;- \u043a\u044d\u0448 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u251c\u2500\u2500 notifications\/ &lt;- \u043c\u0443\u0441\u043e\u0440 \u0434\u043b\u044f wrapper \u2514\u2500\u2500 wrapper\/ &lt;- \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b wrapper <\/code><\/pre>\n<h4>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 GitLab \u043a\u044d\u0448 \u0434\u043b\u044f Gradle Wrapper<\/h4>\n<p>\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b Gradle \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 <code>$GRADLE_USER_HOME\/wrapper\/<\/code>, \u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0443\u0441\u043e\u0440 \u043e\u0442 \u043d\u0435\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <code>$GRADLE_USER_HOME\/notifications\/<\/code>. \u0425\u043e\u0440\u043e\u0448\u043e \u0431\u044b \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 GitLab cache key:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-wrapper-cache:   - key: cache-wrapper     policy: pull     unprotect: true     paths:       - .gradle\/wrapper\/       - .gradle\/notifications\/  .pull-push-wrapper-cache:   - key: cache-wrapper     policy: pull-push     unprotect: true     paths:       - .gradle\/wrapper\/       - .gradle\/notifications\/ <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">cache build:   ...   cache:     - !reference [ .pull-push-wrapper-cache ] <\/code><\/pre>\n<p>\u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Gradle \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0447\u0442\u043e \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u043e\u0432 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f. \u041f\u043e\u0432\u0435\u0440\u0438\u043c \u0438\u043c \u043d\u0430 \u0441\u043b\u043e\u0432\u043e. \u041a\u044d\u0448 \u0441 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0430\u043c\u0438 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0437\u0440\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u0438\u043b\u044c\u043d\u043e.<\/p>\n<p>\u0412 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">lint:   ...   cache:     - !reference [ .pull-wrapper-cache ] <\/code><\/pre>\n<p>\u0414\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b Gradle \u043d\u0435 \u0432\u0435\u0441\u044f\u0442 \u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0430\u0440\u0445\u0438\u0432\u044b \u0441 \u043d\u0438\u043c\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0436\u043e\u0431\u0443 \u0431\u044b\u0441\u0442\u0440\u043e.<\/p>\n<h4>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 GitLab \u043a\u044d\u0448 \u0434\u043b\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h4>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u044d\u0442\u043e AAR \u0438 JAR \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0432\u0441\u0435\u0445 \u043b\u0438\u0431 \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435. Gradle \u0438\u0445 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 <code>$GRADLE_USER_HOME\/caches\/modules-2\/<\/code>. \u0412\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u044d\u0448\u0430\u043c\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-deps-cache:   - key: cache-deps     policy: pull     unprotect: true     paths:       - .gradle\/caches\/modules-2\/  .push-deps-cache:   - key: cache-deps     policy: push     unprotect: true     paths:       - .gradle\/caches\/modules-2\/ <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0432 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">cache build:   ...   cache:     - !reference [ .push-deps-cache ] <\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043a\u0430\u0447\u0430\u0435\u0442 \u0438\u0445 \u0437\u0430\u043d\u043e\u0432\u043e. \u041e\u0431\u044a\u044f\u0441\u043d\u044f\u044e \u044d\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u0412 \u0434\u0436\u043e\u0431\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0442 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"yaml\">lint:   ...   cache:     - !reference [ .pull-deps-cache ] <\/code><\/pre>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u0435\u0441\u044f\u0442 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b gradle, \u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u0447\u0435\u043c \u0431\u0438\u043b\u0434 \u043a\u044d\u0448.<\/p>\n<h4>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 GitLab \u043a\u044d\u0448 \u0434\u043b\u044f Gradle build cache<\/h4>\n<p>\u0421\u0430\u043c\u0430\u044f \u0442\u044f\u0436\u0435\u043b\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a\u044d\u0448\u0430 \u2014 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448.<\/p>\n<p>\u0411\u0438\u043b\u0434-\u043a\u044d\u0448 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <code>$GRADLE_USER_HOME\/caches\/build-cache-1\/<\/code>. \u0412\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0442, \u0442\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0433\u0440\u043e\u043c\u043d\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043d\u044f \u0441 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448\u043e\u043c:<\/p>\n<pre><code class=\"yaml\"># cache.yml  .pull-build-cache:   - key: cache-build     policy: pull     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/  .push-build-cache:   - key: cache-build     policy: push     unprotect: true     paths:       - .gradle\/caches\/build-cache-1\/ <\/code><\/pre>\n<p>\u0414\u0436\u043e\u0431\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"yaml\">cache build:   ...   cache:     - !reference [ .push-build-cache ] <\/code><\/pre>\n<p>\u0418 \u0441\u043d\u043e\u0432\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0447\u0442\u043e \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u044d\u0448\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u044d\u0448\u0430 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442. \u041e\u0431\u044a\u044f\u0441\u043d\u044f\u044e \u044d\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u0414\u0436\u043e\u0431\u044b \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0449\u0438\u0435 \u0431\u0438\u043b\u0434 \u043a\u044d\u0448 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c:<\/p>\n<pre><code class=\"yaml\">test:   ...   cache:     - !reference [ .pull-build-cache ] <\/code><\/pre>\n<h4>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u043e\u0435\u0434\u0438\u043d\u043e, \u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"yaml\">.base:   variables:     GRADLE_USER_HOME: $CI_PROJECT_DIR\/.gradle   # \u0422\u0443\u0442 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0435\u0449\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043b   before_script:     - ...   after_script:     - ...  # \u042d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u041c\u0420\u0435 build:   stage: check   extends: .base   script:     - .\/gradlew :app:assembleDebug   cache:     - !reference [ .pull-wrapper-cache ]     - !reference [ .pull-deps-cache ]     - !reference [ .pull-build-cache ]   rules:     - if: $CI_PIPELINE_SOURCE = \"merge_request_event\"  # \u042d\u0442\u0430 \u0434\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u044f \u041c\u0420\u0430 cache build:   stage: post-check   extends: .base   script:     - .\/gradlew :app:assembleDebug   cache:     - !reference [ .pull-push-wrapper-cache ]     - !reference [ .push-deps-cache ]     - !reference [ .push-build-cache ]   rules:     - if: $CI_PIPELINE_SOURCE = \"push\" &amp;&amp; $CI_COMMIT_BRANCH == \"master\" <\/code><\/pre>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0441\u0431\u043e\u0440\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u0445 \u041c\u0420\u0430 \u0431\u0443\u0434\u0435\u0442 \u0443\u0436\u0435 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0430. \u041d\u043e \u043a\u0430\u043a \u043b\u044e\u0431\u044f\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u0441\u043e\u0435\u0432\u044b\u0435 \u0430\u0439\u0442\u0438\u0448\u043d\u0438\u043a\u0438, &#171;\u0442\u0443\u0442 \u0435\u0441\u0442\u044c \u0442\u043e\u0447\u043a\u0438 \u0440\u043e\u0441\u0442\u0430&#187;.<\/p>\n<figure class=\"\">\n<div><figcaption>Build cache isn&#8217;t reused<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0434\u0436\u043e\u0431\u0435 <code>cache build<\/code> \u043d\u0435 \u0434\u0430\u0435\u0442\u0441\u044f \u043a\u044d\u0448 \u043e\u0442 \u0435\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432. \u0422\u043e \u0435\u0441\u0442\u044c \u0431\u0438\u043b\u0434 \u0438 \u0437\u0430\u043a\u0430\u0447\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0432 \u044d\u0442\u043e\u0439 \u0434\u0436\u043e\u0431\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441 \u043d\u0443\u043b\u044f. \u0412\u0441\u0435 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e Gradle \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435 \u043e\u0447\u0438\u0449\u0430\u0435\u0442 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043a\u044d\u0448 \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u044d\u0448\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u043f\u0440\u043e\u0433\u043e\u043d\u043e\u0432, \u0442\u043e \u043a\u044d\u0448 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u0441 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e. \u041e\u043d \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u0432\u0430\u043b\u0438\u0442 \u0437\u0430 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043e\u0442\u043c\u0435\u0442\u043a\u0443 \u0432 5 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0432\u044b \u0434\u0430\u0436\u0435 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 s3. \u041a\u043e\u0440\u043e\u0447\u0435, \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043d\u0435\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u0440\u043e\u0441\u0442\u0430 GitLab \u043a\u044d\u0448\u0430.<\/p>\n<p>\u041f\u043e\u043b\u043d\u043e\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0431\u0438\u043b\u0434-\u043a\u044d\u0448\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0434\u043e\u043b\u0433\u0438\u043c \u043f\u0440\u043e\u0433\u043e\u043d\u0430\u043c. \u041d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u043b\u0433\u0438\u043c, \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u0434\u0443\u043c\u0430\u0442\u044c\u0441\u044f, \u0430 \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e \u043b\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043a\u044d\u0448 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u043b\u0438\u0432\u0430\u043d\u0438\u0438 \u0432 <code>master<\/code>, \u0438\u043b\u0438 \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e?<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0433\u043b\u0438 \u0441\u0430\u043c\u0438 \u043e\u0447\u0438\u0449\u0430\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 cache entry \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>$GRADLE_USER_HOME\/caches\/build-cache-1\/<\/code>, \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u0443\u043f\u0435\u0440 \u0443\u0434\u043e\u0431\u043d\u043e, \u043c\u043c\u043c\u043c?<\/p>\n<h4>\u0423\u043f\u0441, \u043a\u0443\u043f\u0438\u0442\u0435 Gradle Enterprise<\/h4>\n<p>\u041d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 Gradle Enterprise, \u043d\u043e \u0437\u0430 \u043d\u0435\u0433\u043e \u0443 \u0432\u0430\u0441 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0434\u0435\u043d\u044f\u043a. \u0410 \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u0411\u043e\u0433\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043c\u043e\u0439, \u0442\u043e \u0432\u0430\u043c \u0434\u0430\u0436\u0435 \u043d\u0435 \u043f\u0440\u043e\u0434\u0430\u0434\u0443\u0442. \u0412\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438 Gradle \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u043f\u0446\u0438\u0438 <code>--scan<\/code>. \u041d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440 \u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 CI \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u041f\u0440\u043e \u0442\u043e \u043a\u0430\u043a \u0441\u043b\u043e\u043c\u0430\u0442\u044c Gradle Enterprise \u043f\u043b\u0430\u0433\u0438\u043d \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0431\u0438\u043b\u0434 \u0441\u043a\u0430\u043d\u0430\u043c\u0438 \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u043c\u0435\u0442\u043a\u0443. \u0414\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438 \u043d\u0430\u0448\u0435\u043b \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443.<\/p>\n<figure class=\"\">\n<div><figcaption>POV: You dig down into Gradle<\/figcaption><\/div>\n<\/figure>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441-\u043c\u043e\u0434\u0435\u043b\u044c Gradle \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043d\u0430 \u043d\u0435\u043d\u0430\u0432\u0438\u0441\u0442\u0438 \u043a \u043b\u044e\u0434\u044f\u043c, \u043c\u044b \u0442\u0430\u043a\u043e\u0435 \u043e\u0441\u0443\u0436\u0434\u0430\u0435\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0435\u043d\u044f\u043a \u0438\u043c \u043d\u0435 \u0434\u0430\u0434\u0438\u043c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0431\u0435\u0437 Enterprise \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438 \u043e\u0442 \u0431\u0438\u043b\u0434\u043e\u0432 \u043d\u0430 CI.<\/p>\n<h3>\u0412\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u043c \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0438<\/h3>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0435\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0431\u0438\u043b\u0434\u0430, \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c gradle internal api. \u0425\u043e\u0440\u043e\u0448\u0435\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u0434\u0430\u043b\u044c\u0448\u0435 \u0434\u0435\u043b\u0430\u0435\u043c, \u0435\u0441\u0442\u044c \u0432 <a href=\"https:\/\/mobiusconf.com\/en\/archive\/2024%20Spring\/talks\/f9f7e56446a7462eb8e3e4ba6cc64770\/?referer=%2Fen%2Farchive%2F2024%2520Spring%2Fpartners%2F42a2ee1c-85c9-4ceb-ba77-a0fe87f91cec%2F\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u043e\u0442 \u0422\u0438\u043d\u044c\u043a\u043e\u0444\u0444 \u043d\u0430 Mobius Spring 2024<\/a>.<\/p>\n<h4>\u041f\u0438\u0448\u0435\u043c BuildService<\/h4>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0441\u0435 \u0431\u0438\u043b\u0434-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0431\u0438\u043b\u0434\u0430 \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u044d\u0448-\u043a\u043b\u044e\u0447\u0435\u0439 \u0432 \u0444\u0430\u0439\u043b:<\/p>\n<pre><code class=\"kotlin\">internal abstract class CacheKeysHandlerService :     BuildService&lt;CacheKeysHandlerService.Params&gt;,     BuildOperationListener,     AutoCloseable {      interface Params : BuildServiceParameters {         val cacheKeysFile: RegularFileProperty     }      private val cacheKeys: MutableSet&lt;String&gt; = ConcurrentHashMap.newKeySet()      override fun started(descriptor: BuildOperationDescriptor, event: OperationStartEvent) {         \/* no-op *\/     }      override fun progress(identifier: OperationIdentifier, event: OperationProgressEvent) {         \/* no-op *\/     }      override fun finished(descriptor: BuildOperationDescriptor, event: OperationFinishEvent) {         when (val details = descriptor.details) <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-427991","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/427991","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=427991"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/427991\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=427991"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=427991"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=427991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}