aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-05 08:43:11 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-05 08:43:11 +0200
commit301c8998bfdcac80ad3302e2d2ebe853e2ea6de1 (patch)
tree36b0606919f7fb1a7e2ace92d40d8f3e5a6d9d8d /packages/meshbay-node/tests
parent171a36984feff5247786b32958b52673e13cc8f0 (diff)
downloadmeshbay-301c8998bfdcac80ad3302e2d2ebe853e2ea6de1.tar.gz
feat(packaging): bundle ffmpeg in the Windows installer by default
winget install ffmpeg was considered and rejected as the mechanism: it needs network access and winget/App Installer present at the exact moment setup runs, and its failure mode is silent -- video just does not stream, with nothing pointing back at ffmpeg. Not viable for a non-technical install. MeshBay transcodes browser-incompatible video to H.264 (-c:v libx264, webrtc_server.py) -- a real encode, not remux -- so this needs a genuine GPL ffmpeg build; no LGPL-only build includes an H.264 encoder, since libx264 itself is GPL. packaging/win/fetch-ffmpeg.ps1 (new) Downloads, checksum-verifies and stages ffmpeg for the build. Source: BtbN/FFmpeg-Builds' Windows x86_64 gpl-shared preset -- shared DLLs rather than two independent static binaries, which is what nearly tripled this: the "full" static build many devs already have via winget is ~220 MB *per executable*. Pinned to one dated release tag (immutable once published) and its own sha256, not the "latest" alias BtbN repoints on every auto-build -- verified by hand first (downloaded, hash matched, ran a real encode+probe with libx264) before pinning. ffplay.exe (an SDL2 player, ~17 MB) is dropped; MeshBay never invokes it. Cached after the first build. Runs its own smoke test (encode + probe a real clip) so a broken fetch fails at build time, not for the first user who tries to watch something. packaging/win/LICENSE-ffmpeg.txt (new) GPLv3 notice + where the corresponding source is, required because this redistributes a GPL binary even though it is unmodified and only ever invoked as a subprocess. Ships alongside ffmpeg.exe in the installer. build-node-runtime.ps1 / build-win.ps1 Bundling is now the DEFAULT, replacing the old opt-in -FfmpegDir (which copied from a local directory and left most builds without ffmpeg at all). -SkipFfmpeg opts out for a smaller, streaming-less local-iteration build. Also fixes a real bug the ffmpeg change exposed rather than caused: the final `--help` smoke test did `$help -notmatch "meshbay-node"` against $help captured as a PowerShell ARRAY (one element per line) -- -notmatch on a collection is a FILTER, not a boolean test, and returns the non-matching elements; any non-empty array is truthy in if() regardless of content. Once --help wrapped past one line (it now does, with autostart/service in the verb list) this threw unconditionally. Fixed by joining to one string before matching, and pinned by a new test so a future edit cannot silently reintroduce the collection-vs-scalar trap. Verified: downloaded and hashed the pinned release by hand (matches), ran a real libx264 encode + ffprobe against the extracted build, fetch-ffmpeg.ps1 end to end (161 MB staged), a full build-node-runtime.ps1 run (308 MB node-runtime/) and a full installer build (MeshBay-Setup- 1.0.0.exe, 210.8 MB with ffmpeg bundled). Node suite 850 pass / 25 skip. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests')
-rw-r--r--packages/meshbay-node/tests/test_packaging_win.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_packaging_win.py b/packages/meshbay-node/tests/test_packaging_win.py
index 22ce44b..31816d2 100644
--- a/packages/meshbay-node/tests/test_packaging_win.py
+++ b/packages/meshbay-node/tests/test_packaging_win.py
@@ -316,6 +316,29 @@ def test_service_status_reports_state_without_admin():
"calls status/run/end directly, unelevated")
+def test_the_help_smoke_test_joins_multiline_output_before_matching():
+ """
+ `& exe --help 2>&1` is an ARRAY once the output wraps past one line, which
+ it now does with `autostart`/`service` in the verb list. `$array -notmatch
+ X` is a FILTER, not a boolean test -- it returns the *non-matching*
+ elements, and any non-empty array is truthy in `if()` regardless of what
+ is in it. Almost every help line lacks the literal string "meshbay-node",
+ so an unjoined check throws unconditionally the moment --help exceeds one
+ line: found when this specific verb list finally grew past that point,
+ which is exactly the kind of one-off silent breakage a passing build
+ yesterday gives no warning of today.
+ """
+ src = (WIN / "build-node-runtime.ps1").read_text(encoding="utf-8")
+ body = src.split("smoke test: meshbay-node --help", 1)[1]
+ body = body[:800]
+ assert '-join "`n"' in body, (
+ "the captured --help output must be joined to a single string before "
+ "any -match/-notmatch check, or a multi-line result silently always "
+ "fails the smoke test")
+ # And the join has to happen at capture time, not on some other variable.
+ assert '(& $exe --help 2>&1) -join' in body
+
+
def test_main_js_drives_the_service_task_for_all_three_actions():
"""The hard requirement: Start/Stop/Restart from the Node page must
control the Scheduled Task when service mode is active, not just spawn a
@@ -409,3 +432,67 @@ def test_the_bundled_daemon_goes_on_the_user_path_and_comes_back_off():
# PATH points at the real .exe dir, so `where meshbay-node` resolves to the
# binary the client and the W3 launcher use too — not a shim.
assert 'MB_NODE_BIN "$INSTDIR\\resources\\node-runtime"' in nsh
+
+
+# ── ffmpeg: bundled by default (fetch-ffmpeg.ps1) ───────────────────────────
+
+def test_fetch_ffmpeg_and_its_license_notice_exist():
+ assert (WIN / "fetch-ffmpeg.ps1").exists()
+ notice = WIN / "LICENSE-ffmpeg.txt"
+ assert notice.exists()
+ text = notice.read_text(encoding="utf-8")
+ assert "GPL" in text
+ assert "ffmpeg.org" in text or "FFmpeg/FFmpeg" in text, (
+ "the notice must point at where the corresponding source actually is")
+
+
+def test_ffmpeg_is_pinned_to_a_dated_release_not_the_moving_latest_alias():
+ """
+ BtbN repoints the "latest" release on every auto-build (their asset
+ filenames even embed a fresh git-describe each time), so a URL built from
+ that alias silently changes what a build fetches. The dated tag
+ (autobuild-YYYY-MM-DD-HH-MM) is immutable once published -- that is what
+ makes the pinned checksum mean anything.
+ """
+ src = (WIN / "fetch-ffmpeg.ps1").read_text(encoding="utf-8")
+ tag_match = re.search(r'\$FFMPEG_TAG\s*=\s*"([^"]+)"', src)
+ assert tag_match, "no $FFMPEG_TAG pin found"
+ assert re.match(r"autobuild-\d{4}-\d{2}-\d{2}-\d{2}-\d{2}$", tag_match.group(1)), (
+ f"{tag_match.group(1)!r} is not a dated release tag")
+ assert "/releases/latest/" not in src and "/releases/download/latest/" not in src
+
+ sha_match = re.search(r'\$FFMPEG_SHA256\s*=\s*"([0-9a-f]+)"', src)
+ assert sha_match, "no $FFMPEG_SHA256 pin found"
+ assert len(sha_match.group(1)) == 64, "not a full sha256 hex digest"
+
+ assert '$FFMPEG_URL' in src and '$FFMPEG_TAG' in src.split("$FFMPEG_URL", 1)[1][:200], (
+ "the download URL must be built from the pinned tag")
+
+
+def test_ffplay_is_excluded_from_the_bundle():
+ """The vendor zip carries an SDL2 player MeshBay never invokes (~17 MB);
+ bundling it would be the collect_all-everything instinct applied where a
+ fixed allowlist is right instead."""
+ src = (WIN / "fetch-ffmpeg.ps1").read_text(encoding="utf-8")
+ keep_block = src.split("$KEEP_FILES", 1)[1].split(")", 1)[0]
+ assert "ffplay" not in keep_block
+ assert "ffmpeg.exe" in keep_block and "ffprobe.exe" in keep_block
+
+
+def test_ffmpeg_bundling_is_the_default_not_opt_in():
+ """
+ Video streaming needs a real H.264 encoder (libx264, GPL -- no LGPL-only
+ ffmpeg build has one), and asking an end user to separately run
+ `winget install ffmpeg` is not viable for a non-technical install (needs
+ network + winget present at that moment, fails silently). So bundling
+ must be the default, with an explicit opt-out for local iteration --
+ the reverse of the old -FfmpegDir opt-in this replaced.
+ """
+ runtime_src = (WIN / "build-node-runtime.ps1").read_text(encoding="utf-8")
+ assert "SkipFfmpeg" in runtime_src
+ assert "FfmpegDir" not in runtime_src, "the old opt-in mechanism should be gone, not parallel"
+ assert "fetch-ffmpeg.ps1" in runtime_src
+
+ win_src = (WIN / "build-win.ps1").read_text(encoding="utf-8")
+ assert "SkipFfmpeg" in win_src
+ assert "FfmpegDir" not in win_src