Cache и artifacts в GitLab CI: как передать результат сборки следующему job
Задача build успешно создала архив, а test сообщает, что файла нет. На своей машине разработчик запускал команды по очереди в одном каталоге, поэтому всё работало. В CI следующая job получает отдельное рабочее окружение. Общий commit ещё не означает общий диск и сохранение файлов после предыдущей задачи.
Нужно явно описать, какой результат build публикует и кто его получает. Для этого в GitLab есть artifacts. Cache решает соседнюю задачу: позволяет повторно использовать скачанные зависимости и другие восстанавливаемые данные. Если перепутать эти механизмы, успешность тестов начнёт зависеть от того, на какой Runner они попали и сохранился ли там кэш.
Передадим маленький результат, который можно проверить
Создайте пустой тестовый репозиторий с таким .gitlab-ci.yml. Обе задачи используют Python, но работают в разных контейнерах. Первая действительно вычисляет контрольную сумму файла и публикует пару файлов; вторая заново считает сумму после получения артефактов.
stages: [build, test]
build:
stage: build
image: python:3.12-alpine
script:
- mkdir -p dist
- python -c 'from pathlib import Path; Path("dist/message.txt").write_text("release=42\n", encoding="utf-8", newline="\n")'
- python -c 'import hashlib; from pathlib import Path; p=Path("dist/message.txt"); Path("dist/sha256.txt").write_text(hashlib.sha256(p.read_bytes()).hexdigest(), encoding="ascii")'
artifacts:
paths:
- dist/
expire_in: 1 day
verify:
stage: test
image: python:3.12-alpine
needs:
- job: build
artifacts: true
script:
- python -c 'import hashlib; from pathlib import Path; actual=hashlib.sha256(Path("dist/message.txt").read_bytes()).hexdigest(); expected=Path("dist/sha256.txt").read_text(encoding="ascii"); assert actual == expected; print(actual)'
В логе build должны появиться загрузка dist как artifact и успешное завершение. В verify — скачивание результата build, затем вычисленная шестнадцатеричная сумма. Если убрать artifacts из build, исходный репозиторий не содержит dist, и verify завершится ошибкой чтения. Это полезная проверка маршрута передачи: тест использует файл, созданный предыдущей job, а не случайный остаток в рабочем каталоге.
Что именно задаёт needs
Связь needs указывает производителя результата и зависимость выполнения. При её использовании задача получает артефакты от перечисленных jobs, поэтому важно назвать именно build. Явное artifacts: true делает намерение понятным при чтении. Не добавляйте одновременно dependencies для настройки того же пути: выбрать один способ проще и для автора, и для диагностики.
Путь dist/ задаётся относительно каталога проекта. Файл, записанный вне этого дерева, не станет артефактом только потому, что команда завершилась успешно. Когда загрузчик пишет no matching files, проверьте рабочий каталог и фактический путь после сборки. Для этого в конце script временно выведите список файлов нужного каталога, затем сопоставьте его с artifacts.paths.
Срок хранения задаёт, как долго отложенная задача сможет получить результат. Один день подходит учебному примеру, но ручной релиз через неделю может лишиться файла. Для такого процесса выберите согласованный срок или публикуйте релизный объект в хранилище пакетов. Уточнения о скачивании и хранении есть в справке artifacts.
Где остаётся место для cache
Предположим, проект устанавливает Python-зависимости через pip. Кэшировать можно каталог скачиваний pip внутри проекта, например .cache/pip, задав PIP_CACHE_DIR. Ключ cache удобно привязать к lock-файлу зависимостей. Тогда повторный запуск с тем же набором пакетов может скачать меньше данных, но установка всё равно должна уметь пройти при пустом cache.
Артефакт же связывается с конкретной работой: проверяем именно то, что построил этот build. Кэш с широким ключом может пережить несколько pipelines и обновляться разными jobs. Даже если положить туда dist, получатель не приобретёт надёжной связи «этот файл произведён нужным commit». Поэтому обязательный вход теста передаём через artifacts, а ускорение загрузки зависимостей настраиваем отдельно.
При неожиданном промахе кэша проверьте ключ, пути, политику pull/push и доступное исполнителям cache-хранилище. Разные Runner без общего хранилища могут видеть разные наборы данных. Это влияет на скорость, но не должно менять результат сборки. Подробнее варианты размещения описаны в настройке cache.
В рабочем проекте замените message.txt настоящим архивом, бинарным файлом или собранным сайтом, сохранив явную связь производителя и потребителя. Проверка суммы здесь подтверждает целостность передачи; тесты содержимого остаются отдельной задачей. Так исчезновение кэша замедлит запуск, а потеря обязательного артефакта даст конкретную ошибку до релиза.
Ещё по теме
- GitLab CI: job завис в pending — как проверить Runner и теги
- GitLab CI: отменяем устаревшие сборки и сохраняем нужный деплой
Продолжить изучение
Хотите собрать проверяемый путь от коммита до релиза? Jobs, runners, артефакты и деплой — темы программы «GitLab CI/CD: автоматизация сборки и деплоя».
Продолжить на практике
- GitLab CI/CD: автоматизация сборки и деплоя ↗
От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.
