Skip to content

Commit 85514ba

Browse files
committed
Harden NovaSeal Fiber devnet readiness
1 parent 69b5ad7 commit 85514ba

1 file changed

Lines changed: 83 additions & 8 deletions

File tree

‎scripts/novaseal_fiber_node_experiments.py‎

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,23 @@ def previous_executions(output: pathlib.Path, current_fiber_repo: dict[str, Any]
310310
return executions
311311

312312

313-
def cleanup_fiber_processes(fiber_repo: pathlib.Path) -> None:
313+
def cleanup_fiber_processes(fiber_repo: pathlib.Path, *, include_all_fiber_devnet: bool = False) -> None:
314314
patterns = [
315315
re.compile(r"\.\./\.\./target/[^ ]*/fnn -d (?:[123]|cch)(?:\s|$)"),
316316
re.compile(rf"ckb run -C {re.escape(str(fiber_repo / 'tests' / 'deploy' / 'node-data'))}"),
317317
re.compile(rf"bitcoind -conf={re.escape(str(fiber_repo / 'tests' / 'deploy' / 'lnd-init' / 'bitcoind' / 'bitcoin.conf'))}"),
318318
re.compile(rf"lnd --lnddir={re.escape(str(fiber_repo / 'tests' / 'deploy' / 'lnd-init' / 'lnd-bob'))}"),
319319
re.compile(rf"lnd --lnddir={re.escape(str(fiber_repo / 'tests' / 'deploy' / 'lnd-init' / 'lnd-ingrid'))}"),
320320
]
321+
if include_all_fiber_devnet:
322+
patterns.extend(
323+
[
324+
re.compile(r"bash \./tests/nodes/start\.sh e2e/"),
325+
re.compile(r"ckb run -C .*/tests/deploy/node-data(?:\s|$)"),
326+
re.compile(r"bitcoind -conf=.*/tests/deploy/lnd-init/bitcoind/bitcoin\.conf(?:\s|$)"),
327+
re.compile(r"lnd --lnddir=.*/tests/deploy/lnd-init/lnd-(?:bob|ingrid)(?:\s|$)"),
328+
]
329+
)
321330
completed = subprocess.run(["ps", "-axo", "pid=,command="], text=True, capture_output=True, check=False)
322331
matched_pids: list[int] = []
323332
for line in completed.stdout.splitlines():
@@ -347,6 +356,73 @@ def cleanup_fiber_processes(fiber_repo: pathlib.Path) -> None:
347356
os.kill(pid, signal.SIGKILL)
348357

349358

359+
def wait_for_fiber_nodes(
360+
fiber_repo: pathlib.Path,
361+
node_process: subprocess.Popen[str],
362+
log_dir: pathlib.Path,
363+
timeout: int,
364+
env: dict[str, str],
365+
) -> dict[str, Any] | None:
366+
started_at = time.time()
367+
wait_process = subprocess.Popen(
368+
["./tests/nodes/wait.sh"],
369+
cwd=fiber_repo,
370+
text=True,
371+
stdout=subprocess.PIPE,
372+
stderr=subprocess.PIPE,
373+
env=env,
374+
)
375+
while True:
376+
wait_returncode = wait_process.poll()
377+
if wait_returncode is not None:
378+
wait_stdout, wait_stderr = wait_process.communicate()
379+
write_text(log_dir / "wait.stdout", wait_stdout)
380+
write_text(log_dir / "wait.stderr", wait_stderr)
381+
if wait_returncode != 0:
382+
return {
383+
"failure": "fiber node wait failed",
384+
"wait_returncode": wait_returncode,
385+
}
386+
if node_process.poll() is not None:
387+
return {
388+
"failure": "fiber node launcher exited after readiness check",
389+
"node_returncode": node_process.returncode,
390+
"wait_returncode": wait_returncode,
391+
}
392+
return None
393+
394+
if node_process.poll() is not None:
395+
wait_process.terminate()
396+
try:
397+
wait_stdout, wait_stderr = wait_process.communicate(timeout=10)
398+
except subprocess.TimeoutExpired:
399+
wait_process.kill()
400+
wait_stdout, wait_stderr = wait_process.communicate(timeout=10)
401+
write_text(log_dir / "wait.stdout", wait_stdout)
402+
write_text(log_dir / "wait.stderr", wait_stderr)
403+
return {
404+
"failure": "fiber node launcher exited before readiness check completed",
405+
"node_returncode": node_process.returncode,
406+
"wait_returncode": wait_process.returncode,
407+
}
408+
409+
if time.time() - started_at > timeout:
410+
wait_process.terminate()
411+
try:
412+
wait_stdout, wait_stderr = wait_process.communicate(timeout=10)
413+
except subprocess.TimeoutExpired:
414+
wait_process.kill()
415+
wait_stdout, wait_stderr = wait_process.communicate(timeout=10)
416+
write_text(log_dir / "wait.stdout", wait_stdout)
417+
write_text(log_dir / "wait.stderr", wait_stderr)
418+
return {
419+
"failure": "fiber node wait timed out",
420+
"wait_timeout_seconds": timeout,
421+
}
422+
423+
time.sleep(1)
424+
425+
350426
def fiber_run_env(base_env: dict[str, str], log_dir: pathlib.Path) -> dict[str, str]:
351427
env = dict(base_env)
352428
real_ckb_cli = shutil.which("ckb-cli", path=env.get("PATH"))
@@ -444,12 +520,14 @@ def run_workflow(args: argparse.Namespace, workflow: FiberWorkflow) -> dict[str,
444520
log_dir = args.output.resolve().parent / "novaseal-fiber-node-experiments" / workflow.suite.replace("/", "__")
445521
log_dir.mkdir(parents=True, exist_ok=True)
446522
env = fiber_run_env(os.environ, log_dir)
523+
clean_external_devnet_state = bool(env.get("REMOVE_OLD_STATE") or env.get("NOVASEAL_CLEAN_FIBER_DEVNET_PROCESSES"))
447524
started_node = False
448525
node_process: subprocess.Popen[str] | None = None
449526
node_log_handle = None
450527
started_at = time.time()
451528
try:
452529
if not args.assume_nodes_running:
530+
cleanup_fiber_processes(fiber_repo, include_all_fiber_devnet=clean_external_devnet_state)
453531
node_log = log_dir / "start-node.log"
454532
node_log_handle = node_log.open("w", encoding="utf-8")
455533
node_process = subprocess.Popen(
@@ -462,18 +540,15 @@ def run_workflow(args: argparse.Namespace, workflow: FiberWorkflow) -> dict[str,
462540
env=env,
463541
)
464542
started_node = True
465-
wait = run_cmd(["./tests/nodes/wait.sh"], fiber_repo, timeout=args.timeout_seconds, env=env)
466-
write_text(log_dir / "wait.stdout", wait.stdout)
467-
write_text(log_dir / "wait.stderr", wait.stderr)
468-
if wait.returncode != 0:
543+
readiness_failure = wait_for_fiber_nodes(fiber_repo, node_process, log_dir, args.timeout_seconds, env)
544+
if readiness_failure is not None:
469545
return {
470546
"status": "failed",
471547
"started_node": started_node,
472548
"command": ["./tests/nodes/start.sh", suite_arg],
473-
"failure": "fiber node wait failed",
474-
"wait_returncode": wait.returncode,
475549
"duration_seconds": round(time.time() - started_at, 3),
476550
"fiber_repo": fiber_repo_info,
551+
**readiness_failure,
477552
}
478553
bruno_cwd, bruno_compatibility_patches = bruno_workspace_for_suite(fiber_repo, workflow.suite, log_dir)
479554
command = ["npm", "exec", "--", "@usebruno/cli", "run", suite_arg, "-r", "--env", "test"]
@@ -507,7 +582,7 @@ def run_workflow(args: argparse.Namespace, workflow: FiberWorkflow) -> dict[str,
507582
node_process.kill()
508583
node_process.wait(timeout=20)
509584
if started_node:
510-
cleanup_fiber_processes(fiber_repo)
585+
cleanup_fiber_processes(fiber_repo, include_all_fiber_devnet=clean_external_devnet_state)
511586
if node_log_handle is not None:
512587
node_log_handle.close()
513588

0 commit comments

Comments
 (0)