build: alle Template-PDFs automatisch in Build und Release aufnehmen

Alle *.pdf im template-Ordner werden ausgeliefert; Dateien mit '_' oder '.'
am Anfang sowie andere Dateitypen werden ignoriert. Veraltete PDFs im
Build-Ordner werden entfernt. Tests entsprechend angepasst.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
RobandClaude Sonnet 5.5 committed 2026-11-03 11:53:55 +01:00
1 parent 2237779e56
commit 7de6984ebc
4 files changed
+42 -12

No files matched your search

+12 -5
View File
@@ -21,7 +21,7 @@ from datetime import date
from pathlib import Path
from typing import Optional
from deploy import deploy, write_release_manifest
from deploy import deploy, is_template_pdf, write_release_manifest
# ── Pfade ───────────────────────────────────────────────────────
BUILD_PIPELINE_DIR = Path(__file__).resolve().parent
@@ -223,10 +223,17 @@ def _prepare_build_dir() -> None:
shutil.copy2(f, config_dst / f.name)
shutil.copy2(CHANGELOG_PATH, BUILD_OUTPUT_DIR / "CHANGELOG.md")
shutil.copy2(
APP_DIR / "template" / "Tätigkeitsnachweise Stellenförderung.pdf",
BUILD_OUTPUT_DIR / "template" / "Tätigkeitsnachweise Stellenförderung.pdf",
)
# Alle Template-PDFs ausliefern (ohne Dateien mit '_' oder '.' am Anfang).
# Veraltete PDFs aus früheren Builds werden entfernt.
tpl_src = APP_DIR / "template"
tpl_dst = BUILD_OUTPUT_DIR / "template"
wanted = {p.name for p in tpl_src.iterdir() if is_template_pdf(p)}
for old_pdf in tpl_dst.iterdir():
if is_template_pdf(old_pdf) and old_pdf.name not in wanted:
old_pdf.unlink()
for name in sorted(wanted):
shutil.copy2(tpl_src / name, tpl_dst / name)
# README für input-Ordner
input_readme = BUILD_OUTPUT_DIR / "input" / "_DATEIEN_HIER_ABLEGEN_.txt"
+21 -4
View File
@@ -18,10 +18,27 @@ MANIFEST_NAME = "release.json"
PACKAGE_FILES = [
EXE_NAME, "README.md", "CHANGELOG.md",
"config/settings.ini", "config/input-fields.json", "config/output-fields.json",
"template/Tätigkeitsnachweise Stellenförderung.pdf",
]
def is_template_pdf(path: Path) -> bool:
"""Nur *.pdf, die nicht mit '_' oder '.' beginnen, gelten als Template."""
return path.is_file() and path.suffix.lower() == ".pdf" and not path.name.startswith(("_", "."))
def template_files(base_dir: Path) -> list[str]:
"""Relative Pfade aller Template-PDFs in base_dir/template (sortiert)."""
folder = base_dir / "template"
if not folder.is_dir():
return []
return [f"template/{p.name}" for p in sorted(folder.iterdir()) if is_template_pdf(p)]
def package_files(build_dir: Path) -> list[str]:
"""Alle Dateien des Release-Pakets: feste Dateien plus alle Template-PDFs."""
return PACKAGE_FILES + template_files(build_dir)
def normalize_version(version: str) -> str:
if not re.fullmatch(r"\d+\.\d+(?:\.\d+)?", version):
raise ValueError(f"Ungültige Versionsnummer: {version}")
@@ -40,7 +57,7 @@ def write_release_manifest(build_dir: Path, version: str) -> None:
"""Record the version and all payload hashes after a successful build."""
manifest = {
"version": normalize_version(version),
"files": {name: file_hash(build_dir / name) for name in PACKAGE_FILES},
"files": {name: file_hash(build_dir / name) for name in package_files(build_dir)},
}
(build_dir / MANIFEST_NAME).write_text(
json.dumps(manifest, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
@@ -51,7 +68,7 @@ def validate_release(build_dir: Path) -> str:
raise ValueError("Kein bestätigter Build vorhanden. Bitte zuerst build.bat ausführen.")
manifest = json.loads((build_dir / MANIFEST_NAME).read_text(encoding="utf-8"))
version = normalize_version(manifest["version"])
for name in PACKAGE_FILES:
for name in package_files(build_dir):
path = build_dir / name
if not path.is_file() or file_hash(path) != manifest.get("files", {}).get(name):
raise ValueError(f"Build-Datei fehlt oder wurde nach dem Build verändert: {name}. Bitte neu bauen.")
@@ -83,7 +100,7 @@ def deploy(build_dir: Path = BUILD_DIR, target_dir: Path = DEPLOY_DIR) -> Path:
temporary = Path(temporary)
try:
with zipfile.ZipFile(temporary, "w", zipfile.ZIP_DEFLATED) as package:
for name in PACKAGE_FILES:
for name in package_files(build_dir):
package.write(build_dir / name, name)
for directory in ["input/", "output/"]:
# Fixed timestamps keep repeated deployments byte-identical.