# 🚀 Документация CI/CD Pipeline NOCR ## 📋 Обзор Проект NOCR использует современную многопайплайновую CI/CD систему на базе Drone CI, работающую на Kubernetes. Этот документ описывает 5 специализированных пайплайнов и способы их использования. --- ## 🎯 Архитектура пайплайнов ### Пайплайн 1: **Feature Validation (Валидация функциональных веток)** **Триггер:** Push в ветки `feature/*`, `fix/*` или `issues/*` **Назначение:** Быстрая обратная связь для разработчиков **Длительность:** ~3-5 минут **Что делает:** - Клонирует репозиторий с субмодулями - Восстанавливает все NuGet-пакеты (общий кэш) - Собирает все 4 сервиса в Debug-режиме - Запускает unit и integration тесты с Testcontainers **Пример рабочего процесса:** ```bash git checkout -b feature/add-new-filter # Внесите изменения... git add . git commit -m "Add new filter functionality" git push origin feature/add-new-filter ``` Drone автоматически запустит тесты. Проверьте результаты перед созданием PR. --- ### Пайплайн 2: **Main Validation (Валидация основной ветки)** **Триггер:** Push в ветку `main` **Назначение:** Валидация основной ветки после мерджа **Длительность:** ~3-5 минут **Что делает:** - То же, что и Feature Validation - Гарантирует, что ветка main всегда в рабочем состоянии **Пример рабочего процесса:** ```bash # После мерджа PR в main # Пайплайн запускается автоматически ``` --- ### Пайплайн 3: **Contracts-Only Publish (Публикация только контрактов)** **Триггер:** Тег с сообщением коммита, содержащим `contracts_only:` **Назначение:** Быстрая публикация NuGet-пакетов контрактов без сборки Docker-образов **Длительность:** ~2 минуты **Что делает:** - Упаковывает контракты указанного сервиса в NuGet-пакеты - Публикует во внутреннем NuGet-фиде - Пропускает сборку Docker-образов **Пример рабочего процесса:** ```bash # Обновите контракты telegram-listener cd telegram-listener # Внесите изменения в Async.Api.Contracts... git add . git commit -m "contracts_only:telegram_listener - Add MessageEdited event" git push origin main # Создайте тег git tag v1.2.4-contracts git push origin v1.2.4-contracts ``` **Поддерживаемые маркеры:** - `contracts_only:telegram_listener` - `contracts_only:text_matcher` - `contracts_only:users` --- ### Пайплайн 4: **Full Release (Полный релиз)** **Триггер:** Тег на main БЕЗ `contracts_only` или `deploy_only` в сообщении коммита **Назначение:** Полный цикл релиза **Длительность:** ~8-10 минут **Что делает:** 1. **Этап 1:** Публикация всех контрактов в NuGet (параллельно) 2. **Этап 2:** Сборка всех Docker-образов с Kaniko (3 параллельных потока) 3. **Этап 3:** Деплой в Kubernetes (только для тегов, начинающихся с `v`) **Пример рабочего процесса:** ```bash # Готовы к релизу git tag v1.3.0 git push origin v1.3.0 # Drone выполнит: # 1. Публикацию контрактов # 2. Сборку образов (с тегами v1.3.0, commit SHA, и latest) # 3. Деплой в k8s (если тег начинается с 'v') ``` **Создаваемые теги образов:** - `hub.musk.fun/k8s/nocr/telegram_listener:v1.3.0` - `hub.musk.fun/k8s/nocr/telegram_listener:abc1234` (commit SHA) - `hub.musk.fun/k8s/nocr/telegram_listener:latest` --- ### Пайплайн 5: **Deploy-Only (Только деплой)** **Триггер:** Тег с сообщением коммита, содержащим `deploy_only: ` **Назначение:** Быстрый деплой уже собранных образов **Длительность:** ~1 минута **Что делает:** - Пропускает сборку - Деплоит указанные образы в Kubernetes - Полезно для отката или продвижения существующих образов **ВАЖНО:** В сообщении коммита нужно указать версию образов для деплоя: **Пример рабочего процесса:** ```bash # Деплой существующих образов v1.2.9 git commit --allow-empty -m "deploy_only: v1.2.9" git tag deploy-v1.2.9 git push origin deploy-v1.2.9 # Откат на предыдущую версию v1.2.8 git commit --allow-empty -m "deploy_only: v1.2.8" git tag rollback-v1.2.8 git push origin rollback-v1.2.8 ``` **Формат commit message:** - `deploy_only: v1.2.9` - деплоит образы с тегом `v1.2.9` - Скрипт извлекает версию из сообщения и использует соответствующие образы - Образы должны существовать в registry (собраны ранее через full-release) --- ## 🛠️ Скрипты деплоя Все скрипты деплоя находятся в `_deploy/scripts/`: ### `deploy.sh` **Назначение:** Деплой сервисов в Kubernetes **Использование:** ```bash # Full release (использует TAG для образов) ./deploy.sh v1.3.0 abc1234 # Deploy only (переопределяет тег образа) ./deploy.sh deploy-v1.2.9 def5678 v1.2.9 ``` **Параметры:** 1. `tag` - Git тег (обязательный) 2. `commit-sha` - SHA коммита (опциональный) 3. `image-tag-override` - Переопределение тега образа (опциональный, для deploy_only) **Возможности:** - Обновляет deployment-манифесты новыми тегами образов - Применяет манифесты в кластер - Ожидает завершения rollout с таймаутом - Запускает проверки здоровья после деплоя - Показывает статус подов ### `rollback.sh` **Назначение:** Откат деплоев к предыдущей версии **Использование:** ```bash # Откат одного сервиса ./rollback.sh telegram-listener # Откат всех сервисов ./rollback.sh all ``` **Возможности:** - Показывает историю ревизий - Выполняет kubectl rollout undo - Ожидает завершения отката - Запускает проверки здоровья после отката ### `health-check.sh` **Назначение:** Проверка здоровья всех сервисов NOCR **Использование:** ```bash ./health-check.sh ``` **Проверяет:** - Статус подов (Running/Ready) - Health-эндпоинты (/health) - Последние события для упавших подов --- ## 📦 Оптимизации ### Общий NuGet-кэш Все пайплайны используют общий временный volume для NuGet-пакетов: - Первый `dotnet restore` скачивает пакеты - Последующие сборки переиспользуют кэшированные пакеты - **~60% быстрее**, чем индивидуальное восстановление для каждого сервиса ### Параллельное выполнение - Публикация контрактов: 3 сервиса параллельно - Сборка Docker: 3 параллельных потока - Независимые операции никогда не блокируют друг друга ### Кэширование Kaniko Все сборки Kaniko используют: - `--cache=true` - Включено кэширование слоев - `--cache-repo=hub.musk.fun/k8s/cache/*` - Общий репозиторий кэша - `--compressed-caching=true` - Быстрая передача кэша --- ## 🧪 Поддержка Testcontainers Пайплайны валидации Feature и Main включают Docker-in-Docker сервис для Testcontainers: ```yaml services: - name: docker image: docker:27-dind privileged: true ``` Тесты могут использовать Testcontainers для запуска реальных баз данных, очередей сообщений и т.д. --- ## 🔒 Необходимые секреты Настройте эти секреты в Drone: - `hub_username` - Имя пользователя Docker registry - `hub_password` - Пароль Docker registry - `nuget_musk_api_key` - API-ключ NuGet-фида --- ## 📊 Дерево решений пайплайна ``` Push в feature/* → Feature Validation (сборка + тесты) Push в main → Main Validation (сборка + тесты) Тег + "contracts_only:" → Contracts Publish Тег + "deploy_only:" → Deploy Only Тег (без маркеров) → Full Release (контракты → образы → деплой) ``` --- ## 🎓 Лучшие практики 1. **Функциональные ветки** - Всегда создавайте функциональные ветки для новой работы - Дайте CI валидировать перед мерджем в main 2. **Изменения контрактов** - Используйте `contracts_only:` для быстрого обновления контрактов - Другие сервисы могут сразу обновить ссылки 3. **Процесс релиза** - Создавайте теги только из ветки main - Используйте семантическое версионирование (v1.2.3) - Теги, начинающиеся с `v`, автоматически деплоятся в k8s 4. **Экстренный откат** ```bash # Быстрый откат через deploy-only git commit --allow-empty -m "deploy_only: v1.2.8" git tag rollback-v1.2.8 git push origin rollback-v1.2.8 # Или используйте скрипт отката напрямую в кластере kubectl exec -it deploy-pod -- bash cd /flea/_deploy/scripts ./rollback.sh all ``` 5. **Мониторинг деплоев** - Следите за UI Drone для прогресса пайплайна - Проверяйте логи подов: `kubectl logs -f deployment/telegram-listener -n nocr` - Запускайте проверки здоровья: `./_deploy/scripts/health-check.sh` --- ## 🐛 Устранение неполадок ### Пайплайн завис на "Waiting for contracts" **Причина:** Публикация контракта упала **Решение:** Проверьте NuGet-фид, проверьте API-ключ ### Сборка Docker падает с ошибкой "unauthorized" **Причина:** Неверные учетные данные registry **Решение:** Обновите секреты `hub_username` и `hub_password` ### Тесты падают с ошибкой "Cannot connect to Docker daemon" **Причина:** Testcontainers не может достичь Docker-in-Docker сервиса **Решение:** Проверьте, что переменная окружения `DOCKER_HOST` установлена правильно ### Деплой падает с ошибкой "ImagePullBackOff" **Причина:** Образ не найден в registry **Решение:** Проверьте, что образ был собран и запушен успешно на предыдущем этапе ### YAML-ошибки в .drone.yml **Причина:** Неправильное форматирование многострочных команд или двоеточие в переменных **Решение:** - Используйте блоки `|` для многострочных команд - Экранируйте переменные с двоеточиями (например, `"${VAR:0:7}"`) - Проверьте YAML: `python3 -c "import yaml; list(yaml.safe_load_all(open('.drone.yml')))"` --- ## 📚 Дополнительные ресурсы - [Документация Drone CI](https://docs.drone.io/) - [Документация Kaniko](https://github.com/GoogleContainerTools/kaniko) - [Testcontainers для .NET](https://dotnet.testcontainers.org/) - [Kubernetes Deployments](https://kubernetes.io/ru/docs/concepts/workloads/controllers/deployment/) --- ## 🔄 История изменений (15-16 октября 2025) ### Исправлена критическая проблема с YAML **Проблема:** - Ошибка `yaml: line 126: mapping values are not allowed in this context` - Многострочные команды `/kaniko/executor` содержали переменные с двоеточием (`${DRONE_COMMIT_SHA:0:7}`) - YAML парсер интерпретировал двоеточие как разделитель ключ:значение **Решение:** 1. Обернули все команды `/kaniko/executor` в многострочные блоки с `|` 2. Добавили обратные слэши `\` для продолжения команды 3. Экранировали аргументы с двоеточиями в кавычках **Пример:** ```yaml # До (неправильно): commands: - /kaniko/executor --destination=hub.musk.fun/image:${DRONE_COMMIT_SHA:0:7} # После (правильно): commands: - | /kaniko/executor \ --destination=hub.musk.fun/image:${DRONE_COMMIT_SHA:0:7} ``` ### Добавлены новые функции - ✨ Контракты-только пайплайн для быстрой итерации - 🚀 Деплой-только пайплайн для откатов - 🔄 Обработка MessageEdited событий - 📝 Скрипт автокоммита субмодулей - ⚡ Оптимизированный общий NuGet-кэш - 🔧 Параллельная сборка и деплой --- ## 📞 Поддержка Если у вас возникли проблемы с CI/CD: 1. Проверьте логи в Drone UI: https://drone.musk.fun/nocr/flea 2. Проверьте статус подов: `kubectl get pods -n nocr` 3. Запустите health-check: `./health-check.sh` 4. Проверьте логи контейнеров: `kubectl logs -f -n nocr` Для вопросов по инфраструктуре обращайтесь к DevOps-команде.