Files
felhom.eu/documentation/audits/version-travel-2026-09-26/tools/a5live.py
T

57 lines
3.0 KiB
Python

"""a5live.py <step> — Part A's live proof on 9202 (0.275.0-rc1, drill catalog), through the buttons' endpoints.
Output lands in A5-live/ (a1.py's helpers with A1OUT=A5-live)."""
import os, sys, json, time, subprocess
os.environ["A1OUT"] = "A5-live"
import walk as w, a1
D = "/mnt/5_hdd/felhom.eu/drill/app-catalog-drill"
LIVE = "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu"
def drill(msg, compose_from_rev=None, revert=False):
subprocess.run(["git", "-C", D, "pull", "-q", "--rebase", "origin", "main"], check=True)
if revert:
subprocess.run(["git", "-C", D, "revert", "--no-edit", "HEAD"], check=True, capture_output=True)
else:
body = subprocess.run(["git", "-C", LIVE, "show", compose_from_rev + ":templates/docmost/docker-compose.yml"], check=True, capture_output=True, text=True).stdout
open(D + "/templates/docmost/docker-compose.yml", "w").write(body)
subprocess.run(["git", "-C", D, "commit", "-q", "-am", msg], check=True)
subprocess.run(["git", "-C", D, "push", "-q", "origin", "main"], check=True, capture_output=True)
print("drill:", subprocess.run(["git", "-C", D, "log", "--oneline", "-1"], capture_output=True, text=True).stdout.strip())
def wait_refresh(expect, label, cap=600):
t0 = time.time()
while time.time() - t0 < cap:
out = w.guest("grep -A3 '\"image_pins\"' /mnt/sys_drive/felhom-data/backups/primary/docmost/manifest.json | head -4; date -u +%T")
if expect in out:
print(f"{label}: manifest image_pins now carry {expect} at {out.split()[-1]}")
return True
time.sleep(20)
print(f"{label}: no refresh with {expect} within {cap}s"); return False
def press(label):
r = w.press_update("docmost", poll=1)
json.dump(r, open(f"{w.EV}/A5-live/{label}.json", "w"), indent=1, default=str)
print(label, {k: v for k, v in r.items() if k != "phases"})
return r
if __name__ == "__main__":
w.login()
step = sys.argv[1]
if step == "deploy095":
drill("LIVE A5: docmost deployable at 0.95.0 / postgres 16 (reverted after the deploy)", "a2115b2")
w.sync_rescan("docmost", "docmost/docmost:0.95.0")
print(w.deploy("docmost", "c-docs"))
a1.seed("L1-deployed"); a1.read("L1-deployed")
drill(None, revert=True)
w.sync_rescan("docmost", "postgres:18-alpine")
a1.unit("L1-deployed")
elif step == "press":
w.sync_rescan("docmost", "postgres:18-alpine")
press(sys.argv[2]); a1.unit(sys.argv[2])
elif step == "refresh":
wait_refresh(sys.argv[3], sys.argv[2]); a1.unit(sys.argv[2])
elif step == "restore":
a1.restore(sys.argv[2], tier2=len(sys.argv) > 3); a1.read(sys.argv[2]); a1.unit(sys.argv[2])
code, d = w.ctl("GET", "/api/backup/restore-status")
open(f"{w.EV}/A5-live/{sys.argv[2]}.txt", "a").write("restore-status (the page's sentence): " + json.dumps(d.get("data"), ensure_ascii=False) + "\n")
print(json.dumps((d.get("data") or {}).get("last"), ensure_ascii=False))