Skip to content

Latest commit

 

History

History
394 lines (284 loc) · 18.1 KB

File metadata and controls

394 lines (284 loc) · 18.1 KB

Анализ программы GUI Bootstrap Manager

1. Назначение программы

GUI Bootstrap Manager — это desktop-приложение на PySide6 для автоматизации старта новых проектов под разные технологические стеки.

Программа решает 4 задачи:

  1. Проверка доступности инструментов разработки в системе (git, python, node, dotnet и т.д.).
  2. Provisioning (подготовка среды) через PowerShell-скрипт с winget.
  3. Генерация структуры нового проекта из Jinja2-шаблонов.
  4. Запуск стек-специфичной инициализации фреймворка (например, wails init, create-next-app, dotnet new, создание Python venv).

Итог: пользователь через GUI получает готовую директорию проекта с базовой структурой, скриптами запуска/сборки, метаданными и (опционально) инициализированным Git-репозиторием.


2. Что входит в проект

Корневые элементы:

  • main.py — точка входа.
  • app/ — GUI и бизнес-логика.
  • templates/ — шаблоны файлов для каждого стека.
  • provisioning/setup_env.ps1 — сценарий установки инструментов.
  • requirements.txt — зависимости текущего GUI-приложения (PySide6, Jinja2).

Ключевые модули app/:

  • app/main.py — создание QApplication и запуск окна.
  • app/window.py — главное окно и обработчики действий пользователя.
  • app/models.py — описание поддерживаемых стеков (конфигурация).
  • app/services/tooling.py — проверка инструментов и версий.
  • app/services/provisioning.py — запуск provisioning-скрипта.
  • app/services/generator.py — генерация проекта и пост-обработка.
  • app/utils.py — утилиты путей, нормализация имени проекта.
  • app/widgets/log_view.py — виджет лога.

3. Поддерживаемые стеки и профили

Стек определяется в app/models.py (словарь STACKS).

Поддерживаются:

  1. go — Wails + React + TypeScript + Tailwind.
  2. cs — .NET + WinUI 3 + Windows App SDK + XAML.
  3. python — PySide6 + Qt Quick + QML + PyInstaller + Nuitka.
  4. astro — Astro + TypeScript + Tailwind.
  5. next — Next.js + TypeScript + React + Tailwind.
  6. docs — Docusaurus + TypeScript + MDX.

Для каждого стека задано:

  • required_tools — список инструментов, проверяемых в GUI.
  • provision_profile — профиль для PowerShell provisioning (go, cs, python, web, docs).
  • template_dir — каталог шаблонов в templates/.

DEFAULT_PROJECT_ROOT = Path.home() / "Projects" — базовый путь для новых проектов в UI.


4. Жизненный цикл приложения

4.1 Запуск

  1. Выполняется корневой main.py.
  2. Он вызывает app.main.run().
  3. В run():
    • создается QApplication;
    • задаются имя приложения и организация;
    • создается MainWindow;
    • окно показывается;
    • запускается event loop через app.exec().

4.2 Инициализация окна

В MainWindow.__init__():

  1. Устанавливаются заголовок и размер окна.
  2. Создается ProjectGenerator.
  3. Строится UI (_build_ui).
  4. Заполняется список стеков (_fill_stacks).
  5. В поле целевой папки подставляется DEFAULT_PROJECT_ROOT.

4.3 Первичная проверка инструментов

_fill_stacks() вызывает on_stack_changed(), а тот вызывает on_check_tools(). То есть сразу после запуска идет проверка инструментов для текущего выбранного стека + powershell + winget.


5. Интерфейс и пользовательские действия

Экран состоит из 3 блоков:

  1. Создание проекта:

    • имя проекта;
    • папка назначения;
    • стек;
    • чекбокс git init;
    • чекбокс Upgrade при provisioning;
    • кнопки: выбрать папку, подготовить среду, создать проект.
  2. Проверка инструментов:

    • кнопка обновления;
    • таблица с колонками: Tool, Found, Path, Version.
  3. Лог:

    • текстовый лог;
    • кнопка очистки.

Отдельно есть кнопка Открыть папку проекта.

5.1 Смена стека

on_stack_changed():

  • обновляет описание стека в description_view;
  • запускает повторную проверку инструментов.

5.2 Проверка инструментов

on_check_tools():

  1. Берет required_tools выбранного стека.
  2. Добавляет powershell и winget.
  3. Вызывает check_many(...).
  4. Заполняет таблицу статусами.
  5. Пишет запись в лог.

