Кэширование зависимостей в GitHub Action
GitHub Actions предоставляет два способа хранения файлов: кэширование для таких вещей, как dependencies
, и artifacts
для результатов работы, таких как логи или бинарники. Хотя звучат они похоже, используются они для разных целей. Так, мы будем использовать кэширование, чтобы ускорить выполнение рабочих процессов.
Ещё один момент: доступ к кэшу будет ограничен только несколькими ветками: current branch
, base branch
для pull request
и default branch
. Кэши, созданные в несвязанных ветках, будут недоступны, но в большинстве случаев это не повлияет на нас, поскольку мы обычно работаем либо с текущей, либо с базовой веткой.
Правильное использование кэширования может помочь сократить время сборки, особенно для проектов, чьи зависимости меняются нечасто.
Выбор правильного ключа кэша
Можно создавать ключи кэша на основе метаданных, например хэшей ОС или коммитов, позволяющие повторно использовать зависимости только в случае крайней необходимости. Также можно использовать ключи восстановления для получения близких соответствий для кэшей, что поможет минимизировать время пересборки.
Как правило, для рабочих процессов, выполняющихся на нескольких ОС, хорошей практикой является изоляция кэшей для каждой ОС, позволяющая избежать лишних пересборок между платформами. Иногда можно даже использовать временные кэши, действительные только для одного запуска, что удобно, когда не требуется длительное повторное использование.
- uses: actions/cache@v4
with:
path: path/to/dependencies
# Генерирование ключа кэша на основе хэша lockfiles
key: cache-${{ hashFiles('**/lockfiles') }}
- uses: actions/cache@v4
with:
path: path/to/dependencies
key: cache-${{ hashFiles('**/lockfiles') }}
# Восстановление ключей для ближайших совпадений. Это минимизирует время, затрачиваемое на загрузку новых зависимостей
restore-keys: |
cache-npm-
- uses: actions/cache@v4
with:
path: path/to/dependencies
#key: cache-${{ hashFiles('**/lockfiles') }}
# Кэши, ориентированные на конкретную ОС, позволяют избежать ненужных ребилдов на разных платформах
key: ${{ runner.os }}-cache
restore-keys: |
cache-npm-
- uses: actions/cache@v4
with:
path: path/to/dependencies
#key: cache-${{ hashFiles('**/lockfiles') }}
#key: ${{ runner.os }}-cache
# Недолговечные кэши для разового использования
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
cache-npm-
Также можно разделять кэши между заданиями, централизуя создание кэша для экономии времени, и обеспечивать сохранение кэшей даже при неудачной сборке используя условие always()
.
# Централизованное использование кэша
- id: cache-primes-save
uses: actions/cache/save@v4 # Сохранение кэша
with:
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- uses: actions/cache/restore@v4 # Восстановление кэша
with:
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
# Сохранение кэша после сбоя сборки
- uses: actions/cache@v4
with:
path: path/to/dependencies
key: cache-${{ hashFiles('**/lockfiles') }}
if: always()
Примеры кэширования менеджера пакетов GitHub Actions
Я собрал несколько примеров кэширования для различных менеджеров пакетов: npm
, pip
, Maven
и NuGet
. Следующая конфигурация позволит избежать повторной загрузки зависимостей при каждом запуске рабочего процесса. Например, при использовании npm
мы не кэшируем node_modules
, чтобы избежать проблем с разными версиями Node.
Вместо этого мы динамически кэшируем сам npm
. Кэш pip
должен быть разным в зависимости от ОС, и то же самое делается для Maven
и NuGet
для их путей к репозиториям и файлам блокировки.
# Кэширование зависимостей npm
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
# Кэширование зависимостей pip
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
# Кэширование зависимостей Maven
- uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
# Кэширование зависимостей NuGet
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: ${{ runner.os }}-nuget-
Заключение
Кэширование в GitHub Actions подразумевает оптимизацию рабочего процесса непрерывной интеграции за счёт отказа от дублирования задач, например, повторной загрузки зависимостей. Тщательный выбор ключей кэша на основе метаданных, операционной системы или файла блокировки, поиск близких совпадений с ключами восстановления и уменьшение их количества значительно сократит время сборки. Храните отдельно кэши для разных операционных систем и используйте транзитные кэши для разовой сборки.