summaryrefslogtreecommitdiffstats
path: root/packaging/win/README.md
blob: d02adca00341fe411d5d83f334eed42ec75a9c34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# Windows packaging (W4)

A single per-user installer — `MeshBay-Setup-<version>.exe` — that lays down the
Electron **client** and the Python **node** daemon. No hub (server-only, stays
Linux). `meshbay-common` rides along inside the node runtime.

## What the installer contains

```
%LOCALAPPDATA%\Programs\meshbay-client\
├─ MeshBay.exe                     Electron client
├─ resources\
│  ├─ app.asar                     src/ + ui/ (the interface ships in the package)
│  └─ node-runtime\
│     ├─ meshbay-node.exe          frozen daemon (PyInstaller onedir)
│     ├─ _internal\ …              its Python + deps (aiortc, av, aioquic, …)
│     └─ ffmpeg.exe, ffprobe.exe   only if built with -FfmpegDir
└─ Uninstall MeshBay.exe
```

Runtime data stays where the node already puts it: `%LOCALAPPDATA%\meshbay\`
(`node.toml`, `keystore.enc`, `unlock.key`, `data\`). The installer never writes
there and the uninstaller never deletes it — installers place files, not secrets.

## Build

On a Windows machine with **Node ≥ 22**, **Python ≥ 3.12** (`py -3.12`) and
**git**:

```powershell
cd packages\meshbay-client
npm run dist:win
```

That runs [`build-win.ps1`](build-win.ps1):

| Step | |
|---|---|
| 1 | Node ≥ 22 check |
| 2 | `npm ci` + download Electron's Chromium |
| 3 | bump Electron to the latest release (Chromium CVE policy; `-NoElectronBump` to skip) |
| 4 | `npm run sync-ui` — copy the interface from `meshbay-hub/.../static` |
| 5 | [`build-node-runtime.ps1`](build-node-runtime.ps1) — PyInstaller freeze → `packages/meshbay-client/node-runtime/` |
| 6 | `electron-builder --win nsis` → `packages/meshbay-client/dist/MeshBay-Setup-<version>.exe` |

### ffmpeg

Not bundled by default — the node resolves `ffmpeg`/`ffprobe` from `PATH` at
startup, and video streaming needs them. To make the installer self-contained:

```powershell
npm run dist:win -- -FfmpegDir "C:\path\to\ffmpeg\bin"
# or: $env:MESHBAY_FFMPEG_DIR = "C:\path\to\ffmpeg\bin"; npm run dist:win
```

They are copied beside `meshbay-node.exe`, which is on the daemon's search path.

### Iterating

```powershell
# rebuild only the installer, reuse an existing node-runtime\
powershell -File ..\..\packaging\win\build-win.ps1 -SkipNodeRuntime

# build just the frozen daemon, into an existing venv, keep it for next time
powershell -File ..\..\packaging\win\build-node-runtime.ps1 -Python C:\path\python.exe -KeepBuildVenv
```

## Why PyInstaller and not the python-embed zip

The frozen `meshbay-node.exe` is a genuine relocatable single binary. It is what
the client spawns (`findNodeBinary` in `src/main.js`) and what the W3 autostart
launcher points at (`meshbay_node.platform._node_exe`). The python.org
embeddable zip would need pip to make a `meshbay-node.exe` wrapper, and that
wrapper bakes in an **absolute** interpreter path — it stops working the moment
the tree is installed somewhere other than where it was built.

## Dependency surface that needs watching

`meshbay-node.spec` pulls the awkward packages in whole (`collect_all`) because
they have C/Rust extensions or do dynamic imports: `aiortc`, `av` (bundles
FFmpeg DLLs), `aioquic`, `pydantic_core`, `uvicorn`, `watchdog`, `guessit`,
`blake3`, `zstandard`, `msgpack`. If a frozen run raises `ModuleNotFoundError`,
add the package to `COLLECT_ALL` / `HIDDEN` / `COPY_META` in the spec — that is
the expected way the list grows.

## Not done

- **Authenticode signing** — Phase 13.9. Unsigned installer triggers SmartScreen.
- **CI** — no Windows runner builds this yet (Phase 18.3). Build is manual.
- **Delta updates / auto-update** — `electron-updater` is not wired.