13 KiB
DevConsole
Веб-панель для управления сборкой и запуском Flutter/Android-проектов на одном Linux-сервере. Оператор добавляет Git-репозиторий, DevConsole клонирует его в рабочий каталог, определяет стек, ставит зависимости, и дальше по кнопке выполняет типовые команды (git pull, flutter clean, flutter pub get, flutter build apk, flutter run --profile, adb logcat) с live-выводом в браузер. Собранный APK можно поставить на подключённое по ADB устройство или выложить по SFTP на сервер обновлений вместе с latest.json (OTA). Дополнительно есть песочница обращений к OpenAI Responses API с автоподбором модели по типу задачи.
Панель рассчитана на одного владельца сервера: аутентификации нет, всё, что открыто по HTTP, выполняется с правами сервисного пользователя.
Стек
- Python 3, FastAPI, Uvicorn.
- SQLite (
sqlite3из стандартной библиотеки) — хранилище настроек. SQLAlchemy/aiosqlite объявлены в зависимостях, но в коде не используются. - JSON-файлы — реестр проектов и реестр APK-артефактов.
- Frontend: статический HTML + ванильный JavaScript, без сборщика.
- OpenAI SDK (Responses API), модели по умолчанию
gpt-5/gpt-5-mini. - paramiko — SFTP-публикация OTA.
- Внешние системные инструменты:
git,adb,flutter,sdkmanager,docker,systemctl,nginx. - Развёртывание: bash-установщик + systemd unit.
Структура
| Путь | Назначение |
|---|---|
backend/main.py |
Точка входа FastAPI, подключение роутеров, статус системы, настройки OpenAI/GitHub, эндпоинты сборки и выдачи APK |
backend/config_store.py |
Настройки в SQLite (settings): ключ OpenAI, модель, учётка GitHub, параметры SOCKS5-прокси |
backend/openai_client.py |
Обёртка над OpenAI Responses API |
backend/model_router.py |
Выбор модели по типу задачи и по ключевым словам в промпте |
backend/project_analyzer.py |
Клонирование/обновление репозитория, определение стека, список шагов установки зависимостей |
backend/projects_registry.py |
Реестр проектов в projects_registry.json (включая настройки OTA) |
backend/projects_api.py |
/api/projects/* — список, регистрация, настройки проекта, версия из pubspec |
backend/runtime_api.py |
/api/runtime/* — набор runtime-команд, потоковый (SSE) вывод, остановка, установка/удаление APK, рестарт приложения |
backend/flutter_manual_api.py |
/api/runtime/flutter-manual-stream и flutter-batch-stream — ручные и пакетные команды Flutter |
backend/shell_runner.py |
Запуск shell-команд с чёрным списком опасных токенов и ограничением рабочего каталога |
backend/android_tools.py |
adb devices с разбором свойств устройств, поиск APK, flutter build apk, установка APK |
backend/ota_publish.py |
Публикация APK и latest.json по SFTP, синхронизация версии из pubspec.yaml |
backend/artifacts_registry.py |
История собранных APK в apk_artifacts.json (до 50 записей на workspace) |
backend/pubspec_tools.py |
Чтение version: X.Y.Z+build из pubspec.yaml |
backend/file_workspace.py, backend/workspace_api.py |
/api/files/* — дерево, чтение и запись файлов внутри каталога проектов |
backend/system_api.py |
/api/system/checks и /api/system/restart — проверка Flutter/SDK/ADB/Docker/Nginx. Роутер не подключён в main.py |
backend/publish_files_api.py |
Загрузка google-services.json, keystore, key.properties и т.п. в проект. Роутер не подключён в main.py |
backend/runtime_logs.py |
Кольцевой буфер системного лога в памяти |
frontend/runtime.html, frontend/workspace.js |
Актуальный интерфейс: проекты, устройства, runtime-сценарии, логи, панель ошибок |
frontend/index.html, frontend/app.js |
Старый интерфейс редактора. Помечен в docs/RUNTIME_UI_BASELINE.md как legacy |
docs/RUNTIME_UI_BASELINE.md |
Зафиксированный baseline UI и правило: корневой маршрут отдаёт runtime.html |
scripts/install_ubuntu.sh |
Установщик под Ubuntu: пакеты, Docker, пользователь, venv, .env, udev-правила, systemd |
requirements.txt |
Python-зависимости |
Как запустить
Штатный путь — установщик (требует root, ставит систему целиком и заводит systemd-сервис):
sudo bash scripts/install_ubuntu.sh
Установщик создаёт пользователя devconsole, каталоги /opt/devconsole, /var/lib/devconsole, /var/log/devconsole, ставит adb, fastboot, openjdk-17-jdk, Docker, клонирует репозиторий с GitHub и поднимает сервис на порту 8077.
Важно: clone_or_update_repo() тянет код из DEVCONSOLE_REPO_URL (по умолчанию GitHub) и делает git reset --hard + git clean -fd в /opt/devconsole. При переезде на Gitea переменную нужно переопределить, иначе установщик перезапишет каталог кодом из GitHub.
Ручной запуск для разработки:
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
DEVCONSOLE_DATA_DIR=./data ./venv/bin/uvicorn backend.main:app --host 0.0.0.0 --port 8077
Запускать из корня репозитория — импорты в коде абсолютные (from backend...). Flutter SDK и Android SDK установщиком не ставятся, их нужно поставить отдельно и указать через переменные окружения.
Конфигурация
Часть настроек читается из .env (создаётся установщиком), часть хранится в SQLite и задаётся через веб-панель. Значения из SQLite имеют приоритет над переменными окружения.
| Имя | Назначение | Пример |
|---|---|---|
DEVCONSOLE_HOST |
Адрес прослушивания (используется только в systemd unit) | 0.0.0.0 |
DEVCONSOLE_PORT |
Порт панели | 8077 |
DEVCONSOLE_DATA_DIR |
Каталог данных: БД настроек, projects/, реестры, артефакты |
/var/lib/devconsole |
DEVCONSOLE_LOG_DIR |
Каталог логов (используется в unit-файле) | /var/log/devconsole |
DEVCONSOLE_USB_DIR |
Каталог USB-зоны отладки | /mnt/devconsole-usb |
DEVCONSOLE_RUNTIME_HOME |
HOME для runtime-команд Flutter/ADB | /home/devconsole |
FLUTTER_HOME |
Каталог Flutter SDK, подставляется в PATH runtime-команд | /opt/flutter |
ANDROID_HOME / ANDROID_SDK_ROOT |
Каталог Android SDK | /opt/android-sdk |
PUB_CACHE |
Кэш pub | /home/devconsole/.pub-cache |
OPENAI_API_KEY |
Ключ OpenAI. Можно не задавать в .env и ввести через панель |
см. .env |
OPENAI_MODEL |
Модель по умолчанию | gpt-5 |
GITHUB_USERNAME |
Логин для клонирования приватных репозиториев | viktor138irk |
GITHUB_TOKEN |
Токен для клонирования. Подставляется в URL вида https://user:token@... |
см. .env |
PROXY_ENABLED |
Включение SOCKS5-прокси (1/0) |
0 |
PROXY_HOST, PROXY_PORT, PROXY_USERNAME, PROXY_PASSWORD |
Параметры SOCKS5-прокси | 127.0.0.1, 1080 |
DEVCONSOLE_ALLOW_SHELL, DEVCONSOLE_ALLOW_DOCKER, DEVCONSOLE_ALLOW_ANDROID |
Пишутся установщиком в .env как флаги безопасности, но в коде нигде не читаются |
1 |
DEVCONSOLE_DATABASE_URL |
Пишется установщиком в .env, в коде не используется |
sqlite+aiosqlite:///... |
Настройки OTA задаются не через окружение, а по каждому проекту в панели и хранятся в projects_registry.json: sftp_host, sftp_port, sftp_username, sftp_password, remote_path, public_base_url, latest_json_name, latest_apk_name, version, build, notes.
Состояние
Прототип, брошенный после короткого интенсивного спринта. Вся работа уложилась в два дня: 11 и 12 мая 2026 года. 96 коммитов, последний — 12.05.2026. Версия в коде — 0.3.1, в файле VERSION — 0.1.0.
Основной сценарий (добавленный проект → runtime-команды → live-лог → установка APK на устройство) собран целиком. Части, добавленные последними, до конца не сведены между backend и frontend.
Что не доделано
- В
frontend/runtime.htmlесть обработчики, которых нет вfrontend/workspace.js:openAddProjectModal,closeAddProjectModal,analyzeProject,loadApkArtifacts,syncPubspecVersion. То есть модалка «Добавить проект», панель APK-артефактов и кнопка чтения версии из pubspec в текущем UI не работают. - Роутеры
system_apiиpublish_files_apiне подключены вmain.py. Панель статусов систем в UI и загрузкаgoogle-services.json/keystore недоступны. - Эндпоинты
/api/projects/analyze,/api/projects/install-dependencies,/api/android/build,/api/android/apks,/api/files/*не вызываются из актуального интерфейса. - Нет аутентификации и авторизации. Открытая панель даёт запуск произвольных shell-команд (
shell_runner,runtime_api,flutter_manual_api) и запись файлов. Защита сводится к чёрному списку строк вродеrm -rf /и требованию, чтобы рабочий каталог лежал внутри каталога проектов. - Пароли SFTP и токен GitHub хранятся в открытом виде: в
projects_registry.jsonи в таблицеsettingsSQLite. - SOCKS5-прокси настраивается (
build_proxy_url,httpx-socksв зависимостях), но нигде не применяется:openai_client.pyсоздаёт клиент без прокси. - Из
requirements.txtфактически не используютсяsqlalchemy,aiosqlite,websockets,httpx,httpx-socks,python-dotenv. - Задекларированные в исходном README модули (оркестратор агентов, snapshot/rollback, очередь задач, SSH runner, история диалогов) не реализованы.
- Тестов нет. CI нет. Миграций БД нет — таблица
settingsсоздаётся на лету. - В
system_api.pyсостояние сервисов определяется черезsystemctlиdocker— на машине без systemd эти проверки бесполезны.