a975cfde5b
gates / gates (push) Successful in 28s
Part 1: tandoor/zipline/wger probes corrected in the catalog and red-proofed live on 9202 in both directions - "Nem egeszseges" with the front door serving 200, then "Fut" after the real sync with no redeploy. tandoor's failed edge re-walked: done at +41.1s where it was failed at +361.9s. Part 2: fifteen proven versions on the live catalog, one commit per app; the guarded Update pressed on four apps on demo-hp, all four done. Opened: R-630 (paperless-ngx's probe has never run on any box - a silent absence, worse than the wrong probe that was found in one night), R-631 (five templates no static rule can judge), R-632 (28 of 53 templates never deployed by any drill). Closed: R-618. Register 318 -> 321. No product code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
66 lines
3.3 KiB
Python
66 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Red-proof for R-618, live on 9202 through the product.
|
|
|
|
The claim: three templates name a health probe the app does not answer. The proof must show BOTH
|
|
halves at the same moment, or it shows nothing:
|
|
(a) the PRODUCT says the app is unhealthy — the controller's state, and the app page's badge;
|
|
(b) the APP is fine — its own front door answers 200, and docker's healthcheck reads healthy.
|
|
A reading of (a) alone is equally consistent with "the app really is broken", which is exactly the
|
|
mistake this whole exercise exists to stop making.
|
|
"""
|
|
import json, re, sys, time
|
|
sys.path.insert(0, '.')
|
|
import walk as w
|
|
|
|
OUT = "../probe-fix-2026-09-22"
|
|
APPS = [("tandoor", "tandoor", "/accounts/login/"),
|
|
("zipline", "zipline", "/"),
|
|
("wger", "wger", "/")]
|
|
|
|
|
|
def observe(name, sub, path, tag):
|
|
st = w.stack(name)
|
|
ac = st.get("app_config") or {}
|
|
rc, code, body = w.app_curl(sub, path)
|
|
dk = w.guest(f"docker inspect --format '{{{{.State.Health.Status}}}}' "
|
|
f"$(docker ps -q --filter name={name}) 2>&1 | head -3").strip()
|
|
bg = w.badges(name)
|
|
# The health word the HOUSEHOLD reads, in both languages — the version badge is a different
|
|
# element and quoting it instead would prove nothing about health (it says "Naprakesz" either
|
|
# way). Taken from the rendered page, scripts and styles stripped first: a `<script>` block on
|
|
# this page contains the same words and an unstripped scan picks them up (measured 2026-09-21).
|
|
health = {}
|
|
for lang, suffix in (("hu", ""), ("en", "?lang=en")):
|
|
h = w.page(f"/apps/{name}{suffix}")
|
|
h = re.sub(r"<script.*?</script>|<style.*?</style>", "", h, flags=re.S)
|
|
txt = re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", h))
|
|
m = re.search(r"\u2190 Alkalmaz\u00e1sok .{0,80}?\s(Nem eg\u00e9szs\u00e9ges|Eg\u00e9szs\u00e9ges|Fut|Le\u00e1ll\u00edtva|Indul|Hib\u00e1s)\s", txt) or \
|
|
re.search(r"\u2190 (?:Apps|Alkalmaz\u00e1sok) .{0,80}?\s(Not healthy|Healthy|Running|Stopped|Starting|Failed)\s", txt)
|
|
health[lang] = m.group(1) if m else None
|
|
health[lang + "_context"] = txt[txt.find("\u2190"):txt.find("\u2190") + 220] if "\u2190" in txt else None
|
|
rec = {"when": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "tag": tag, "app": name,
|
|
"controller_state": st.get("state"), "deployed": st.get("deployed"),
|
|
"pinned_images": ac.get("pinned_images"), "installed_images": ac.get("installed_images"),
|
|
"front_door_rc": rc, "front_door_code": code, "front_door_bytes": len(body),
|
|
"docker_health": dk, "version_badge": bg, "health_word": health}
|
|
print(json.dumps(rec, ensure_ascii=False, indent=2))
|
|
return rec
|
|
|
|
|
|
if __name__ == "__main__":
|
|
w.login()
|
|
tag = sys.argv[1] if len(sys.argv) > 1 else "before"
|
|
only = sys.argv[2:] or [a[0] for a in APPS]
|
|
recs = []
|
|
for name, sub, path in APPS:
|
|
if name not in only:
|
|
continue
|
|
print(f"\n=== {name} ({tag})")
|
|
if tag == "before":
|
|
ok = w.deploy(name, sub)
|
|
print(f" deploy ok={ok}")
|
|
w.wait_app(sub, path)
|
|
recs.append(observe(name, sub, path, tag))
|
|
open(f"{OUT}/probe-{tag}.json", "w").write(json.dumps(recs, ensure_ascii=False, indent=2))
|
|
print(f"\nwritten {OUT}/probe-{tag}.json")
|