@@ -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+
350426def 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