03 · Платформа: DevOps, k8s, сеть, хранилище3.2 · CI с Jenkins3.2.3средний

Пайплайн качества: lint, test, build, push

Зачем это нужно

Зелёный Jenkins — не самоцель. Цель — гарантировать, что каждый артефакт в registry прошёл согласованный набор проверок. Для ML-сервиса недостаточно «pytest прошёл»: нужны проверки контракта API, размера образа, smoke-тест predict и воспроизводимости зависимостей.

Этот урок собирает типовой quality pipeline, который вы повторите в практикуме модуля 3.2 и будете расширять до Helm и Argo CD.

Основные идеи

Lint — дешёвая первая линия. Статический анализ ловит опечатки, неиспользуемый код, нарушение стиля до запуска тестов. Для Python: ruff, flake8, mypy (по зрелости проекта). Stage должен быть быстрым (< 1 мин).

Test — поведение системы. Unit-тесты функций препроцессинга; интеграционные — API с TestClient FastAPI; для модели — фиксированный набор входов и ожидаемых форматов выхода (не обязательно точное совпадение float, но shape и dtype). Храните маленькие fixture-файлы в tests/fixtures/, не полный датасет.

Build — воспроизводимый образ. docker build с --pull периодически обновляет базовый образ (patch security). Тегируйте однозначно:

environment { IMAGE = "registry.example.com/ml/scorer" TAG = "${env.GIT_COMMIT.take(7)}-${env.BUILD_NUMBER}" }

Не перезаписывайте тег latest без контроля — в prod деплоят immutable tags.

Push — только после успеха. Registry login через credentials; push в stage после test и build:

stage('Push') { steps { withCredentials([usernamePassword( credentialsId: 'registry-creds', usernameVariable: 'REG_USER', passwordVariable: 'REG_PASS' )]) { sh ''' echo "$REG_PASS" | docker login registry.example.com -u "$REG_USER" --password-stdin docker push ${IMAGE}:${TAG} ''' } } }

Parallel stages. Независимые проверки (lint + unit tests) можно запускать параллельно — короче feedback.

Artifacts и отчёты. JUnit XML из pytest публикуют через junit 'reports/*.xml' — Jenkins показывает тренд тестов. Coverage — опционально, но полезно для кода inference (не для notebook DS).

Smoke после build. Лёгкий контейнерный тест: docker run --rm image curl localhost/health — ловит «образ собрался, но приложение не стартует».

Как это выглядит на практике

Полный Jenkinsfile для сервиса scoring:

Stage Команда Gate
Lint ruff check . fail → stop
Test pytest -q --junitxml=reports/junit.xml fail → stop
Build docker build -t $IMAGE:$TAG . fail → stop
Smoke run container + HTTP GET /health fail → stop
Push docker push $IMAGE:$TAG только main

В PR собирают и тестируют, push — только при merge в main (блок when { branch 'main' }).

Артефакт для следующих модулей: образ scorer:abc1234-57 в registry. Helm chart (3.4) будет ссылаться на этот тег через values.yaml. Jenkins не обязан делать kubectl apply — часто достаточно push + обновление values в Git для Argo CD.

Практикум модуля: добейтесь зелёного Jenkinsfile с минимум lint → test → build → push.

Что сделать после занятия

  • Добавьте в свой репозиторий stage Lint и stage Test с JUnit-отчётом.

  • Настройте push образа только для ветки main.

  • Напишите smoke-тест: контейнер поднимается и /health возвращает 200.

Официальные материалы