86c4b9a0d8
gates / gates (push) Successful in 27s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
65 lines
2.9 KiB
Python
65 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Part A, first half — on controller v0.267.0 (the field's version): vikunja installed, seeded (A),
|
|
backed up by the product (the update's own `backing-up` leg, then a pull that fails: nothing moves),
|
|
RESTORED from its own unit — which recreates its volumes WITHOUT compose labels (R-658) — and seeded
|
|
again (B, after the restore). Evidence only; every act is a product endpoint."""
|
|
import json, re, sys, time
|
|
sys.path.insert(0, ".")
|
|
import walk as w
|
|
import fixtures as fx
|
|
|
|
ST = "../partA/state.json"
|
|
F = fx.Vikunja()
|
|
SUB = "vikunja-la"
|
|
out = {"controller": w.guest("cat /etc/felhom-controller-image").strip()}
|
|
w.login()
|
|
|
|
|
|
def drill_set(ref, msg):
|
|
import fcntl
|
|
with open(f"{w.SC}/drill.lock", "w") as lk:
|
|
fcntl.flock(lk, fcntl.LOCK_EX)
|
|
w.sh(["git", "-C", w.DRILL, "pull", "-q", "--rebase", "origin", "main"], timeout=120)
|
|
p = f"{w.DRILL}/templates/vikunja/docker-compose.yml"
|
|
s = open(p).read()
|
|
s = re.sub(r"image: vikunja/vikunja:\S+", f"image: vikunja/vikunja:{ref}", s)
|
|
open(p, "w").write(s)
|
|
w.sh(["git", "-C", w.DRILL, "commit", "-qam", f"LIVE-A vikunja {ref}: {msg}"])
|
|
r = w.sh(["git", "-C", w.DRILL, "push", "-q", "origin", "main"], timeout=120)
|
|
h = w.sh(["git", "-C", w.DRILL, "rev-parse", "--short=12", "HEAD"]).stdout.strip()
|
|
w.say(f"drill {h}: vikunja {ref} ({msg}) push rc={r.returncode}")
|
|
return h
|
|
|
|
|
|
def labels():
|
|
return w.guest("for v in $(docker volume ls -q | grep '^vikunja_'); do echo \"$v $(docker volume inspect $v --format '{{json .Labels}}')\"; done")
|
|
|
|
|
|
out["drill_A"] = drill_set("2.5.0", "the install version")
|
|
w.sync_rescan()
|
|
out["deployed"] = w.deploy("vikunja", SUB)
|
|
w.wait_app(SUB, "/", tries=60, delay=3)
|
|
A = F.seed(w, SUB, w.say)
|
|
out["seed_A"] = bool(A)
|
|
out["labels_after_install"] = labels()
|
|
w.say("labels after install:\n" + out["labels_after_install"])
|
|
|
|
out["drill_E"] = drill_set("2.5.99-notag", "a tag that does not exist: backing-up runs, the pull fails, nothing moves")
|
|
out["badge_wait"] = w.sync_rescan("vikunja", "vikunja/vikunja:2.5.99-notag")
|
|
out["press_backup"] = w.press_update("vikunja")
|
|
out["snapshots"] = w.snapshots("vikunja")
|
|
w.say("snapshots offered: " + json.dumps(out["snapshots"])[:400])
|
|
out["drill_back"] = drill_set("2.5.0", "back to the install version")
|
|
w.sync_rescan()
|
|
|
|
out["restore"] = w.restore("vikunja")
|
|
out["labels_after_restore_v0267"] = labels()
|
|
w.say("labels after the v0.267.0 restore:\n" + out["labels_after_restore_v0267"])
|
|
w.wait_app(SUB, "/", tries=60, delay=3)
|
|
out["A_after_restore"] = bool(F.verify(w, SUB, A, w.say))
|
|
B = F.seed(w, SUB, w.say)
|
|
out["seed_B_after_restore"] = bool(B)
|
|
json.dump({"A": A, "B": B, "sub": SUB}, open(ST, "w"))
|
|
json.dump(out, open("../partA/01-v0267-install-backup-restore.json", "w"), indent=2, ensure_ascii=False, default=str)
|
|
open("../partA/01-v0267-install-backup-restore.log", "w").write("\n".join(w.LOG) + "\n")
|