Ajout updater auto + build_exe.bat + version.txt

- app/updater.py : verifie les mises a jour depuis Gitea, telecharge
  via git pull ou archive zip
- version.txt : version courante (1.0.0)
- build_exe.bat : script de compilation PyInstaller pour Windows
  avec tous les hidden-imports necessaires (reportlab fonts, pypdfium2)
- Au lancement, propose la mise a jour si nouvelle version disponible
- Apres mise a jour, redemarre automatiquement

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jules
2026-03-20 19:08:43 +01:00
parent 057b6c1d3c
commit 83dc563135
4 changed files with 229 additions and 0 deletions

129
app/updater.py Normal file
View File

@@ -0,0 +1,129 @@
"""Mise a jour automatique depuis Gitea."""
import os
import sys
import json
import urllib.request
import urllib.error
import subprocess
import tempfile
import shutil
GITEA_API = "https://git.copydev.fr/api/v1"
REPO = "jules/copydev-imposing-tool"
BRANCH = "master"
# Version actuelle (incrementee a chaque release)
VERSION = "1.0.0"
def get_remote_version():
"""Recuperer la version distante depuis le fichier version.txt sur Gitea."""
try:
url = f"{GITEA_API}/repos/{REPO}/raw/version.txt?ref={BRANCH}"
req = urllib.request.Request(url, headers={"User-Agent": "CopydevImposingTool"})
with urllib.request.urlopen(req, timeout=10) as resp:
return resp.read().decode().strip()
except Exception:
return None
def check_for_update():
"""Verifier si une mise a jour est disponible.
Retourne (disponible: bool, version_distante: str ou None)
"""
remote = get_remote_version()
if not remote:
return False, None
if remote != VERSION:
return True, remote
return False, remote
def get_app_dir():
"""Trouver le dossier de l'application."""
if getattr(sys, 'frozen', False):
return os.path.dirname(sys.executable)
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def do_update():
"""Telecharger et appliquer la mise a jour.
Retourne (success: bool, message: str)
"""
app_dir = get_app_dir()
# Verifier si git est disponible
git_cmd = _find_git()
if not git_cmd:
return False, "Git introuvable. Reinstallez l'application."
# Si c'est un repo git, faire un pull
git_dir = os.path.join(app_dir, ".git")
if os.path.isdir(git_dir):
try:
result = subprocess.run(
[git_cmd, "pull", "origin", BRANCH],
cwd=app_dir, capture_output=True, text=True, timeout=60
)
if result.returncode == 0:
return True, f"Mise a jour reussie.\n{result.stdout}"
return False, f"Erreur git pull:\n{result.stderr}"
except Exception as e:
return False, str(e)
# Sinon, telecharger l'archive zip depuis Gitea
try:
url = f"{GITEA_API}/repos/{REPO}/archive/{BRANCH}.zip"
req = urllib.request.Request(url, headers={"User-Agent": "CopydevImposingTool"})
with urllib.request.urlopen(req, timeout=120) as resp:
tmp = tempfile.mktemp(suffix=".zip")
with open(tmp, "wb") as f:
f.write(resp.read())
# Extraire
import zipfile
tmp_dir = tempfile.mkdtemp()
with zipfile.ZipFile(tmp, "r") as z:
z.extractall(tmp_dir)
# Trouver le dossier extrait
extracted = os.listdir(tmp_dir)
if extracted:
src = os.path.join(tmp_dir, extracted[0])
# Copier les fichiers
for item in os.listdir(src):
s = os.path.join(src, item)
d = os.path.join(app_dir, item)
if os.path.isdir(s):
if os.path.exists(d):
shutil.rmtree(d)
shutil.copytree(s, d)
else:
shutil.copy2(s, d)
# Nettoyer
os.remove(tmp)
shutil.rmtree(tmp_dir)
return True, "Mise a jour reussie depuis l'archive."
except Exception as e:
return False, str(e)
def _find_git():
"""Trouver l'executable git."""
# Git systeme
try:
result = subprocess.run(["git", "--version"], capture_output=True, timeout=5)
if result.returncode == 0:
return "git"
except Exception:
pass
# Git portable (installeur)
app_dir = get_app_dir()
portable = os.path.join(app_dir, "..", "git", "cmd", "git.exe")
if os.path.exists(portable):
return portable
return None