Files
felhom.eu/documentation/audits/night-2026-09-23/press9201.py
T
admin 3e58c184f6
gates / gates (push) Successful in 27s
night shift 2026-09-23: the record, the register, the morning note
DRILL-night-2026-09-23.md: Parts A-E. 09 §3 decisions 21 (operator word),
22 and 23 (CC unattended, operator may reverse); §6.4 parts 4 and 6
(catalog half) shipped; §6.1a residuals R-658/R-659. Register 330 -> 336:
R-651..R-660 opened (R-658 and R-659 P1), R-650/R-640/R-499/R-626 closed.
Capability map, nightly rotation (opengist), STATUS (one question: the
floor), CONTEXT, REPORT. The floor stays 0.266.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-24 00:24:04 +02:00

60 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""press9201.py — Part D's second half: on demo-hp guest 9201 (the HP demo box, LIVE catalog, a hub),
press the guarded Update of each STANDING app that Part C moved tonight, one at a time.
GUEST=9201 python3 press9201.py <app> [<app> ...]
Per app: the badge and the app page in BOTH languages before; the guarded Update and every phase with
its time; the four version observables after; the app's front door after; the page in both languages
after. Nothing is seeded (these are the demo box's own standing apps) and nothing is fixed: a failure
here is the undo's first real outing on a standing app — recorded, not repaired.
No whole-box backup is pressed (R-648): the update's own `backing-up` phase backs up the one app.
"""
import json, os, sys, time
os.environ.setdefault("GUEST", "9201")
sys.path.insert(0, ".")
import walk as w
import live
FRONT = {"romm": ("arcade", "/api/heartbeat"), "opengist": ("gist", "/healthcheck"),
"kimai": ("kimai", "/en/login")}
EV = os.path.join(os.path.dirname(os.path.abspath(__file__)), "press9201")
os.makedirs(EV, exist_ok=True)
def sub_for(app):
ac = (w.stack(app).get("app_config") or {})
env = ac.get("env") or {}
return env.get("SUBDOMAIN") or FRONT[app][0]
def main(apps):
assert w.GUEST == "9201", "this script presses on 9201 only"
w.login()
w.say("sync + rescan so the box sees tonight's live catalog")
w.sync_rescan()
for app in apps:
w.LOG.clear()
rec = {"app": app}
sub = sub_for(app)
w.say(f"==== 9201 {app} (sub {sub})")
rec["before"] = {"observables": w.observables(app), "badges": w.badges(app), "lines": live.page_lines(app)}
want = list((rec["before"]["observables"].get("catalog_images") or {}).values())
w.say(f" catalog now offers {want}; pinned {rec['before']['observables'].get('pinned_images')}")
res = w.press_update(app)
rec["press"] = res
rec["after"] = {"observables": w.observables(app), "badges": w.badges(app), "lines": live.page_lines(app)}
path = FRONT.get(app, (sub, "/"))[1]
rc, code, _ = w.app_curl(sub, path, timeout=30)
rec["front_door"] = {"path": path, "rc": rc, "http": code}
w.say(f" END phase={res.get('final_phase')} hold={res.get('hold_reason')!r} front door {path} -> {code}")
w.say(f" pinned after: {rec['after']['observables'].get('pinned_images')}")
w.say(f" inspect after: {rec['after']['observables'].get('docker_inspect')}")
w.say(f" page hu/en after: {json.dumps(rec['after']['badges'], ensure_ascii=False)[:300]}")
json.dump(rec, open(os.path.join(EV, f"{app}.json"), "w"), indent=2, ensure_ascii=False)
open(os.path.join(EV, f"{app}.log"), "w").write("\n".join(w.LOG) + "\n")
if __name__ == "__main__":
main(sys.argv[1:])