Механика check_many/check_tool (app/services/tooling.py):

  • путь ищется через shutil.which;
  • если команда найдена, версия определяется через subprocess.run с соответствующей командой (git --version, node --version, и т.п.);
  • timeout получения версии: 10 секунд;
  • исключения при получении версии не роняют процесс, версия просто остается пустой.

5.3 Provisioning среды

on_provision():

  1. Берет provision_profile текущего стека.
  2. Вызывает start_provisioning(profile, upgrade).
  3. Если процесс запущен, читает stdout целиком через read() и пишет вывод в лог.
  4. Ошибки показываются через QMessageBox.critical и пишутся в лог.

start_provisioning (app/services/provisioning.py):

  • находит provisioning/setup_env.ps1 через app_root();
  • проверяет, что файл существует;
  • разрешает запуск только на Windows (os.name == "nt");
  • запускает powershell -NoProfile -ExecutionPolicy Bypass -File ... -Profile ... [-Upgrade];
  • возвращает subprocess.Popen с объединенным stdout/stderr.

Важно: чтение stdout.read() синхронное, UI может ждать завершения provisioning.

5.4 Создание проекта

on_create_project():

  1. Читает project_name, target_root, stack_key, git_init.
  2. Валидирует непустое имя.
  3. Вызывает ProjectGenerator.generate(...).
  4. При успехе:
    • логирует путь проекта;
    • логирует число созданных файлов;
    • добавляет вывод framework-init, если он есть;
    • показывает QMessageBox.information.
  5. При ошибке: лог + QMessageBox.critical.

5.5 Открыть папку проекта

on_open_project_dir():

  • требует заполненное имя проекта;
  • формирует путь как root_edit / project_name (в этом месте имя не нормализуется, используется сырой ввод);
  • если папки нет, показывает ошибку;
  • если Windows: os.startfile(path);
  • иначе: xdg-open.

6. Алгоритм генерации проекта (детально)

Основной поток в ProjectGenerator.generate(...):

  1. Проверка, что stack_key существует в STACKS.
  2. Нормализация имени проекта (normalize_project_name):
    • допустимы только [A-Za-z0-9-_];
    • остальные символы заменяются на _;
    • повторяющиеся __ схлопываются;
    • подчеркивания по краям убираются.
  3. Если после нормализации имя пустое — ошибка.
  4. Формируется project_dir = target_root / safe_name.
  5. Если папка уже существует — FileExistsError.
  6. Создается project_dir.
  7. Создаются базовые подпапки:
    • src, assets, assets/locales, docs, tests, build, scripts, tools.
  8. Рендерятся шаблоны выбранного стека (_render_stack_templates).
  9. Выполняется framework-init (_run_framework_init).
  10. Дописываются общие служебные файлы:
    • CHANGELOG.md;
    • assets/locales/en.json, ru.json, uk.json;
    • .cursorrules, .windsurfrules, AGENTS.md, .editorconfig, .gitignore, .env.example;
    • bootstrap.meta.json.
  11. Если включен git_init — выполняется git init.
  12. Возвращается GenerationResult:
    • путь проекта;
    • список созданных из шаблонов файлов;
    • вывод framework-init команд.

6.1 Рендер шаблонов

_render_stack_templates(...):

  • берет каталог templates/<template_dir>;
  • рекурсивно проходит все файлы;
  • для .j2:
    • удаляет суффикс .j2 у целевого файла;
    • рендерит Jinja2-контекстом: project_name, stack;
    • пишет UTF-8 текст;
  • для не-.j2 файлов копирует как есть (shutil.copy2);
  • возвращает список созданных путей.

6.2 Framework-init по стеку

_run_framework_init(...):

  • python:

    1. python -m venv venv;
    2. venv\Scripts\python.exe -m pip install -U pip;
    3. venv\Scripts\python.exe -m pip install -r requirements.txt.
  • go:

    • cmd /c "cd /d src && wails init -n src -t react-ts".
  • cs:

    • dotnet new winui -n <project_name> -o src.
  • astro:

    • cmd /c "npm create astro@latest src -- --template basics --typescript --install --no-git".
  • next:

    • cmd /c "npx create-next-app@latest src --ts --tailwind --eslint --app --src-dir --import-alias @/* --use-npm".
  • docs:

    • cmd /c "npx create-docusaurus@latest src classic --typescript".

Все команды запускаются через _run_optional_command:

  • используется subprocess.run(..., capture_output=True, text=True, shell=False);
  • возвращается строка вида [Label] exit=<code> + stdout/stderr;
  • если команда не найдена, возвращается skipped: command not found;
  • при любой другой ошибке возвращается failed: <error>;
  • это не прерывает генерацию автоматически (ошибка конвертируется в текстовый результат).

6.3 Пост-генерационные файлы

