/
alexefan136
/
flowstack
Обзор
Документация
Войти
/
alexefan136
/
flowstack
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
Makefile
509 строк
25 KB
Alexander Efanov
Обновление репозитория
15 июл 2026, 12:19
15 июл 2026, 12:19
76704c6
Код
Авторство
О чём код?
# ============================================================================ # FlowStack — Makefile для управления разработкой и деплоем # ============================================================================ # Использование: # make help — показать все команды # make dev — запустить весь стек (engine + gateway + rag + ui) # make dev-minimal — запустить минимальный стек (engine + gateway + ui) # make dev-rag — запустить только RAG + Qdrant # make build — собрать образы # make logs — показать логи # make down — остановить все сервисы # make env-setup — настроить .env файлы # make test-llm — протестировать LLM интеграцию # make test-rag — протестировать RAG сервис # ============================================================================ .PHONY: help dev dev-backend dev-ui dev-minimal dev-rag build build-no-cache build-rag \ up down stop restart ps \ logs logs-follow logs-engine logs-gateway logs-ui logs-rag logs-qdrant logs-postgres logs-redis \ test test-engine test-gateway test-ui test-rag test-rag-integration \ lint lint-engine lint-gateway lint-ui lint-rag \ clean clean-all clean-cache clean-rag \ shell-engine shell-gateway shell-ui shell-rag shell-qdrant \ health health-engine health-gateway health-ui health-rag health-qdrant health-postgres health-redis \ inspect-engine inspect-rag \ env-setup env-check env-edit env-rag-setup \ test-llm test-llm-stream test-llm-config \ rag-ingest rag-search rag-stats rag-browse \ qdrant-dashboard # Цвета для вывода GREEN := \033[0;32m YELLOW := \033[0;33m CYAN := \033[0;36m RED := \033[0;31m BLUE := \033[0;34m MAGENTA:= \033[0;35m NC := \033[0m # Дефолтная цель .DEFAULT_GOAL := help # ============================================================================ # HELP # ============================================================================ help: ## 📖 Показать это сообщение @echo "" @echo "$(CYAN)╔══════════════════════════════════════════════════════════════╗$(NC)" @echo "$(CYAN)║ FlowStack — Доступные команды ║$(NC)" @echo "$(CYAN)╚══════════════════════════════════════════════════════════════╝$(NC)" @echo "" @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " $(CYAN)%-25s$(NC) %s\n", $$1, $$2}' @echo "" # ============================================================================ # DOCKER COMPOSE — Основные команды # ============================================================================ dev: env-check ## 🚀 Запустить весь стек (engine + gateway + rag + ui) @echo "$(GREEN)🚀 Запуск FlowStack (все сервисы)...$(NC)" @docker compose up --build -d @echo "" @echo "$(CYAN)╔══════════════════════════════════════════════════════════════╗$(NC)" @echo "$(CYAN)║ FlowStack запущен! ║$(NC)" @echo "$(CYAN)╚══════════════════════════════════════════════════════════════╝$(NC)" @echo "" @echo "$(GREEN)🌐 UI: $(CYAN)http://localhost:3000$(NC)" @echo "$(GREEN)🦀 Gateway: $(CYAN)http://localhost:8080$(NC)" @echo "$(GREEN)🐍 Engine: $(CYAN)http://localhost:8000$(NC)" @echo "$(GREEN)📚 RAG: $(CYAN)http://localhost:8002$(NC)" @echo "$(GREEN)🔍 Qdrant: $(CYAN)http://localhost:6333/dashboard$(NC)" @echo "" @echo "$(YELLOW)Команды:$(NC)" @echo " $(CYAN)make logs$(NC) — смотреть логи всех сервисов" @echo " $(CYAN)make ps$(NC) — статус контейнеров" @echo " $(CYAN)make health$(NC) — проверить здоровье сервисов" @echo " $(CYAN)make test-llm$(NC) — протестировать LLM" @echo " $(CYAN)make test-rag$(NC) — протестировать RAG API" @echo " $(CYAN)make down$(NC) — остановить всё" dev-backend: env-check ## 🚀 Запустить только backend (engine + gateway + rag) @echo "$(GREEN)🚀 Запуск backend...$(NC)" @docker compose up --build -d engine gateway rag qdrant dev-minimal: env-check ## 🚀 Запустить минимальный стек (engine + gateway + ui) @echo "$(GREEN)🚀 Запуск минимального стека...$(NC)" @docker compose up --build -d engine gateway ui dev-rag: env-check ## 🚀 Запустить только RAG + Qdrant @echo "$(GREEN)🚀 Запуск RAG + Qdrant...$(NC)" @docker compose up --build -d rag qdrant @echo "" @echo "$(GREEN)📚 RAG: $(CYAN)http://localhost:8002$(NC)" @echo "$(GREEN)🔍 Qdrant: $(CYAN)http://localhost:6333/dashboard$(NC)" dev-infra: ## 🏗️ Запустить только инфраструктуру (postgres + redis + qdrant) @echo "$(GREEN)🏗️ Запуск инфраструктуры...$(NC)" @docker compose up --build -d postgres redis qdrant build: ## 🔨 Собрать все образы @echo "$(CYAN)🔨 Сборка образов...$(NC)" @docker compose build build-rag: ## 🔨 Собрать только RAG образ @echo "$(CYAN)🔨 Сборка RAG образа...$(NC)" @docker compose build rag build-no-cache: ## 🔨 Собрать образы без кэша (полная пересборка) @echo "$(YELLOW)🔨 Полная пересборка без кэша...$(NC)" @docker compose build --no-cache up: ## 🚀 Запустить все сервисы в фоне @echo "$(GREEN)🚀 Запуск сервисов...$(NC)" @docker compose up -d down: ## 🛑 Остановить и удалить все контейнеры @echo "$(YELLOW)🛑 Остановка сервисов...$(NC)" @docker compose down stop: ## ⏸️ Остановить все сервисы (без удаления) @echo "$(YELLOW)⏸️ Остановка сервисов...$(NC)" @docker compose stop restart: ## 🔄 Перезапустить все сервисы @echo "$(CYAN)🔄 Перезапуск сервисов...$(NC)" @docker compose restart ps: ## 📋 Показать статус всех контейнеров @docker compose ps # ============================================================================ # LOGS — Просмотр логов # ============================================================================ logs: ## 📜 Показать последние логи всех сервисов @docker compose logs --tail=100 logs-follow: ## 📜 Следить за логами в реальном времени @docker compose logs -f logs-engine: ## 📜 Логи только Engine @docker compose logs -f engine logs-gateway: ## 📜 Логи только Gateway @docker compose logs -f gateway logs-ui: ## 📜 Логи только UI @docker compose logs -f ui logs-rag: ## 📜 Логи только RAG @docker compose logs -f rag logs-qdrant: ## 📜 Логи только Qdrant @docker compose logs -f qdrant logs-postgres: ## 📜 Логи только PostgreSQL @docker compose logs -f postgres logs-redis: ## 📜 Логи только Redis @docker compose logs -f redis # ============================================================================ # ENVIRONMENT — Управление конфигурацией # ============================================================================ env-setup: env-rag-setup ## 🔧 Создать все .env файлы из примеров @echo "$(CYAN)🔧 Настройка окружения...$(NC)" @if [ ! -f core/engine/.env ]; then \ if [ -f core/engine/.env.example ]; then \ cp core/engine/.env.example core/engine/.env; \ echo "$(GREEN)✅ Создан core/engine/.env из .env.example$(NC)"; \ else \ echo "$(YELLOW)⚠️ Файл core/engine/.env.example не найден$(NC)"; \ fi; \ else \ echo "$(GREEN)✅ core/engine/.env уже существует$(NC)"; \ fi @echo "" @echo "$(YELLOW)⚠️ Отредактируйте .env файлы и добавьте API ключи$(NC)" env-rag-setup: ## 🔧 Создать .env для RAG сервиса @echo "$(CYAN)🔧 Настройка RAG окружения...$(NC)" @if [ ! -f core/rag/.env ]; then \ if [ -f core/rag/.env.example ]; then \ cp core/rag/.env.example core/rag/.env; \ echo "$(GREEN)✅ Создан core/rag/.env из .env.example$(NC)"; \ else \ echo "$(YELLOW)⚠️ Создаю пустой core/rag/.env (используются переменные из docker-compose)$(NC)"; \ touch core/rag/.env; \ fi; \ else \ echo "$(GREEN)✅ core/rag/.env уже существует$(NC)"; \ fi env-check: ## ✅ Проверить наличие .env файлов @echo "$(CYAN)✅ Проверка конфигурации...$(NC)" @echo "" @echo "$(BLUE)[Engine]$(NC)" @if [ ! -f core/engine/.env ]; then \ echo "$(YELLOW) ⚠️ Файл core/engine/.env не найден$(NC)"; \ echo "$(YELLOW) Запустите 'make env-setup' для создания$(NC)"; \ else \ echo "$(GREEN) ✅ core/engine/.env найден$(NC)"; \ if grep -q '^LLM_API_KEY=$$' core/engine/.env 2>/dev/null; then \ echo "$(YELLOW) ⚠️ LLM_API_KEY не установлен в engine .env$(NC)"; \ elif grep -q '^LLM_API_KEY=your-api-key-here$$' core/engine/.env 2>/dev/null; then \ echo "$(YELLOW) ⚠️ LLM_API_KEY содержит placeholder$(NC)"; \ else \ echo "$(GREEN) ✅ LLM_API_KEY установлен$(NC)"; \ fi; \ fi @echo "" @echo "$(BLUE)[RAG]$(NC)" @if [ ! -f core/rag/.env ]; then \ echo "$(YELLOW) ⚠️ core/rag/.env не найден (будет создан автоматически)$(NC)"; \ else \ echo "$(GREEN) ✅ core/rag/.env найден$(NC)"; \ fi @echo "" @if [ -f .env ]; then \ echo "$(GREEN)✅ Глобальный .env найден в корне проекта$(NC)"; \ else \ echo "$(YELLOW)⚠️ Глобальный .env не найден — будет использоваться core/engine/.env$(NC)"; \ fi env-edit: ## ✏️ Открыть engine .env в редакторе @echo "$(CYAN)✏️ Открытие .env...$(NC)" @$${EDITOR:-nano} core/engine/.env env-edit-rag: ## ✏️ Открыть RAG .env в редакторе @echo "$(CYAN)✏️ Открытие RAG .env...$(NC)" @$${EDITOR:-nano} core/rag/.env env-edit-global: ## ✏️ Открыть глобальный .env в редакторе @echo "$(CYAN)✏️ Открытие глобального .env...$(NC)" @$${EDITOR:-nano} .env # ============================================================================ # UI — Управление фронтендом # ============================================================================ ui-build: ## 🔨 Собрать UI образ @echo "$(CYAN)🔨 Пересборка UI...$(NC)" @docker compose build ui ui-logs: ## 📜 Логи UI контейнера @docker compose logs -f ui ui-shell: ## 🐚 Открыть shell в UI контейнере @docker compose exec ui sh ui-local: ## 🎨 Установить зависимости UI (локально) @echo "$(CYAN)📦 Установка зависимостей UI...$(NC)" @cd ui && npm install # ============================================================================ # LLM — Тестирование LLM интеграции # ============================================================================ test-llm: ## 🤖 Протестировать LLM (обычный запрос) @echo "$(CYAN)🤖 Тестирование LLM (обычный запрос)...$(NC)" @curl -s -X POST http://localhost:8000/api/v1/llm/chat \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"Привет! Скажи одно слово."}],"stream":false}' \ | python3 -m json.tool || echo "$(RED)❌ LLM недоступен$(NC)" test-llm-stream: ## 🤖 Протестировать LLM (стриминг) @echo "$(CYAN)🤖 Тестирование LLM (стриминг)...$(NC)" @curl -N -X POST http://localhost:8000/api/v1/llm/chat \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"Расскажи про Rust async"}],"stream":true}' test-llm-config: ## ⚙️ Показать текущую конфигурацию LLM @echo "$(CYAN)⚙️ Конфигурация LLM:$(NC)" @curl -s http://localhost:8000/api/v1/llm/models | python3 -m json.tool || echo "$(RED)❌ Engine недоступен$(NC)" # ============================================================================ # RAG — Тестирование RAG сервиса # ============================================================================ test-rag: rag-ingest rag-search ## 🧪 Полный тест RAG (ingest + search) @echo "" @echo "$(GREEN)✅ RAG тест пройден успешно!$(NC)" rag-ingest: ## 📥 Ingest тестового документа в RAG @echo "$(CYAN)📥 Ingest тестового документа...$(NC)" @curl -s -X POST http://localhost:8002/ingest \ -H "Content-Type: application/json" \ -d '{ \ "content": "Rust is a systems programming language focused on safety, speed, and concurrency. It guarantees memory safety without a garbage collector. Rust was originally designed by Graydon Hoare at Mozilla Research.", \ "source": "rust-intro.md", \ "doc_type": "markdown", \ "workspace_id": "engineering", \ "title": "Introduction to Rust" \ }' | python3 -m json.tool || echo "$(RED)❌ RAG недоступен$(NC)" rag-search: ## 🔍 Поиск в RAG @echo "$(CYAN)🔍 Поиск в RAG...$(NC)" @curl -s -X POST http://localhost:8002/search \ -H "Content-Type: application/json" \ -d '{ \ "query": "What is Rust?", \ "workspace_id": "engineering", \ "top_k": 5 \ }' | python3 -m json.tool || echo "$(RED)❌ RAG недоступен$(NC)" rag-stats: ## 📊 Статистика RAG сервиса @echo "$(CYAN)📊 Статистика RAG:$(NC)" @curl -s http://localhost:8002/stats | python3 -m json.tool || echo "$(RED)❌ RAG недоступен$(NC)" rag-browse: ## 📋 Список всех документов в RAG @echo "$(CYAN)📋 Список документов:$(NC)" @curl -s http://localhost:8002/documents | python3 -m json.tool || echo "$(RED)❌ RAG недоступен$(NC)" qdrant-dashboard: ## 🔍 Открыть Qdrant Dashboard в браузере @echo "$(CYAN)🔍 Открываю Qdrant Dashboard...$(NC)" @echo "$(GREEN)URL: $(CYAN)http://localhost:6333/dashboard$(NC)" @open http://localhost:6333/dashboard 2>/dev/null || xdg-open http://localhost:6333/dashboard 2>/dev/null || echo "$(YELLOW)Откройте URL вручную в браузере$(NC)" # ============================================================================ # ТЕСТЫ # ============================================================================ test: test-engine test-gateway test-rag-unit test-ui ## 🧪 Запустить все тесты test-engine: ## 🧪 Запустить тесты engine (pytest) @echo "$(CYAN)🧪 Запуск тестов engine...$(NC)" @cd core/engine && uv run pytest -v test-gateway: ## 🧪 Запустить тесты gateway (cargo test) @echo "$(CYAN)🧪 Запуск тестов gateway...$(NC)" @cd core/gateway && cargo test test-rag-unit: ## 🧪 Запустить unit-тесты RAG (локально, без Docker) @echo "$(CYAN)🧪 Запуск unit-тестов RAG...$(NC)" @cd core/rag && cargo test --lib test-rag-integration: ## 🧪 Запустить интеграционные тесты RAG (требует Qdrant) @echo "$(CYAN)🧪 Запуск интеграционных тестов RAG...$(NC)" @cd core/rag && cargo test --lib -- --ignored test-ui: ## 🧪 Запустить тесты UI (vitest) @echo "$(CYAN)🧪 Запуск тестов UI...$(NC)" @cd ui && npm run test --if-present || echo "$(YELLOW)⚠️ UI тесты не настроены$(NC)" # ============================================================================ # LINTING # ============================================================================ lint: lint-engine lint-gateway lint-rag lint-ui ## 🔍 Запустить все линтеры lint-engine: ## 🔍 Линтинг engine (ruff) @echo "$(CYAN)🔍 Линтинг engine...$(NC)" @cd core/engine && uv run ruff check src @cd core/engine && uv run ruff format --check src lint-gateway: ## 🔍 Линтинг gateway (clippy) @echo "$(CYAN)🔍 Линтинг gateway...$(NC)" @cd core/gateway && cargo clippy -- -D warnings lint-rag: ## 🔍 Линтинг RAG (clippy) @echo "$(CYAN)🔍 Линтинг RAG...$(NC)" @cd core/rag && cargo clippy -- -D warnings @cd core/rag && cargo fmt -- --check lint-rag-fix: ## 🔧 Автофикс проблем в RAG @echo "$(CYAN)🔧 Автофикс RAG...$(NC)" @cd core/rag && cargo clippy --fix --allow-dirty @cd core/rag && cargo fmt lint-ui: ## 🔍 Линтинг UI (eslint + tsc) @echo "$(CYAN)🔍 Линтинг UI...$(NC)" @cd ui && npm run lint --if-present || echo "$(YELLOW)⚠️ UI линтер не настроен$(NC)" # ============================================================================ # HEALTH CHECKS # ============================================================================ health: health-engine health-gateway health-ui health-rag health-qdrant health-postgres health-redis ## 🏥 Проверить здоровье всех сервисов health-engine: ## 🏥 Проверить здоровье engine @echo -n "$(CYAN)🏥 Engine (8000):$(NC) " @curl -s http://localhost:8000/health | python3 -m json.tool 2>/dev/null || echo "$(RED)❌ недоступен$(NC)" health-gateway: ## 🏥 Проверить здоровье gateway @echo -n "$(CYAN)🏥 Gateway (8080):$(NC) " @curl -s http://localhost:8080/ready | python3 -m json.tool 2>/dev/null || echo "$(RED)❌ недоступен$(NC)" health-ui: ## 🏥 Проверить здоровье UI @echo -n "$(CYAN)🏥 UI (3000):$(NC) " @curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/ | grep -q "200" && echo "$(GREEN)✅ доступен$(NC)" || echo "$(RED)❌ недоступен$(NC)" health-rag: ## 🏥 Проверить здоровье RAG @echo -n "$(CYAN)🏥 RAG (8002):$(NC) " @curl -s http://localhost:8002/health | python3 -m json.tool 2>/dev/null || echo "$(RED)❌ недоступен$(NC)" health-qdrant: ## 🏥 Проверить здоровье Qdrant @echo -n "$(CYAN)🏥 Qdrant (6333):$(NC) " @curl -s http://localhost:6333/healthz | python3 -m json.tool 2>/dev/null || echo "$(RED)❌ недоступен$(NC)" health-postgres: ## 🏥 Проверить здоровье PostgreSQL @echo -n "$(CYAN)🏥 Postgres(5432):$(NC) " @docker compose exec -T postgres pg_isready -U flowstack >/dev/null 2>&1 && echo "$(GREEN)✅ доступен$(NC)" || echo "$(RED)❌ недоступен$(NC)" health-redis: ## 🏥 Проверить здоровье Redis @echo -n "$(CYAN)🏥 Redis (6379):$(NC) " @docker compose exec -T redis redis-cli ping 2>/dev/null | grep -q "PONG" && echo "$(GREEN)✅ доступен$(NC)" || echo "$(RED)❌ недоступен$(NC)" health-short: ## 🏥 Краткая проверка здоровья всех сервисов @echo "" @echo "$(CYAN)=== Health Checks ===$(NC)" @echo -n "$(CYAN) Postgres :$(NC) "; curl -s -o /dev/null -w "%{http_code}" http://localhost:5432 2>/dev/null | grep -q "000" && (docker compose exec -T postgres pg_isready -U flowstack >/dev/null 2>&1 && echo "$(GREEN)✅$(NC)" || echo "$(RED)❌$(NC)") || echo "$(RED)❌$(NC)" @echo -n "$(CYAN) Redis :$(NC) "; docker compose exec -T redis redis-cli ping 2>/dev/null | grep -q "PONG" && echo "$(GREEN)✅$(NC)" || echo "$(RED)❌$(NC)" @echo -n "$(CYAN) Qdrant :$(NC) "; curl -s http://localhost:6333/healthz >/dev/null 2>&1 && echo "$(GREEN)✅$(NC)" || echo "$(RED)❌$(NC)" @echo -n "$(CYAN) RAG :$(NC) "; curl -s http://localhost:8002/health >/dev/null 2>&1 && echo "$(GREEN)✅$(NC)" || echo "$(RED)❌$(NC)" @echo -n "$(CYAN) Engine :$(NC) "; curl -s http://localhost:8000/health >/dev/null 2>&1 && echo "$(GREEN)✅$(NC)" || echo "$(RED)❌$(NC)" @echo -n "$(CYAN) Gateway :$(NC) "; curl -s http://localhost:8080/ready >/dev/null 2>&1 && echo "$(GREEN)✅$(NC)" || echo "$(RED)❌$(NC)" @echo -n "$(CYAN) UI :$(NC) "; curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/ 2>/dev/null | grep -q "200" && echo "$(GREEN)✅$(NC)" || echo "$(RED)❌$(NC)" @echo "" # ============================================================================ # DEBUG & INSPECT # ============================================================================ shell-engine: ## 🐚 Открыть shell в контейнере engine @docker compose exec engine bash shell-gateway: ## 🐚 Открыть shell в контейнере gateway @docker compose exec gateway sh shell-ui: ## 🐚 Открыть shell в контейнере UI @docker compose exec ui sh shell-rag: ## 🐚 Открыть shell в контейнере RAG @docker compose exec rag bash shell-qdrant: ## 🐚 Открыть shell в контейнере Qdrant @docker compose exec qdrant sh shell-postgres: ## 🐚 Открыть psql shell @docker compose exec postgres psql -U flowstack shell-redis: ## 🐚 Открыть redis-cli @docker compose exec redis redis-cli inspect-engine: ## 🔍 Инспектировать контейнер engine @docker compose exec engine env | grep -E "^(LLM_|FLOWSTACK_|OPENAI_|RAG_)" | sort inspect-rag: ## 🔍 Инспектировать контейнер RAG @docker compose exec rag env | grep -E "^(LLM_|QDRANT_|SERVER_|CHUNKING_|RUST_)" | sort # ============================================================================ # CLEANUP # ============================================================================ clean: ## 🧹 Очистить build артефакты (не трогая образы) @echo "$(YELLOW)🧹 Очистка build артефактов...$(NC)" @cd core/engine && rm -rf .pytest_cache .ruff_cache .mypy_cache __pycache__ 2>/dev/null || true @cd core/gateway && cargo clean --profile dev 2>/dev/null || true @cd core/rag && cargo clean --profile dev 2>/dev/null || true @cd ui && rm -rf dist .vite 2>/dev/null || true @echo "$(GREEN)✅ Build артефакты очищены$(NC)" clean-rag: ## 🧹 Полная очистка RAG (target + образ) @echo "$(YELLOW)🧹 Полная очистка RAG...$(NC)" @cd core/rag && cargo clean 2>/dev/null || true @docker rmi flowstack-rag:latest 2>/dev/null || true @echo "$(GREEN)✅ RAG очищен$(NC)" clean-cache: ## 🧹 Очистить LLM кэш @echo "$(YELLOW)🧹 Очистка LLM кэша...$(NC)" @docker compose exec engine rm -rf /app/cache/* 2>/dev/null || true @echo "$(GREEN)✅ Кэш очищен$(NC)" clean-qdrant: ## 🧹 Очистить данные Qdrant (все коллекции!) @echo "$(RED)⚠️ ВНИМАНИЕ: Будут удалены ВСЕ данные Qdrant!$(NC)" @read -p "Продолжить? [y/N] " confirm && [ "$$confirm" = "y" ] || exit 1 @docker compose down qdrant @docker volume rm flowstack_qdrant_data 2>/dev/null || true @echo "$(GREEN)✅ Qdrant данные удалены$(NC)" clean-postgres: ## 🧹 Очистить данные PostgreSQL @echo "$(RED)⚠️ ВНИМАНИЕ: Будут удалены ВСЕ данные PostgreSQL!$(NC)" @read -p "Продолжить? [y/N] " confirm && [ "$$confirm" = "y" ] || exit 1 @docker compose down postgres @docker volume rm flowstack_postgres_data 2>/dev/null || true @echo "$(GREEN)✅ PostgreSQL данные удалены$(NC)" clean-all: clean ## 🗑️ Полная очистка (включая Docker образы и volumes) @echo "$(RED)🗑️ Полная очистка Docker ресурсов...$(NC)" @docker compose down -v --rmi local @echo "$(GREEN)✅ Готово$(NC)" # ============================================================================ # UTILS # ============================================================================ restart-%: ## 🔄 Перезапустить конкретный сервис (например: make restart-rag) @echo "$(CYAN)🔄 Перезапуск $*...$(NC)" @docker compose restart $* kill-%: ## 💀 Принудительно остановить сервис @echo "$(RED)💀 Остановка $*...$(NC)" @docker compose kill $* rebuild-%: ## 🔨 Пересобрать и перезапустить конкретный сервис @echo "$(CYAN)🔨 Пересборка $*...$(NC)" @docker compose up --build -d --force-recreate $*