aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-15 17:42:30 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-15 17:45:41 +0200
commit0d082ab4d19412079516b281aff76e8c3f70d9ba (patch)
tree46bc48f67663c4049384578c594b8558bce2db6c /packages/meshbay-node
parent41d03f0a35a95daa7d54e7f29ab924776bedf6e4 (diff)
downloadmeshbay-0d082ab4d19412079516b281aff76e8c3f70d9ba.tar.gz
fix(packaging): setup ends a command-line client run from its install
A `meshbay-cli chat --follow` left open holds node-runtime's DLLs, so the previous version's uninstaller failed ("Failed to uninstall old application files"), a silent update included, and left the node it had stopped not running. stop-node.ps1 now ends a meshbay-cli.exe run from this install (-InstallDir, setup's $INSTDIR), and no other copy. Found through CIM, not Get-Process: setup runs the 32-bit PowerShell, which reads no path for a 64-bit process, and the first version of the stop matched nothing. The test runs the script in that PowerShell. Checked live: an update over a running follower now ends it, replaces every file and restarts the node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node')
-rw-r--r--packages/meshbay-node/tests/test_packaging_win.py50
1 files changed, 49 insertions, 1 deletions
diff --git a/packages/meshbay-node/tests/test_packaging_win.py b/packages/meshbay-node/tests/test_packaging_win.py
index ed8104f..6ee4891 100644
--- a/packages/meshbay-node/tests/test_packaging_win.py
+++ b/packages/meshbay-node/tests/test_packaging_win.py
@@ -285,7 +285,7 @@ def test_the_installer_asks_the_node_to_stop_before_forcing_it():
src = STOP_NODE_PS1.read_text(encoding="utf-8")
i_api = src.index("/api/shutdown")
i_task = src.index("schtasks /end /tn \"MeshBay Node\"")
- i_kill = src.index("Stop-Process -Force")
+ i_kill = src.index("Stop-Process -Force", src.index("Get-Process -Name meshbay-node "))
assert i_api < i_task < i_kill, (
"graceful through the control API, then Task Scheduler, then taskkill")
assert "ui_port" in src and r"data\ui-token" in src
@@ -426,6 +426,54 @@ def _dummy_node(tmp_path, name):
@pytest.mark.skipif(sys.platform != "win32", reason="runs the installer's PowerShell for real")
+def test_setup_ends_the_command_line_client_of_this_install_only(tmp_path):
+ """A `meshbay-cli chat --follow` left open holds node-runtime's DLLs, and the
+ previous version's uninstaller then failed the update, silent ones too
+ ("Failed to uninstall old application files", seen live). Setup ends a
+ client run from its own install, and no other copy of the same name."""
+ import shutil
+ import subprocess
+
+ name = "mbclistoptest"
+ install = tmp_path / "MeshBay"
+ runtime = install / "resources" / "node-runtime"
+ runtime.mkdir(parents=True)
+ elsewhere = tmp_path / "elsewhere"
+ elsewhere.mkdir()
+ procs = []
+ for where in (runtime, elsewhere):
+ exe = where / f"{name}.exe"
+ shutil.copy(r"C:\Windows\System32\PING.EXE", exe)
+ procs.append(subprocess.Popen([str(exe), "-n", "300", "127.0.0.1"],
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL))
+ ours, other = procs
+ script = (STOP_NODE_PS1.read_text(encoding="utf-8")
+ .replace('"MeshBay Node"', '"MeshBay Node stop-test"')
+ .replace("meshbay-node", "mbnodestoptest-none")
+ .replace("meshbay-cli", name))
+ copy = tmp_path / "stop-node-test.ps1"
+ copy.write_text(script, encoding="utf-8")
+ # The 32-bit PowerShell, as setup runs it ($SYSDIR is SysWOW64 in a 32-bit
+ # installer): from there Get-Process reads no path of a 64-bit process, and
+ # the first version of this stop matched nothing, live.
+ windir = os.environ.get("SystemRoot", r"C:\Windows")
+ pwsh = os.path.join(windir, "SysWOW64", "WindowsPowerShell", "v1.0", "powershell.exe")
+ if not os.path.exists(pwsh):
+ pwsh = shutil.which("powershell")
+ try:
+ r = subprocess.run([pwsh, "-NoProfile", "-ExecutionPolicy", "Bypass", "-File",
+ str(copy), "-InstallDir", str(install)],
+ capture_output=True, text=True, timeout=90)
+ assert r.returncode == 0, r.stdout + r.stderr
+ assert ours.wait(timeout=10) is not None
+ assert other.poll() is None, "a copy outside this install was ended"
+ finally:
+ for p in procs:
+ if p.poll() is None:
+ p.kill()
+
+
+@pytest.mark.skipif(sys.platform != "win32", reason="runs the installer's PowerShell for real")
def test_setup_stops_a_node_that_answers_through_its_control_api(tmp_path):
"""The graceful path: the script finds port and token where the node keeps
them, POSTs /api/shutdown, and waits for the process to go -- here a stand-in