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.
|
# die EXE nachbauen, die der Updater ausliefert.
|
||||||
!Steuerrechnungstool.spec
|
!Steuerrechnungstool.spec
|
||||||
!Updater.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 -
|
# Bauordner uebernimmt sonst Reste, die es in der Quelle nicht mehr gibt -
|
||||||
# und in setup/ laege noch die Datei der VORIGEN Nummer herum. Beim
|
# und in setup/ laege noch die Datei der VORIGEN Nummer herum. Beim
|
||||||
# Ausliefern greift man dann leicht zur falschen.
|
# 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)
|
shutil.rmtree(os.path.join(HIER, ordner), ignore_errors=True)
|
||||||
|
|
||||||
lauf([sys.executable, "-m", "PyInstaller", "--noconfirm", f"{stamm}.spec"],
|
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}",
|
lauf([iscc(), f"/DVersion={version.VERSION}", f"/DExeProgramm={mit_nummer}",
|
||||||
"Installer.iss"], "Setup")
|
"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()
|
||||||
print(f"FERTIG | {stamm} {version.VERSION}")
|
print(f"FERTIG | {stamm} {version.VERSION}")
|
||||||
for name in sorted(os.listdir(os.path.join(HIER, "dist"))):
|
print()
|
||||||
p = os.path.join(HIER, "dist", name)
|
print(" release/ - genau diese Dateien gehoeren ans Release:")
|
||||||
print(f" {name:44s} {os.path.getsize(p):>10,d} B {summe(p)}")
|
for name in sorted(os.listdir(freigabe)):
|
||||||
setup = os.path.join(HIER, "setup")
|
p = os.path.join(freigabe, name)
|
||||||
for name in sorted(os.listdir(setup)) if os.path.isdir(setup) else []:
|
|
||||||
p = os.path.join(setup, name)
|
|
||||||
print(f" {name:44s} {os.path.getsize(p):>10,d} B {summe(p)}")
|
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