Files
AnabasisChatRemove/build.py
benya 8d4bc10cb7
Some checks failed
Desktop Dev Pre-release / prerelease (push) Failing after 2m18s
feat(updater): stage3 resilient gui update flow
- added retry-based file copy, rollback restart, and version marker validation in updater GUI

- added build step to write dist/version.txt for post-update validation

- added unit tests for updater helpers
2026-02-15 21:46:36 +03:00

148 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import shutil
import subprocess
import sys
from app_version import APP_VERSION
# --- Конфигурация ---
APP_NAME = "AnabasisManager"
UPDATER_NAME = "AnabasisUpdater"
VERSION = APP_VERSION # Единая версия приложения
MAIN_SCRIPT = "main.py"
UPDATER_SCRIPT = "updater_gui.py"
ICON_PATH = "icon.ico"
DIST_DIR = os.path.join("dist", APP_NAME)
ARCHIVE_NAME = f"{APP_NAME}-{VERSION}" # Формат Название-Версия
SAFE_CLEAN_ROOT_FILES = {"main.py", "updater_gui.py", "requirements.txt", "build.py"}
REMOVE_LIST = [
"Qt6Pdf.dll", "Qt6PdfQuick.dll", "Qt6PdfWidgets.dll",
"Qt6VirtualKeyboard.dll", "Qt6Positioning.dll",
"Qt6PrintSupport.dll", "Qt6Svg.dll", "Qt6Sql.dll",
"Qt6Charts.dll", "Qt6Multimedia.dll", "Qt63DCore.dll",
"translations",
"Qt6QuickTemplates2.dll"
]
def write_version_marker():
marker_path = os.path.join(DIST_DIR, "version.txt")
try:
os.makedirs(DIST_DIR, exist_ok=True)
with open(marker_path, "w", encoding="utf-8") as f:
f.write(str(VERSION).strip() + "\n")
print(f"[OK] Обновлен маркер версии: {marker_path}")
except Exception as e:
print(f"[ERROR] Не удалось записать version.txt: {e}")
sys.exit(1)
def ensure_project_root():
missing = [name for name in SAFE_CLEAN_ROOT_FILES if not os.path.exists(name)]
if missing:
print("[ERROR] Скрипт нужно запускать из корня проекта.")
print(f"[ERROR] Не найдены: {', '.join(missing)}")
sys.exit(1)
def run_build():
print(f"--- 1. Запуск PyInstaller для {APP_NAME} v{VERSION} ---")
command = [
"pyinstaller",
"--noconfirm",
"--onedir",
"--windowed",
"--exclude-module", "PySide6.QtWebEngineCore",
"--exclude-module", "PySide6.QtWebEngineWidgets",
"--exclude-module", "PySide6.QtWebEngineQuick",
f"--name={APP_NAME}",
f"--icon={ICON_PATH}" if os.path.exists(ICON_PATH) else "",
f"--add-data={ICON_PATH}{os.pathsep}." if os.path.exists(ICON_PATH) else "",
f"--add-data=auth_webview.py{os.pathsep}.",
MAIN_SCRIPT
]
command = [arg for arg in command if arg]
try:
subprocess.check_call(command)
print("\n[OK] Сборка PyInstaller завершена.")
except subprocess.CalledProcessError as e:
print(f"\n[ERROR] Ошибка при сборке: {e}")
sys.exit(1)
def run_updater_build():
print(f"\n--- 1.2 Сборка {UPDATER_NAME} ---")
command = [
"pyinstaller",
"--noconfirm",
"--onefile",
"--windowed",
f"--name={UPDATER_NAME}",
"--distpath", DIST_DIR,
"--workpath", os.path.join("build", "updater"),
"--specpath", os.path.join("build", "updater_spec"),
f"--icon={ICON_PATH}" if os.path.exists(ICON_PATH) else "",
UPDATER_SCRIPT,
]
command = [arg for arg in command if arg]
try:
subprocess.check_call(command)
print(f"[OK] {UPDATER_NAME} собран.")
except subprocess.CalledProcessError as e:
print(f"[ERROR] Ошибка при сборке {UPDATER_NAME}: {e}")
sys.exit(1)
def run_cleanup():
print(f"\n--- 2. Оптимизация папки {APP_NAME} ---")
# Пытаемся найти папку PySide6 внутри сборки
pyside_path = os.path.join(DIST_DIR, "PySide6")
if not os.path.exists(pyside_path):
pyside_path = DIST_DIR
for item in REMOVE_LIST:
path = os.path.join(pyside_path, item)
if os.path.exists(path):
try:
if os.path.isdir(path):
shutil.rmtree(path)
else:
os.remove(path)
print(f"Удалено: {item}")
except Exception as e:
print(f"Пропуск {item}: {e}")
def create_archive():
print(f"\n--- 3. Создание архива {ARCHIVE_NAME}.zip ---")
try:
# Создаем zip-архив из папки DIST_DIR
# base_name - имя файла без расширения, format - 'zip', root_dir - что упаковываем
shutil.make_archive(os.path.join("dist", ARCHIVE_NAME), 'zip', DIST_DIR)
print(f"[OK] Архив создан: dist/{ARCHIVE_NAME}.zip")
except Exception as e:
print(f"[ERROR] Не удалось создать архив: {e}")
if __name__ == "__main__":
ensure_project_root()
# Предварительная очистка
for folder in ["build", "dist"]:
if os.path.exists(folder):
shutil.rmtree(folder)
run_build()
run_updater_build()
run_cleanup()
write_version_marker()
create_archive()
print("\n" + "=" * 30)
print("ПРОЦЕСС ЗАВЕРШЕН")
print(f"Файл для отправки: dist/{ARCHIVE_NAME}.zip")
print("=" * 30)