Fleet scripts find their helpers inside their own tree (the CI checks, the Discord hook, the publish script), env-overridable; the library's node patterns inline
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
c704c8263c
commit
ccfa6e6cb4
5 changed files with 6 additions and 6 deletions
|
|
@ -2,7 +2,7 @@
|
|||
# The fleet's deploy gate (coordinator, 6 October 2026 23:0xZ, after three comment-on-a-line faults): every script pushed to a box
|
||||
# passes master's defaults-line check and a syntax check first; lib/box.py's put() calls this for any .sh/.py source under
|
||||
# tools/fleet and refuses the push on red. Usage: deploy-gate.sh <file...> (exit 0 = clean)
|
||||
set -u; rc=0; HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"; MASTER_CI="${IGNEUM_MASTER_CI:-/Users/joshm/Projects/igneum/tools/ci}"
|
||||
set -u; rc=0; HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"; MASTER_CI="${IGNEUM_MASTER_CI:-$HERE/../ci}" # the same tree's CI checks (master's once merged)
|
||||
for f in "$@"; do
|
||||
case "$f" in
|
||||
*.sh) bash -n "$f" 2>&1 | head -2 | sed "s|^|$f: |" ; [ "${PIPESTATUS[0]}" = 0 ] || rc=1 ;;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import sys, os, json, time, subprocess
|
|||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))); from lib import Box, Registry
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
ROOT = os.path.expanduser("~/Desktop/fleet"); OUT = os.path.join(ROOT, "disk.json"); ALERTS = os.path.join(ROOT, "disk-alerts.json")
|
||||
HOOKS = "/Users/joshm/Projects/igneum/tools/community/discord-hooks.mjs"
|
||||
HOOKS = os.environ.get("IGNEUM_DISCORD_HOOKS", os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "community", "discord-hooks.mjs")) # this tree's hook script
|
||||
def now(): return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
||||
def one(item):
|
||||
iid, b = item
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class Box:
|
|||
return f"{F}/in/{name}"
|
||||
# ---- node ----
|
||||
def stop_node(self):
|
||||
self.run(f"pkill -f '{NODE_PATH_PATTERN}'; sleep 3; pkill -9 -f '{NODE_PATH_PATTERN}' 2>/dev/null; true", 40)
|
||||
self.run(f"pkill -f '[/]root/fleet/in/igneumd|[/]opt/igneum/pkg/bin/igneumd'; sleep 3; pkill -9 -f '[/]root/fleet/in/igneumd|[/]opt/igneum/pkg/bin/igneumd' 2>/dev/null; true", 40)
|
||||
def start_node(self, binary, override_local, peers, devnet_suffix=None, verifier=None, extra=(), appdir=None, log=None, unsynced_mining=False):
|
||||
"""Writes the override file, kills the old node (anchored on its path), starts the new one; returns the digest it prints."""
|
||||
appdir = appdir or (f"{F}/dn2" if devnet_suffix else f"{F}/node"); log = log or (f"{F}/dn2-node.log" if devnet_suffix else f"{F}/node.log")
|
||||
|
|
@ -118,7 +118,7 @@ class Box:
|
|||
b = self.rpc("eth_getBlockByNumber", [hex(height), False]) or {}
|
||||
return b.get("stateRoot")
|
||||
def node_version(self):
|
||||
return self.run(f"v=$(pgrep -fa '{NODE_PATH_PATTERN}' | head -1 | awk '{{print $2}}'); [ -n \"$v\" ] && echo \"$(sha256sum \"$v\" | cut -c1-16) $($v --version 2>&1 | head -1)\"", 30)[1].strip()
|
||||
return self.run(f"v=$(pgrep -fa '[/]root/fleet/in/igneumd|[/]opt/igneum/pkg/bin/igneumd' | head -1 | awk '{{print $2}}'); [ -n \"$v\" ] && echo \"$(sha256sum \"$v\" | cut -c1-16) $($v --version 2>&1 | head -1)\"", 30)[1].strip()
|
||||
def rejects_since(self, since_utc, log=None):
|
||||
log = log or f"{F}/node.log"
|
||||
out = self.run(f"awk -v s='{since_utc}' 'substr($0,1,19) >= s' {log} 2>/dev/null | grep -cE 'got reject message|PoW rejected|block rejected|invalid block'", 30)[1].strip()
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ def digest_alert(label, got, expected):
|
|||
st = json.load(open(DIGEST_ALERTS)) if os.path.exists(DIGEST_ALERTS) else {}
|
||||
if time.time() - st.get(label, 0) < 3600: return
|
||||
what = f"Fleet box {label} answers handshakes with consensus digest {got[:8]}, the live object is {expected[:8]}: peers on the live object refuse it and a node whose only peer it is sits on a frozen tip"
|
||||
subprocess.run(["node", "/Users/joshm/Projects/igneum/tools/community/discord-hooks.mjs", "incident", "open", "--what", what, "--affected", "nodes that peer only with that box (a home miner reads synced on a frozen tip)", "--doing", "the fleet agent restarts the box's node on the live object; the supervisor's five-minute check found it", "--id", f"digest-{label}-{int(time.time())}", "--live"], capture_output=True, text=True, timeout=60)
|
||||
subprocess.run(["node", os.environ.get("IGNEUM_DISCORD_HOOKS", os.path.join(HERE, "..", "community", "discord-hooks.mjs")), "incident", "open", "--what", what, "--affected", "nodes that peer only with that box (a home miner reads synced on a frozen tip)", "--doing", "the fleet agent restarts the box's node on the live object; the supervisor's five-minute check found it", "--id", f"digest-{label}-{int(time.time())}", "--live"], capture_output=True, text=True, timeout=60)
|
||||
st[label] = time.time(); json.dump(st, open(DIGEST_ALERTS, "w")); print(now(), "digest alert", label, got[:8], "expected", expected[:8], flush=True)
|
||||
def check_one(r):
|
||||
b = Box.from_registry(r["label"]); row = dict(r); row["t"] = now()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ result rows (results.json: {card_key: {...}}), the night rows (night.json: [..])
|
|||
"""
|
||||
import time, json, os, sys, time, datetime, subprocess
|
||||
ROOT = os.path.expanduser("~/Desktop/fleet"); OUT = os.path.join(ROOT, "fleet.json")
|
||||
PUBLISH = "/Users/joshm/Projects/igneum/tools/fleet/publish-fleet.sh"
|
||||
PUBLISH = os.environ.get("IGNEUM_FLEET_PUBLISH", os.path.join(os.path.dirname(os.path.abspath(__file__)), "publish-fleet.sh")) # this tree's publish script (master's once merged)
|
||||
def now(): return datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
def jl(name, default):
|
||||
p = os.path.join(ROOT, name)
|
||||
|
|
|
|||
Loading…
Reference in a new issue