add: Versionierung
- semantic versioning - auto update on build - git hash zusätzlich - Anzeige per cli und im Fenster
This commit is contained in:
1 parent
250a473253
commit
102b485794
6 files changed
+130
-5
No files matched your search
@@ -14,7 +14,7 @@ echo.
|
|||||||
echo === AnwesenheitPDF Build ===
|
echo === AnwesenheitPDF Build ===
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
echo [1/2] Abhaengigkeiten installieren...
|
echo [1/3] Abhaengigkeiten installieren...
|
||||||
pip install -r requirements.txt --quiet && pip install -r requirements-dev.txt --quiet
|
pip install -r requirements.txt --quiet && pip install -r requirements-dev.txt --quiet
|
||||||
if %ERRORLEVEL% neq 0 (
|
if %ERRORLEVEL% neq 0 (
|
||||||
echo [FEHLER] pip install fehlgeschlagen.
|
echo [FEHLER] pip install fehlgeschlagen.
|
||||||
@@ -22,7 +22,15 @@ if %ERRORLEVEL% neq 0 (
|
|||||||
exit /b 1
|
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.
|
echo.
|
||||||
|
|
||||||
python -m PyInstaller ^
|
python -m PyInstaller ^
|
||||||
|
|||||||
+11
-1
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"version": "1.0.1+250a473",
|
||||||
"antragsnummer": "100740439",
|
"antragsnummer": "100740439",
|
||||||
"ort": "Dresden",
|
"ort": "Dresden",
|
||||||
"template_pdf": "template/sab.pdf",
|
"template_pdf": "template/sab.pdf",
|
||||||
@@ -24,7 +25,16 @@
|
|||||||
"Nov": "11",
|
"Nov": "11",
|
||||||
"Dez": "12"
|
"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",
|
"plan_hours_value": "6",
|
||||||
"pdf_field_ort": "unterschrift.ort",
|
"pdf_field_ort": "unterschrift.ort",
|
||||||
"pdf_field_erstellungsdatum": "unterschrift.datum",
|
"pdf_field_erstellungsdatum": "unterschrift.datum",
|
||||||
|
|||||||
+8
-1
@@ -23,8 +23,15 @@ from src.validators import show_preview_and_confirm, validate
|
|||||||
|
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
def cli() -> None:
|
@click.pass_context
|
||||||
|
def cli(ctx: click.Context) -> None:
|
||||||
"""Anwesenheit PDF Generator — Excel → PDF"""
|
"""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")
|
@cli.command("validate")
|
||||||
|
|||||||
@@ -156,7 +156,11 @@ class AnwesenheitApp(ctk.CTk):
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
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.geometry("720x680")
|
||||||
self.resizable(False, False)
|
self.resizable(False, False)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"description": "Konfigurationsschema für config.json",
|
"description": "Konfigurationsschema für config.json",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
"version",
|
||||||
"antragsnummer",
|
"antragsnummer",
|
||||||
"ort",
|
"ort",
|
||||||
"template_pdf",
|
"template_pdf",
|
||||||
@@ -20,6 +21,11 @@
|
|||||||
"pauschale_value"
|
"pauschale_value"
|
||||||
],
|
],
|
||||||
"properties": {
|
"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": {
|
"antragsnummer": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "SAB-Antragsnummer (statisch, aus config)"
|
"description": "SAB-Antragsnummer (statisch, aus config)"
|
||||||
|
|||||||
@@ -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()
|
||||||
Reference in new issue
Block a user