From 102b485794d99788e9915a795001564022e72d73 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 8 May 2026 08:35:50 +0200 Subject: [PATCH] add: Versionierung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - semantic versioning - auto update on build - git hash zusätzlich - Anzeige per cli und im Fenster --- build.bat | 12 +++++-- config.json | 14 ++++++-- generate.py | 9 ++++- gui.py | 6 +++- schema.json | 6 ++++ update_version.py | 90 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 update_version.py diff --git a/build.bat b/build.bat index da558ff..ff8c7de 100644 --- a/build.bat +++ b/build.bat @@ -14,7 +14,7 @@ echo. echo === AnwesenheitPDF Build === echo. -echo [1/2] Abhaengigkeiten installieren... +echo [1/3] Abhaengigkeiten installieren... pip install -r requirements.txt --quiet && pip install -r requirements-dev.txt --quiet if %ERRORLEVEL% neq 0 ( echo [FEHLER] pip install fehlgeschlagen. @@ -22,7 +22,15 @@ if %ERRORLEVEL% neq 0 ( exit /b 1 ) -echo [2/2] Build starten... +echo [2/3] Version aktualisieren... +python update_version.py +if %ERRORLEVEL% neq 0 ( + echo [FEHLER] Version-Update fehlgeschlagen. + pause + exit /b 1 +) + +echo [3/3] Build starten... echo. python -m PyInstaller ^ diff --git a/config.json b/config.json index 5e75d2e..17af3bd 100644 --- a/config.json +++ b/config.json @@ -1,4 +1,5 @@ { + "version": "1.0.1+250a473", "antragsnummer": "100740439", "ort": "Dresden", "template_pdf": "template/sab.pdf", @@ -24,7 +25,16 @@ "Nov": "11", "Dez": "12" }, - "valid_status_codes": ["K", "KK", "E", "F", "P", "U", "A", "V"], + "valid_status_codes": [ + "K", + "KK", + "E", + "F", + "P", + "U", + "A", + "V" + ], "plan_hours_value": "6", "pdf_field_ort": "unterschrift.ort", "pdf_field_erstellungsdatum": "unterschrift.datum", @@ -33,4 +43,4 @@ "pdf_use_display_values": true, "pdf_need_appearances": false, "excel_network_source": "J:\\Fachbereiche\\BO\\Produktionsschule\\Maßnahmeunterlagen\\30_Teilnehmende\\01_Anwesenheit\\Anwesenheitsliste\\Anwesenheitsliste 2026.xlsx" -} +} \ No newline at end of file diff --git a/generate.py b/generate.py index a4cc3fb..b730a6e 100644 --- a/generate.py +++ b/generate.py @@ -23,8 +23,15 @@ from src.validators import show_preview_and_confirm, validate @click.group() -def cli() -> None: +@click.pass_context +def cli(ctx: click.Context) -> None: """Anwesenheit PDF Generator — Excel → PDF""" + try: + config = load_config() + version = config.get("version", "unknown") + click.echo(f"Anwesenheit PDF Generator v{version}") + except Exception as exc: + click.echo(f"Fehler beim Laden der Konfiguration: {exc}", err=True) @cli.command("validate") diff --git a/gui.py b/gui.py index c50f83c..59daf4f 100644 --- a/gui.py +++ b/gui.py @@ -156,7 +156,11 @@ class AnwesenheitApp(ctk.CTk): def __init__(self) -> None: super().__init__() - self.title("Anwesenheit PDF Generator") + # Load config and version + config = load_config() + version = config.get("version", "unknown") + + self.title(f"Anwesenheit PDF Generator v{version}") self.geometry("720x680") self.resizable(False, False) diff --git a/schema.json b/schema.json index 879398a..5e6b3a4 100644 --- a/schema.json +++ b/schema.json @@ -4,6 +4,7 @@ "description": "Konfigurationsschema für config.json", "type": "object", "required": [ + "version", "antragsnummer", "ort", "template_pdf", @@ -20,6 +21,11 @@ "pauschale_value" ], "properties": { + "version": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$", + "description": "Semantic version (z. B. 1.0.0)" + }, "antragsnummer": { "type": "string", "description": "SAB-Antragsnummer (statisch, aus config)" diff --git a/update_version.py b/update_version.py new file mode 100644 index 0000000..60a776a --- /dev/null +++ b/update_version.py @@ -0,0 +1,90 @@ +"""Update version in config.json with Git commit hash.""" + +import json +import re +import subprocess +import sys +from pathlib import Path + + +def get_git_commit_hash() -> str: + """Get the short Git commit hash. Return 'unknown' if Git not available.""" + try: + result = subprocess.run( + ["git", "rev-parse", "--short", "HEAD"], + capture_output=True, + text=True, + cwd=Path(__file__).parent, + ) + if result.returncode == 0: + return result.stdout.strip() + return "unknown" + except Exception: + return "unknown" + + +def parse_version(version_str: str) -> tuple[int, int, int]: + """Parse semantic version and return (major, minor, patch).""" + # Remove any build metadata (e.g., "+abc123") + base_version = version_str.split("+")[0].strip() + + match = re.match(r"^(\d+)\.(\d+)\.(\d+)$", base_version) + if not match: + raise ValueError(f"Invalid semantic version format: {base_version}") + + return int(match.group(1)), int(match.group(2)), int(match.group(3)) + + +def increment_patch_version(version_str: str) -> str: + """Increment patch version (e.g., 1.0.0 → 1.0.1).""" + major, minor, patch = parse_version(version_str) + return f"{major}.{minor}.{patch + 1}" + + +def update_version() -> None: + """Update config.json version with incremented patch and Git hash.""" + config_path = Path(__file__).parent / "config.json" + + if not config_path.exists(): + print(f"[ERROR] config.json not found at {config_path}") + sys.exit(1) + + # Load config + try: + with open(config_path, "r", encoding="utf-8") as f: + config = json.load(f) + except Exception as exc: + print(f"[ERROR] Failed to read config.json: {exc}") + sys.exit(1) + + # Get current version + current_version = config.get("version", "1.0.0") + print(f"Current version: {current_version}") + + # Increment patch version + new_base_version = increment_patch_version(current_version) + print(f"New version (base): {new_base_version}") + + # Get Git commit hash + git_hash = get_git_commit_hash() + print(f"Git commit hash: {git_hash}") + + # Combine version with Git hash (Semantic Versioning build metadata) + new_version = f"{new_base_version}+{git_hash}" + print(f"Final version: {new_version}") + + # Update config + config["version"] = new_version + + # Write back to config.json + try: + with open(config_path, "w", encoding="utf-8") as f: + json.dump(config, f, indent=4, ensure_ascii=False) + print(f"\n✓ Version updated in config.json") + except Exception as exc: + print(f"[ERROR] Failed to write config.json: {exc}") + sys.exit(1) + + +if __name__ == "__main__": + update_version()