8db4425d98
gates / gates (push) Successful in 2m38s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
141 lines
6.9 KiB
Python
141 lines
6.9 KiB
Python
"""wgerstep.py <new-definition-dir> — R-762 on scratch 9202 (drill catalog), ONE process, through the product.
|
|
|
|
1 DRILL: wger un-hidden (DRILL only); install fresh at the live definition; seed (the fixture) + read back (C1);
|
|
2 a progress photo posted to the gallery (the household's API with its session); its /media URL read: 404 expected
|
|
(the R-762 fault — the control that the later 200 is the fix, not the test);
|
|
3 the login page's own CSS links read: 404 expected;
|
|
4 a DRILL commit replaces the compose with the new definition + one ladder entry; sync; the product's guarded Update;
|
|
5 after: the seed, the same photo URL (200 + the same byte count), the CSS links (200), wger-files' memory;
|
|
6 box verdict JSON; removed through the product (KEEP=1 keeps it).
|
|
Evidence: ../F/box/step.txt + box-verdict-wger.json."""
|
|
import json, os, re, struct, subprocess, sys, tempfile, time, zlib
|
|
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
|
import box_walk as w
|
|
import upgrade_fixtures_box as fixtures
|
|
|
|
APP, SUB = "wger", "fitness"
|
|
NEWDEF = sys.argv[1]
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
EVD = os.path.join(HERE, "..", "F", "box"); os.makedirs(EVD, exist_ok=True)
|
|
log = open(f"{EVD}/step.txt", "a", buffering=1)
|
|
D = "/mnt/5_hdd/felhom.eu/drill/app-catalog-drill"
|
|
REC = {"app": APP}
|
|
|
|
|
|
def say(*a):
|
|
w.say(*a); log.write(" ".join(map(str, a)) + "\n")
|
|
|
|
|
|
def git(*a):
|
|
return subprocess.run(["git", "-C", D, *a], check=True, capture_output=True, text=True).stdout
|
|
|
|
|
|
def png(path, n=64):
|
|
"""A real PNG (n x n, random-ish colour) — the gallery validates the image."""
|
|
import secrets
|
|
rgb = secrets.token_bytes(3)
|
|
raw = b"".join(b"\x00" + rgb * n for _ in range(n))
|
|
def chunk(t, d):
|
|
return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d) & 0xffffffff)
|
|
data = (b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", n, n, 8, 2, 0, 0, 0))
|
|
+ chunk(b"IDAT", zlib.compress(raw)) + chunk(b"IEND", b""))
|
|
open(path, "wb").write(data)
|
|
return len(data)
|
|
|
|
|
|
def css_links():
|
|
rc, code, page = w.app_curl(SUB, "/en/user/login")
|
|
links = re.findall(r'(/static/[^"]+\.css)', page or "")[:3]
|
|
return {l: w.app_curl(SUB, l)[1] for l in links}
|
|
|
|
|
|
fx = fixtures.FIXTURES[APP]
|
|
w.login()
|
|
if w.stack(APP).get("deployed"):
|
|
say("wger already installed — removing it first (scratch box)")
|
|
w.remove(APP)
|
|
git("pull", "-q", "--rebase", "origin", "main")
|
|
fy = f"{D}/templates/{APP}/.felhom.yml"
|
|
s = open(fy).read()
|
|
if "lifecycle: hidden" in s:
|
|
open(fy, "w").write(s.replace("lifecycle: hidden", "lifecycle: available", 1))
|
|
git("commit", "-q", "-am", "DRILL wger: un-hidden for the R-762 box step (DRILL only)")
|
|
git("push", "-q", "origin", "main")
|
|
say("drill:", git("log", "--oneline", "-1").strip())
|
|
w.sync_rescan()
|
|
time.sleep(5)
|
|
w.sync_rescan()
|
|
if not w.deploy(APP, SUB):
|
|
sys.exit(say("RESULT the install did not complete") or 1)
|
|
before = (w.stack(APP).get("app_config") or {}).get("pinned_images")
|
|
say(f"[1] installed, pinned={before}")
|
|
tok = fx.seed(w, SUB, say)
|
|
if tok is None or not fx.verify(w, SUB, tok, say):
|
|
sys.exit(say(f"RESULT C1 failed: {getattr(fx, 'tried', '')}") or 1)
|
|
|
|
jar = tempfile.mktemp(prefix="wger-jar-")
|
|
hdr, why = fx._login(w, SUB, tok["pw"], jar)
|
|
pic = tempfile.mktemp(prefix="wger-photo-", suffix=".png")
|
|
size = png(pic)
|
|
rc, code, out = w.app_curl(SUB, "/api/v2/gallery/", *hdr, "-F", f"image=@{pic};type=image/png", "-F", "date=2026-10-06",
|
|
"-F", "description=r762", method="POST")
|
|
say(f"[2] POST /api/v2/gallery/ (a {size} B PNG) -> {code}")
|
|
img = None
|
|
try:
|
|
img = json.loads(out).get("image")
|
|
except Exception:
|
|
say(f" body {out[:200]}")
|
|
path = re.sub(r"^https?://[^/]+", "", img or "")
|
|
REC["photo_path"], REC["photo_bytes"] = path, size
|
|
code_b = w.app_curl(SUB, path)[1] if path else None
|
|
REC["photo_before"] = code_b
|
|
REC["css_before"] = css_links()
|
|
say(f"[2] the photo {path} read BEFORE the step -> {code_b}; CSS before {REC['css_before']}")
|
|
|
|
git("pull", "-q", "--rebase", "origin", "main")
|
|
newc = open(os.path.join(NEWDEF, "docker-compose.yml")).read()
|
|
open(f"{D}/templates/{APP}/docker-compose.yml", "w").write(newc)
|
|
to = dict(re.findall(r"^ ([a-z0-9-]+):\s*\n(?:(?! [a-z0-9-]+:\s*\n).*\n)*?\s+image:\s*(\S+)", newc, re.M))
|
|
s = open(fy).read()
|
|
entry = {"from": before, "to": to, "verdict": "proven", "tested_at": "DRILL", "harness_version": 5,
|
|
"evidence": "DRILL (box proof in progress)", "marks": {"files_may_change": False, "needs_person": None, "memory_tight": False}}
|
|
s = s.rstrip("\n") + "\n - " + json.dumps(entry) + "\n"
|
|
s = re.sub(r'^ mem_limit: .*$', ' mem_limit: "416M"', s, count=1, flags=re.M)
|
|
open(fy, "w").write(s)
|
|
git("commit", "-q", "-am", f"DRILL wger: the R-762 definition (wger-files) + its ladder entry (box proof)")
|
|
git("push", "-q", "origin", "main")
|
|
say("drill:", git("log", "--oneline", "-1").strip(), "| to:", to)
|
|
w.sync_rescan(APP, to.get("wger-files"))
|
|
REC["badge_before"] = w.badges(APP)
|
|
since = w.guest("date -u +%Y-%m-%dT%H:%M:%SZ").strip()
|
|
res = w.press_update(APP, poll=1, cap_s=1800)
|
|
for p in res.get("phases", []):
|
|
log.write(f" phase +{p['t']}s {p['phase']} | err={p['error']}\n")
|
|
time.sleep(15)
|
|
read = fx.verify(w, SUB, tok, say)
|
|
code_a = w.app_curl(SUB, path)[1] if path else None
|
|
rc, _, body = w.app_curl(SUB, path, "-o", "/dev/null", "-w", "%{size_download}") if path else (1, None, "")
|
|
REC["photo_after"], REC["photo_after_bytes"] = code_a, body.strip()[-12:]
|
|
REC["css_after"] = css_links()
|
|
REC["memory"] = w.guest("docker stats --no-stream --format '{{.Name}} {{.MemUsage}}' | grep -i wger").strip().splitlines()
|
|
lines = w.guest(f"docker logs --since {since} felhom-controller 2>&1 | grep -E 'update {APP}' | grep -v DEBUG | cut -c1-400")
|
|
log.write(lines + "\n")
|
|
st = w.stack(APP); after = (st.get("app_config") or {}).get("pinned_images")
|
|
REC["badge_after"] = w.badges(APP)
|
|
say(f"[5] after: phase={res.get('final_phase')} pinned={after} seed={read} photo={code_a} ({REC['photo_after_bytes']}) "
|
|
f"css={REC['css_after']} mem={REC['memory']}")
|
|
ok = (res.get("final_phase") == "done" and read and after == to and code_a == "200"
|
|
and REC["css_after"] and all(c == "200" for c in REC["css_after"].values()))
|
|
verdict = {"app": APP, "venue": "box 9202 (drill catalog), the product's guarded Update (R-762 definition step)",
|
|
"from": before, "to": after, "verdict": "proven" if ok else "failed",
|
|
"seed_read_before": True, "seed_read_after": read, "healthy_after": st.get("state") == "running",
|
|
"duration_s": res.get("duration_s"), "final_phase": res.get("final_phase"), "measured_at": since,
|
|
"evidence": "felhom.eu/documentation/audits/design-build-2026-10-06/F/box/step.txt", "r762": REC}
|
|
json.dump(verdict, open(f"{EVD}/box-verdict-{APP}.json", "w"), indent=2)
|
|
say(f"RESULT {verdict['verdict']}")
|
|
for f in (jar, pic):
|
|
if os.path.exists(f):
|
|
os.unlink(f)
|
|
if not os.environ.get("KEEP"):
|
|
say(f"remove -> {w.remove(APP)}")
|