Release-Anhaenge: der Name entscheidet - und ein Pruefstand dafuer
Der Fehler Das Release war angelegt, die EXE hing dran - und der Updater haette trotzdem nie etwas gefunden. Der Anhang trug die Nummer im Namen, gesucht wird aber "Steuerrechnungstool.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. Zweiter Fund: 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, pruef_release.py prueft gegen das echte Repository nach. Beide Dateien sind in beiden Programmen gleich. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
This commit is contained in:
parent
96aa51ac22
commit
e4619259cb
3 changed files with 126 additions and 7 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -19,3 +19,4 @@ setup/
|
|||
# die EXE nachbauen, die der Updater ausliefert.
|
||||
!Steuerrechnungstool.spec
|
||||
!Updater.spec
|
||||
release/
|
||||
|
|
|
|||
33
bauen.py
33
bauen.py
|
|
@ -79,7 +79,7 @@ def main():
|
|||
# Bauordner uebernimmt sonst Reste, die es in der Quelle nicht mehr gibt -
|
||||
# und in setup/ laege noch die Datei der VORIGEN Nummer herum. Beim
|
||||
# Ausliefern greift man dann leicht zur falschen.
|
||||
for ordner in ("build", "dist", "setup"):
|
||||
for ordner in ("build", "dist", "setup", "release"):
|
||||
shutil.rmtree(os.path.join(HIER, ordner), ignore_errors=True)
|
||||
|
||||
lauf([sys.executable, "-m", "PyInstaller", "--noconfirm", f"{stamm}.spec"],
|
||||
|
|
@ -94,14 +94,33 @@ def main():
|
|||
lauf([iscc(), f"/DVersion={version.VERSION}", f"/DExeProgramm={mit_nummer}",
|
||||
"Installer.iss"], "Setup")
|
||||
|
||||
# ---- release/ : genau das, was ins Release gehoert ---------------------
|
||||
# Der Anhang, den der Updater sucht, heisst OHNE Nummer - so steht es in
|
||||
# version.EXE_NAME, und danach sucht passendes_release(). Haengt man ihn
|
||||
# mit Nummer an, findet der Updater nie ein Update und meldet stumm
|
||||
# "aktuell". Die Nummer kommt erst beim Ablegen dazu (updater.dateiname).
|
||||
#
|
||||
# Daneben die Pruefsumme als eigene Datei: ohne sie prueft der Updater nur
|
||||
# die GROESSE. Eine Datei, die unterwegs verfaelscht wurde, hat aber genau
|
||||
# die richtige Groesse.
|
||||
freigabe = os.path.join(HIER, "release")
|
||||
os.makedirs(freigabe, exist_ok=True)
|
||||
shutil.copy2(ziel, os.path.join(freigabe, version.EXE_NAME))
|
||||
with open(os.path.join(freigabe, version.EXE_NAME + ".sha256"),
|
||||
"w", encoding="ascii") as f:
|
||||
f.write(summe(ziel) + chr(10))
|
||||
shutil.copy2(os.path.join(HIER, "dist", "Updater.exe"),
|
||||
os.path.join(freigabe, "Updater.exe"))
|
||||
for name in os.listdir(os.path.join(HIER, "setup")):
|
||||
shutil.copy2(os.path.join(HIER, "setup", name),
|
||||
os.path.join(freigabe, name))
|
||||
|
||||
print()
|
||||
print(f"FERTIG | {stamm} {version.VERSION}")
|
||||
for name in sorted(os.listdir(os.path.join(HIER, "dist"))):
|
||||
p = os.path.join(HIER, "dist", name)
|
||||
print(f" {name:44s} {os.path.getsize(p):>10,d} B {summe(p)}")
|
||||
setup = os.path.join(HIER, "setup")
|
||||
for name in sorted(os.listdir(setup)) if os.path.isdir(setup) else []:
|
||||
p = os.path.join(setup, name)
|
||||
print()
|
||||
print(" release/ - genau diese Dateien gehoeren ans Release:")
|
||||
for name in sorted(os.listdir(freigabe)):
|
||||
p = os.path.join(freigabe, name)
|
||||
print(f" {name:44s} {os.path.getsize(p):>10,d} B {summe(p)}")
|
||||
|
||||
|
||||
|
|
|
|||
99
pruef_release.py
Normal file
99
pruef_release.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# -*- 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")
|
||||
Loading…
Add table
Add a link
Reference in a new issue