rechnungstool/pruef_release.py
TheMockTv 8a391b8dfa Release-Anhaenge: der Name entscheidet - und ein Pruefstand dafuer
Der Fehler
  Das Release 1.7.0 war angelegt, die EXE hing dran - und der Updater haette
  trotzdem nie etwas gefunden. Der Anhang hiess "Rechnungstool-1.7.0.exe",
  gesucht wird aber "Rechnungstool.exe" (version.EXE_NAME). Die Nummer kommt
  erst beim Ablegen dazu.

  Das Tueckische: nichts schlaegt fehl. Der Updater meldet freundlich
  "Aktuell. Kein Update noetig." und startet die alte Fassung. Ein Update,
  das stumm nie ankommt, ist schlimmer als eines, das laut scheitert.

  Zweiter Fund derselben Runde: die Pruefsummen standen nur im Release-TEXT.
  Der Updater liest sie aus einer angehaengten Datei <exe>.sha256. Ohne die
  prueft er nur die Groesse - und eine verfaelschte Datei hat genau die
  richtige Groesse.

bauen.py legt jetzt release/ an
  Genau die vier Dateien, die ans Release gehoeren, unter genau den Namen,
  unter denen der Updater sie sucht. Damit haengt niemand mehr etwas
  Falsches an.

pruef_release.py
  Prueft gegen das echte Repository: gibt es zur Nummer aus version.py ein
  Release, heisst der Anhang exakt wie EXE_NAME, haengt die Pruefsumme dran,
  ist es die der zuletzt gebauten Datei - und findet passendes_release() es
  auch. Ohne Netz wird uebersprungen statt rot gemeldet.

muster/ ist raus
  Der Gast darin ist erfunden, der Betrieb nicht: IBAN, Steuernummer und die
  private Rufnummer des Auftraggebers stehen im Briefkopf. In ein
  oeffentliches Repository gehoert das nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
2026-09-06 20:43:15 +02:00

99 lines
4 KiB
Python

# -*- coding: utf-8 -*-
"""Pruefstand: passt das VEROEFFENTLICHTE Release zu dem, was der Updater sucht?
DER FALL, DER DAZU GEFUEHRT HAT (06.09.2026)
--------------------------------------------
Das Release war angelegt, die EXE hing dran - und der Updater haette trotzdem
nie etwas gefunden. Der Anhang hiess `Rechnungstool-1.7.0.exe`; gesucht wird
aber `Rechnungstool.exe` (so steht es in version.EXE_NAME, und danach sucht
passendes_release). Die Nummer kommt erst beim ABLEGEN dazu.
Das Tueckische daran: nichts schlaegt fehl. Der Updater meldet freundlich
"Aktuell. Kein Update noetig." und startet die alte Fassung. Ein Update, das
stumm nie ankommt, ist schlimmer als eines, das laut scheitert.
Zweiter Fund derselben Runde: die Pruefsummen standen nur im Release-TEXT. Der
Updater liest sie aus einer angehaengten Datei `<exe>.sha256`. Ohne die prueft
er nur die Groesse - und eine unterwegs verfaelschte Datei hat genau die
richtige Groesse.
WAS HIER GEPRUEFT WIRD
----------------------
Gegen das echte Repository, nicht gegen einen Nachbau:
1. Zu der Nummer in version.py gibt es ein Release.
2. Es haengt eine Datei mit EXAKT dem Namen aus version.EXE_NAME an.
3. Es haengt die Pruefsumme `<exe>.sha256` an.
4. Die Summe darin ist die der angehaengten Datei - und die stimmt mit dem
ueberein, was hier zuletzt gebaut wurde (release/<exe>).
5. passendes_release() findet dieses Release auch wirklich.
Ohne Netz wird uebersprungen statt rot gemeldet: ein fehlender Anschluss ist
kein Fehler des Programms.
"""
import os
import sys
HIER = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HIER)
import updater # noqa: E402
import version # noqa: E402
fehler = []
def pruefe(bedingung, text):
zeile = (" OK | " if bedingung else "FEHLER | ") + text
kod = sys.stdout.encoding or "utf-8"
print(zeile.encode(kod, "replace").decode(kod))
if not bedingung:
fehler.append(text)
try:
releases = updater.releases_holen(version.REPOSITORY)
except Exception as e: # noqa: BLE001 - ohne Netz ist hier nichts zu pruefen
print(f"UEBERSPRUNGEN | Repository nicht erreichbar ({e})")
sys.exit(0)
marke = "v" + version.VERSION
dieses = next((r for r in releases if (r.get("tag_name") or "") == marke), None)
pruefe(dieses is not None, f"zu Fassung {version.VERSION} gibt es ein Release ({marke})")
if dieses is None:
print("ROT | ohne Release ist der Rest nicht pruefbar")
sys.exit(1)
anhaenge = {a.get("name"): a for a in dieses.get("assets") or []}
print(f" (Anhaenge: {', '.join(sorted(anhaenge)) or 'keine'})")
pruefe(version.EXE_NAME in anhaenge,
f"der Anhang heisst genau {version.EXE_NAME} - danach sucht der Updater")
pruefe(version.EXE_NAME + ".sha256" in anhaenge,
f"die Pruefsumme haengt als {version.EXE_NAME}.sha256 dran")
# ---- Die Summe muss zur Datei passen, und zwar zu der gebauten ------------
gebaut = os.path.join(HIER, "release", version.EXE_NAME)
url_summe = updater.summe_aus_release(dieses, version.EXE_NAME)
if url_summe:
veroeffentlicht = updater.text_holen(url_summe).strip().split()[0]
if os.path.exists(gebaut):
pruefe(veroeffentlicht == updater.sha256(gebaut),
"die veroeffentlichte Summe ist die der zuletzt gebauten Datei")
else:
print(f" (release/{version.EXE_NAME} fehlt - Summe nicht "
f"gegenpruefbar, vorher: python bauen.py)")
pruefe(len(veroeffentlicht) == 64 and all(c in "0123456789abcdef" for c in veroeffentlicht),
f"und sie sieht aus wie eine SHA256 ({veroeffentlicht[:16]}...)")
# ---- Und findet der Updater das Release ueberhaupt? -----------------------
treffer = updater.passendes_release(releases, version.EXE_NAME)
pruefe(treffer is not None, "passendes_release findet ueberhaupt ein Release")
if treffer:
pruefe((treffer[0].get("tag_name") or "") == marke,
f"und zwar dieses hier ({treffer[0].get('tag_name')})")
if fehler:
print(f"ROT | {len(fehler)} Punkt(e) nicht erfuellt")
sys.exit(1)
print("GRUEN | Das Release ist so, wie der Updater es erwartet")