
Что может быть проще? Пишем команду сборкиgradle clean buildи все готово. На первый взгяд все действительно так, и займет это немного времени. Но со временем кодовая база и, соответственно, количество тестов (ну я очень на это надесь) будет расти, вы не успеете опомниться как сборка будет у вас занимать уже 10 или больше минут
Давайте подумаем что нам может в этом помочь? А для этого проанализируем основные шаги этого процесса:
- Разрешение зависимостей на внешние библиотеки 
- Компиляция Java кода 
- Прогон тестов 
Бьем проект на модули
А так же вспомним (или узнаем) про такую фичу gradle как build cache. Как она может нам помочь? Ведь по факту, если мы внесем в java код какое либо измение, это вызовет перекомпиляцию кода и прогон всех тестов. В этом случае нам может помочь модульность проекта. Если у нас код довольно сильно сегментирован (например по доменным моделям), и зачастую в рамках выполнения задач мы вносим изменения только в какую либо часть проекта - то нет необходимости перекомпилировать весь проект и выполнять абсолютно все тесты.
Например у нас какой либо проект интернет магазина, у него есть несколько основных доменов:
- account (клиенты) 
- product (товары) 
- orders (заказы, этот модуль уже в свою очередь зависит от обоих модулей account и product) 
Например вы вносите изменения в
- модуль account - это вызовет перекомпиляцию модуля account и orders (как зависимого) и выполнит в них тесты. Модуль product не нужно перекомпилировать и выполнять в нем тесты, т.к. код не менялся 
- модуль orders - это вызовет перекомпиляцию только этого модуля и выполнение его тестов. Модули account и product остаются не тронутыми - профита тут уже гораздо больше! 
Итак, наш скрипт запуска уже выглядит так: gradle clean build --build-cache
Запуск на CI
Окей, проверили локально - все супер, повторный запуск команды отрабатывает за секунды, отпрявлям все это на Gitlab CI. И что в итоге видим? А никакого профита нет. Конечно же, каждая джоба выполняется в изолированном контейнере, и в нем нет никаких кэшей, каждый раз выполянется загрузка всех зависимостей с Maven Cental, каждый раз проект компилируется, и каждый раз выполняются все тесты.
Нужно как то переносить "артефакты" между сборками. Тут нам может помочь Gitlab Cache. Окей, инструмент у нас нас есть, теперь нужно определиться, что же мы хотим переносить.
Кэшируем зависимости
Загруженные зависимости по умолчанию хранятся в ${USER_HOME}/.gradle
build:
  stage: build
  image: gradle:7.2-jdk17
  before_script:
    - export GRADLE_USER_HOME=`pwd`/.gradle_home
  script:
    - gradle clean build check --stacktrace --info --build-cache
  cache:
    - key: dep-cache
      paths:
        - .gradle_homeТеперь каждый раз не будут загружаться зависимости, а будут кэшироваться (скорее всего в s3, смотря как настоен ваш Gitlab). Это хоть и не бесплатно, как локальное хранение, но все равно быстрее чем походы во внешнюю сеть.
Кэшируем результаты билда
Дальше нам нужно как то кэшировать результаты компиляции проекта и результатов тестов. Артефакты лежат по умолчанию в папке build в каждом модуле. Прописывать кажду папку вручную не вариант, мы же программисты. Давайте изменим расположение buildDir в каждом моделе. Для этого внесем изменения в корневой build.gradle
ext {
    set('rootProjectDir', "${projectDir}")
}
allprojects {
    buildDir = "${rootProjectDir}/.build/${project.name}/build"
}и добавляем папку .build  из корня проекта под кэш.
cache:
  - key: build-cache
    paths:
      - .buildНа данном шаге мы должны уже получить какой то профит от проделанной работы.
Немного про TestContainers
Давайте рассмотрим еще случай - например использование TestContainers для докеризации окружения в тестах. Здесь есть момент - что когда мы находимся внутри контейнера при запуске тестов мы будем каждый раз загружать образы для внутренних контрейнеров. Если у вас есть корпоративный docker hub (кэширующий прокси), то мы можем подсказать путь для более быстрой загрузки из него:
build:
  stage: build
  image: gradle:7.2-jdk17
  before_script:
    - export GRADLE_USER_HOME=`pwd`/.gradle_home
    - export TESTCONTAINERS_RYUK_CONTAINER_IMAGE=my-docker-hub.io/testcontainers/ryuk:0.3.3
  script:
    - gradle clean build check --stacktrace --info --build-cacheЛибо же пишем код ручками.
P.S. Что не надо бить монолит на модули, а разносить на микросервисы писать замечания не стоит - цель была показать возможность конфигурации buildDir
Комментарии (5)
 - isicju26.01.2022 14:05+1- Кто ненавидит грэдл пожалуйста плюсаните этот комментарий. Хочу понять насколько я одинок. 
 
           
 

Kalinavich
иии для чего этот нам мануал читать?
pavel_nv Автор
Так никто не заставляет же. Демократия в действии. Надеюсь кому то будет полезным.