05. Руководство developer / DevOps
Аудитория. Разработчик, кто поднимает проект локально, мержит PR, крутит миграции и деплоит.
Требования к машине
- macOS / Linux.
- Python 3.12 (конкретно 3.12, не 3.11 и не 3.13).
- Node.js 20+ (для frontend).
- Docker 24+ с Compose plugin.
- 8 GB RAM минимум.
make,git,curl.
Для полноценного dev опционально:
jq,httpie— удобство.psqlклиент (можно из контейнера).
Первичная настройка
git clone <repo-url> lms
cd lms
cp .env.example .env.local
# Отредактируй .env.local: пароли, порты, GEMINI_API_KEY (если планируешь живые вызовы).
# В dev по умолчанию LMS_TEST_MODE=1 (Veo/Lyria заблокированы, Nano Banana cap 3/test).
python3.12 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e '.[dev]'
# Поднимаем инфраструктуру (Postgres, Temporal, MinIO, Temporal UI)
docker compose --env-file .env.local -f infra/docker-compose.dev.yml up -d
# Проверим что все 4 контейнера живы (именно lms-dev, не "lms"!)
docker ps --filter name=lms-
# Применим миграции
.venv/bin/alembic upgrade head
# Засеем демо-школу и 4 пользователя (admin/school_admin/teacher/student)
.venv/bin/python -m scripts.bootstrap
# Засеять методики обучения (опционально)
.venv/bin/python -m scripts.seed_methodologies
Скриптов seed_demo / run_course_workflow / localize_course сейчас нет — это был аспирационный текст ранних версий manual. Ниже — как реально запускать.
Frontend:
cd frontend
npm ci
cd ..
Запуск dev-среды
Есть Makefile-таргеты:
make dev-api # FastAPI на 127.0.0.1:55400
make dev-web # Next.js на 127.0.0.1:3500
# Temporal worker — таргета в Makefile нет, запускай напрямую:
.venv/bin/python -m packages.workflows.worker
Либо вручную:
# API
.venv/bin/uvicorn packages.core.main:app --host 127.0.0.1 --port 55400 --reload
# Worker
.venv/bin/python -m packages.workflows.worker
# Web
cd frontend && npm run dev
Все сервисы строго на loopback (127.0.0.1, не 0.0.0.0) — это прописано в ADR-0002.
Порты (dev, .env.local)
| Сервис | Порт | URL |
|---|---|---|
| FastAPI | 55400 | http://127.0.0.1:55400 |
| Next.js | 3500 | http://127.0.0.1:3500 |
| PostgreSQL | 55432 | postgresql://lms:change_me_locally@127.0.0.1:55432/lms |
| Temporal gRPC | 55433 | 127.0.0.1:55433 |
| Temporal UI | 55480 | http://127.0.0.1:55480 |
| MinIO API | 55490 | http://127.0.0.1:55490 |
| MinIO Console | 55491 | http://127.0.0.1:55491 |
Все меняются в .env.local.
Тесты
.venv/bin/pytest -q tests/ # всё
.venv/bin/pytest -q tests/test_adaptive_supplementer.py # один файл
.venv/bin/pytest -k "critic and not live" -q # по имени
Minimum coverage для packages/core и packages/agents — 70% (manifest §9).
Frontend:
cd frontend && npx tsc --noEmit # типы
npx biome check # lint
npm test # когда будут компонент-тесты
Миграции
ОБЯЗАТЕЛЬНО: перед каждым alembic upgrade (даже dev) — дамп БД в MinIO.
bash scripts/backup_db_to_minio.sh pre-<migration-tag>
# Последняя строка вывода — s3://db-backups/lms-<TS>-<tag>.sql.gz
# ВСТАВЬ её в тело коммита миграции.
.venv/bin/alembic upgrade head
Создать новую миграцию:
.venv/bin/alembic revision -m "0016_short_description"
# Открой файл в packages/core/migrations/versions/ и допиши upgrade/downgrade.
# RLS-политики — ОТДЕЛЬНОЙ миграцией, префикс rls_.
Проверь что в файле ровно один upgrade():
grep -c "^def upgrade" packages/core/migrations/versions/0016_*.py # должно быть 1
Agent prompts (ADR-0011)
Статические промпты агентов — в таблице agent_prompts (append-only). Никаких STATIC_PREFIX = "..." в prompt.py.
Опубликовать новую версию:
.venv/bin/python -m scripts.prompt_cli publish <slug> --file path/to/body.txt --notes "..."
В миграциях — новый INSERT с version = MAX+1.
Если случайно надо переписать существующую версию в dev (ТОЛЬКО dev!):
ALTER TABLE agent_prompts DISABLE TRIGGER agent_prompts_no_update;
DELETE FROM agent_prompts WHERE slug='...' AND version=1;
ALTER TABLE agent_prompts ENABLE TRIGGER agent_prompts_no_update;
Затем alembic stamp <prev> + alembic upgrade head.
MinIO (object storage)
Console: http://127.0.0.1:55491 (логин — из MINIO_ROOT_USER / MINIO_ROOT_PASSWORD).
Бакеты:
course-materials— исходники курсов (PDF/MD/TXT от teacher'ов).media-assets— сгенерированные картинки/аудио/видео.db-backups— дампыpg_dumpперед миграциями.
Temporal
Workflows (реально зарегистрированные):
SamplePingWorkflow— sanity-ping.CourseGenerationWorkflow— генерация курса с нуля. CLI-обёртки нет, запускается из тестов / кастомного скрипта.
Локализация (Localizer-агент) и генерация медиа сейчас вызываются через HTTP-эндпоинты (/courses/{id}/translations, /media/generate-image, /media/generate-narration), без отдельного end-to-end workflow.
Правила (ADR-0001, manifest §7):
- Activities — идемпотентны.
- В workflow — никакого
datetime.now(),uuid.uuid4(), random, I/O. Толькоworkflow.now(),workflow.random(), activities. - Long-running — heartbeat.
- Prompt pinning: каждый workflow первым шагом вызывает
load_prompt_snapshot→ прокидываетPromptSnapshotв каждую activity, которая зовёт агента с промптом.
Gemini API
- Все вызовы — только через
packages/shared/llm_client.py. - Выбор модели — через
ModelTierenum (FAST / PRO / REASONING / ...). Не хардкодить строки. - В dev
LMS_TEST_MODE=1,MAX_DAILY_USD=5.0. - Cost tracking — автоматически в
llm_cost_entries(school_id, user_id, model, tokens_in/out, cost_usd).
Список актуальных моделей — docs/PROJECT_MANIFEST.md §3 или MCP lms-gemini.list_available_models.
MCP-серверы (для IDE)
.vscode/mcp.json подключает 4 stdio-сервера:
lms-db— describe_table, run_readonly_query, list_migrationslms-agents— list_all_agents, check_agent_existslms-methodology— list_methodologies, suggest_ensemblelms-gemini— estimate_cost, list_available_models
Smoke-тест:
make mcp-test
Деплой (концепт, prod — вне Phase 5)
- Бэкап БД.
git pullна сервере.docker compose build --no-cacheдля обновлённых образов.alembic upgrade head.docker compose up -d.- Health check:
curl https://api.your-domain/health→200. - Browser-тест ключевых страниц.
Чего НЕ делать
- Не коммитить
.env.local,/memories/,.vscode/mcp.json,.github/copilot-instructions.md,.github/prompts/,.github/chatmodes/,AGENTS.md,CLAUDE.md,.cursor/,.claude/и прочие AI-артефакты. Всё в.gitignore. - Не упоминать в коммит-месседжах/коде/doc'ах AI-инструменты разработки. Gemini в runtime — ок (это продукт).
- Не прогонять Gemini в цикле без
estimate_cost. - Не использовать
docker composeбез-f infra/docker-compose.dev.yml --env-file .env.local(рядом может быть другойlmsпроект). - Не делать миграцию без MinIO-бэкапа.
Полезные команды
# Проверить актуальную версию миграций
.venv/bin/alembic current
# История
.venv/bin/alembic history --verbose
# Откат на N шагов
.venv/bin/alembic downgrade -1
# Смотреть живые логи API
tail -f /tmp/lms-api.log # если запускаешь через nohup
# Проверить RLS-конфиг текущей сессии
psql "postgresql://lms_app:change_me_locally@127.0.0.1:55432/lms" -c "SHOW app.current_user_id;"
# Перегенерить TS-типы (когда появится OpenAPI)
.venv/bin/python -m scripts.dump_openapi > frontend/types/openapi.json