Кэширование зависимостей

Перестаём качать одни и те же зависимости каждый прогон.

Кэш сохраняет каталоги между запусками, чтобы не скачивать и не собирать заново то, что не менялось.

Проблема

Установка зависимостей — часто самый долгий шаг CI. Если package-lock.json не менялся, скачивать пакеты заново бессмысленно. Кэш решает это: первый прогон наполняет его, последующие — берут готовое.

actions/cache

Универсальный экшен. Ключевая идея — ключ кэша строится по хешу lock-файла: изменился lock — изменился ключ — кэш пересоберётся.

- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      npm-${{ runner.os }}-

Разбор:

  • path — что кэшировать (каталог менеджера пакетов).
  • key — точный ключ; hashFiles(...) даёт хеш по содержимому lock-файла.
  • restore-keys — запасные префиксы: если точного ключа нет, возьмётся ближайший подходящий частичный кэш.

Hit и miss

Если ключ совпал — это cache hit, каталог восстанавливается, шаг установки отрабатывает мгновенно. Если нет — cache miss, зависимости ставятся обычным путём, а в конце job кэш сохраняется под новым ключом для будущих прогонов.

Кэш «из коробки» в setup-экшенах

Часто отдельный actions/cache не нужен — setup-экшены умеют кэшировать сами:

- uses: actions/setup-node@v4
  with:
    node-version: "20"
    cache: "npm"          # включает кэш npm автоматически

Для Python аналогично cache: "pip" в setup-python. Начинайте с этого — проще и достаточно в большинстве случаев.

Важная оговорка

Кэш — это оптимизация, а не источник истины. Он может «протухнуть» или быть очищен (есть лимит размера и срок жизни). Пайплайн обязан корректно работать и при пустом кэше — никогда не полагайтесь на наличие кэша как на обязательное условие.

Итог

  • Кэш экономит время на повторной установке зависимостей.
  • Ключ строят по хешу lock-файла (hashFiles); restore-keys дают частичное попадание.
  • Чаще всего хватает встроенного cache: в setup-экшенах; кэш не должен быть обязательным условием работы.
Проверьте себя
1. На чём обычно строят ключ кэша зависимостей?
AНа номере прогона
BНа хеше lock-файла через hashFiles(), чтобы при изменении зависимостей кэш пересобирался
CНа имени ветки
DНа дате запуска
2. Что произойдёт при cache miss (ключ не найден)?
AJob упадёт с ошибкой
BЗависимости установятся обычным путём, а в конце job кэш сохранится под новым ключом
CWorkflow остановится навсегда
DКэш других репозиториев будет удалён
3. Какой самый простой способ включить кэш npm?
AНаписать свой bash-скрипт архивации
BУказать cache: "npm" в actions/setup-node
CЗакоммитить node_modules в репозиторий
DОтключить установку зависимостей
Поддержать проект