Параллельные jobs перезаписывают cache: выделяем одного писателя
Десять тестовых jobs используют один cache зависимостей. Каждая скачивает его, запускает тесты и в конце загружает архив с тем же ключом. Время на упаковку повторяется десять раз, а содержимое последнего архива зависит от порядка завершения. Особенно неприятно, когда одна job установила дополнительный пакет и оставила другой набор файлов.
Cache хорошо работает как ускоритель, когда задания могут восстановить зависимости и без него. Его ключ не должен изображать канал передачи точного результата между jobs. Если несколько потребителей используют одинаковую подготовку, разумно отделить обновление cache от чтения. Тогда назначенный writer наполняет общий кэш, а параллельные тесты не пытаются публиковать свои версии.
Разделить права чтения и записи
Для npm можно сохранять каталог загрузок, а не node_modules. Установка через npm ci продолжает опираться на lockfile, а cache уменьшает повторное скачивание пакетов. Фрагмент настройки для потребителя выглядит так:
test:
image: node:22-alpine
cache:
key:
files:
- package-lock.json
paths:
- .npm/
policy: pull
script:
- npm ci --cache .npm --prefer-offline
- npm test
Отдельная подготовительная job с тем же ключом может использовать pull-push и запускать npm ci для наполнения .npm. Её нужно поставить раньше тестов, если нужен прогретый cache в том же pipeline. Но отсутствие cache не должно ломать тест: чистый runner должен скачать пакеты из настроенного registry и продолжить работу.
Ключ по lockfile отделяет несовместимые наборы зависимостей лучше, чем вечный default. Если внутри сохраняются платформенно зависимые данные, добавьте различие архитектуры или среды. Не стоит складывать в один ключ всё, что случайно лежит в рабочем каталоге. Размер архива и время его обработки могут превысить выигрыш от скачивания.
Посмотреть на журнал загрузок
После изменения проверьте, что тестовые jobs действительно только восстанавливают cache и не загружают его в конце. Затем сравните время полного pipeline, а не единственной команды установки. Выигрыш может появиться в исчезнувшей упаковке, даже если npm ci почти не ускорился. Если cache распределён между runner не так, как предполагалось, журнал покажет промахи и место восстановления.
Проведите запуск с новым ключом. Он проверит холодный путь: потребитель не должен зависеть от существования вчерашнего архива. Затем повторите pipeline с тем же lockfile и посмотрите тёплый путь. Два наблюдения дают понятный контракт, а не оценку по случайно удачному запуску.
Релизные файлы, собранный бинарник и отчёт тестов передавайте через artifacts с явной связью jobs. Cache остаётся заменяемым ускорителем. Такое разделение упрощает диагностику: исчезновение cache ухудшает скорость, а обязательный вход задания по-прежнему определяется текущим pipeline.
Продолжить практику
Исправление одной job полезно закрепить в полном процессе выпуска. В программе курса «GitLab CI/CD: автоматизация сборки и деплоя» — pipeline учебного приложения с проверками, тестами, сборкой Docker-образа, registry и staging. Отдельно разбираются runners, секреты, нестабильные запуски и возврат к предыдущему образу. Такой проект помогает увидеть, как решение внутри одной job влияет на выпуск версии и дальнейший откат.
Источник: официальная документация.
Другие задачи по теме: Окружение задания и повторяемый pipeline.
Продолжить на практике
- GitLab CI/CD: автоматизация сборки и деплоя ↗
От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.
