Короткий ответ
Разумный пайплайн: установка зависимостей (с кэшем) → линтинг/типизация и unit-тесты параллельно → сборка Docker-образа с кэшированием слоёв → сканирование образа на уязвимости → публикация в registry; кэширование экономит минуты на каждом запуске.
Как это работает подробнее
CI-системы кэшируют директории между запусками по ключу (хеш lock-файла); для Docker используют registry cache или BuildKit cache mount, чтобы не пересобирать неизменившиеся слои на «холодном» раннере.
Пример кода
config.yaml
jobs:
test:
steps:
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ hashFiles('requirements.txt') }}
- run: pip install -r requirements.txt
- run: pytest
build:
needs: test
steps:
- uses: docker/build-push-action@v5
with:
cache-from: type=registry,ref=myrepo/app:cache
cache-to: type=registry,ref=myrepo/app:cache,mode=maxЧто использовать на практике
- Рекомендация. линтинг и тесты не зависят друг от друга и могут идти параллельно, сокращая общее время; сборку образа логично запускать после прохождения тестов, но можно параллелить со сканированием, если образ собирается долго.
Подводные камни
- Риск. кэшировать зависимости по статичному ключу без учёта изменения lock-файла — риск устаревшего кэша; делать все стадии строго последовательными без необходимости, раздувая время пайплайна.