Генератор всегда добавляет:

  • CHANGELOG.md с записью про initial scaffold;
  • локали с greeting на en/ru/uk;
  • правила для IDE/агентов (.cursorrules, .windsurfrules, AGENTS.md);
  • .editorconfig, .gitignore, .env.example;
  • bootstrap.meta.json с метаданными проекта.

git init выполняется «best effort»: исключения подавляются (except Exception: pass).


7. Что именно генерируется по шаблонам

Для каждого стека есть минимум:

  • README.md
  • docs/STACK.md
  • scripts/build.bat
  • scripts/run.bat
  • scripts/clean.bat
  • scripts/check_env.bat

Дополнительно:

  • go: package.json
  • python:
    • requirements.txt
    • src/main.py
    • src/main.qml
    • scripts/AppxManifest.xml

Скрипты ориентированы на Windows (.bat) и запускают типичные команды для dev/build/clean/check окружения.


8. Алгоритм provisioning (provisioning/setup_env.ps1)

Параметры:

  • -Profile: один из go, cs, python, web, docs, all.
  • -Upgrade: при наличии пытается выполнить winget upgrade перед winget install.

Порядок выполнения:

  1. Включается ErrorActionPreference = "Stop".
  2. Проверяется запуск PowerShell от администратора (Require-Admin).
  3. Проверяется наличие winget (Require-Winget).
  4. Ставятся базовые инструменты:
    • Git.Git
    • Microsoft.VisualStudioCode
  5. По профилю ставятся стековые зависимости:
    • go: Go + Node LTS + go install ... wails;
    • cs: .NET SDK 8 + Windows SDK;
    • python: Python 3.12 + Node LTS + pip-пакеты (PySide6/PyInstaller/Nuitka/Jinja2);
    • web: Node LTS;
    • docs: Node LTS;
    • all: объединение всех выше.
  6. Пишется сообщение о завершении.

Если после установки Go команда go еще не в PATH, скрипт выводит предупреждение и просит перезапустить PowerShell.


9. Обработка ошибок и устойчивость

Что сделано:

  • Ошибки UI-операций (provision/create/open) перехватываются и показываются пользователю через модальные окна.
  • Проверка инструментов не падает на ошибках получения версии.
  • Отсутствие внешних команд в framework-init не приводит к крэшу генератора: возвращается текст skipped.
  • Проверка существования папки проекта предотвращает перезапись.

Наблюдаемые ограничения:

  1. Provisioning выполняется синхронным чтением stdout.read(), что может блокировать UI до завершения процесса.
  2. В on_open_project_dir используется сырое имя проекта, а генерация использует нормализованное: при спецсимволах возможен «путь не найден» после успешной генерации.
  3. git init выполняется без проверки кода возврата и без лога причин ошибки.
  4. Команды framework-init выполняются даже если required_tools фактически не найдены; проверка в таблице носит информативный характер, а не блокирующий.

10. Зачем программа полезна

Программа нужна как GUI-оркестратор старта проекта:

  • снижает ручную рутину по созданию структуры и базовых файлов;
  • стандартизирует bootstrap для нескольких стеков;
  • позволяет non-CLI пользователям запускать provisioning и генерацию из одного окна;
  • ускоряет выход к рабочему «нулевому» состоянию проекта (src, scripts, базовые конфиги, локали, метаданные, опционально git).

Иными словами, это внутренний инструмент стандартизированного проектного старта, а не runtime-приложение конечного пользователя.


11. Краткий псевдо-поток (end-to-end)

Start app
  -> create QApplication
  -> show MainWindow
  -> load stacks
  -> auto-check tools for selected stack

User chooses stack/root/name
  -> optional: run provisioning (PowerShell profile)
  -> click "Create project"
       -> validate and normalize name
       -> create project directory and base folders
       -> render stack templates
       -> run stack framework init commands
       -> write common files/locales/metadata
       -> optional git init
       -> show success + logs

User may open created folder from UI

12. Файлы текущего приложения (быстрый индекс)

  • main.py — делегирует запуск в app.main.run.
  • app/main.py — точка запуска Qt event loop.
  • app/window.py — весь GUI + handlers.
  • app/models.py — конфигурация стеков.
  • app/utils.py — путь приложения, нормализация имени, mkdir helper.
  • app/services/tooling.py — which + version probing.
  • app/services/provisioning.py — запуск PowerShell provisioning.
  • app/services/generator.py — генератор проекта + framework init + общие файлы.
  • app/widgets/log_view.py — текстовый лог-виджет.
  • provisioning/setup_env.ps1 — установка SDK/инструментов через winget.
  • templates/** — шаблоны генерируемых файлов для стеков.