diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 1f43509..a1c3a89 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -85,7 +85,7 @@ jobs: draft: false prerelease: ${{ contains(env.APP_VERSION, '-beta') || contains(env.APP_VERSION, '-alpha') || contains(env.APP_VERSION, '-rc') }} files: | - dist/stasis-backend-v*.exe + dist/stasis-backend-v*.zip frontend/src-tauri/target/release/bundle/nsis/*.exe frontend/src-tauri/target/release/bundle/nsis/*.msi frontend/src-tauri/target/release/bundle/zip/*.zip diff --git a/README.md b/README.md index 45fc1bd..2c08f91 100644 --- a/README.md +++ b/README.md @@ -303,8 +303,8 @@ From PowerShell in the project root: |---|---| | **1** | Syncs the version string into `tauri.conf.json`, `package.json`, and `Cargo.toml` | | **2** | Generates `file_version_info.txt` for Windows EXE metadata | -| **3** | Runs PyInstaller using `stasis-backend.spec` → `dist/stasis-backend.exe` | -| **4** | Copies the backend EXE to `frontend/src-tauri/bin/` | +| **3** | Runs PyInstaller using `stasis-backend.spec` → `dist/stasis-backend/` (onedir) | +| **4** | Copies the backend directory to `frontend/src-tauri/bin/stasis-backend/` | | **5** | Runs `npm install` inside `frontend/` | | **6** | Runs `npm run tauri:build` (Vite + Rust + NSIS bundling) | @@ -312,7 +312,7 @@ From PowerShell in the project root: ``` dist/ - stasis-backend-v.exe # Standalone backend (≈100 MB) + stasis-backend-v.zip # Standalone backend directory (zipped) frontend/src-tauri/target/release/bundle/ nsis/ Stasis--setup.exe # Full installer diff --git a/build.ps1 b/build.ps1 index e042c17..06b1351 100644 --- a/build.ps1 +++ b/build.ps1 @@ -20,8 +20,9 @@ $ProjectRoot = $PSScriptRoot $FrontendDir = Join-Path $ProjectRoot "frontend" $BinDir = Join-Path $ProjectRoot "frontend\src-tauri\bin" $SpecFile = Join-Path $ProjectRoot "stasis-backend.spec" -$BackendExe = Join-Path $BinDir "stasis-backend.exe" -$DistExe = Join-Path $ProjectRoot "dist\stasis-backend.exe" +$BackendDir = Join-Path $BinDir "stasis-backend" +$DistDir = Join-Path $ProjectRoot "dist\stasis-backend" +$DistExe = Join-Path $DistDir "stasis-backend.exe" $TauriConf = Join-Path $FrontendDir "src-tauri\tauri.conf.json" $PkgJson = Join-Path $FrontendDir "package.json" @@ -196,16 +197,19 @@ if (-not (Test-Path $DistExe)) { exit 1 } -Write-Host " Copying EXE to src-tauri/bin/ ..." -ForegroundColor Yellow -Copy-Item -Force $DistExe $BackendExe +Write-Host " Copying backend directory to src-tauri/bin/ ..." -ForegroundColor Yellow +if (Test-Path $BackendDir) { + Remove-Item -Recurse -Force $BackendDir +} +Copy-Item -Recurse -Force $DistDir $BackendDir -$exeSize = [math]::Round((Get-Item $BackendExe).Length / 1MB, 1) -Write-Host " [OK] stasis-backend.exe copied ($exeSize MB)" -ForegroundColor Green +$dirSizeMB = [math]::Round((Get-ChildItem $BackendDir -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB, 1) +Write-Host " [OK] stasis-backend dir copied ($dirSizeMB MB)" -ForegroundColor Green -$VersionedExeName = "stasis-backend-v$Version.exe" -$VersionedExePath = Join-Path $ProjectRoot "dist\$VersionedExeName" -Rename-Item -Path $DistExe -NewName $VersionedExeName -Force -Write-Host " [OK] Standalone backend saved as dist\$VersionedExeName" -ForegroundColor Green +$VersionedZipName = "stasis-backend-v$Version.zip" +$VersionedZipPath = Join-Path $ProjectRoot "dist\$VersionedZipName" +Compress-Archive -Path $DistDir -DestinationPath $VersionedZipPath -Force +Write-Host " [OK] Standalone backend saved as dist\$VersionedZipName" -ForegroundColor Green # ------------------------------------------------------- # 3. npm install (if needed) @@ -257,8 +261,9 @@ else { Write-Host " Bundle directory not found. Check Tauri build output above." -ForegroundColor Yellow } -if (Test-Path $VersionedExePath) { - Write-Host " $VersionedExePath ($exeSize MB)" -ForegroundColor Green +if (Test-Path $VersionedZipPath) { + $zipSizeMB = [math]::Round((Get-Item $VersionedZipPath).Length / 1MB, 1) + Write-Host " $VersionedZipPath ($zipSizeMB MB)" -ForegroundColor Green } # Cleanup diff --git a/docs/architecture.md b/docs/architecture.md index f87ac21..d2e30a9 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -40,7 +40,7 @@ Stasis uses a **dual-process architecture**: a compiled Python telemetry engine ## Python backend -The backend is a single compiled `.exe` (PyInstaller) that spawns several daemon threads on startup. +The backend is a compiled directory (PyInstaller `--onedir`) that spawns several daemon threads on startup. ### Entry point (`src/main.py`) @@ -177,7 +177,7 @@ frontend/src-tauri/target/release/bundle/ ## Process communication -The Tauri shell launches `stasis-backend.exe` as a **sidecar process** (configured in `tauri.conf.json`). The React frontend communicates with the backend exclusively via HTTP requests to `http://127.0.0.1:7432`. There are no Tauri IPC commands used for data retrieval — the HTTP API is the single source of truth. +The Tauri shell launches `stasis-backend.exe` (from `bin/stasis-backend/`) as a **sidecar process** (configured in `tauri.conf.json`). The React frontend communicates with the backend exclusively via HTTP requests to `http://127.0.0.1:7432`. There are no Tauri IPC commands used for data retrieval — the HTTP API is the single source of truth. This design means the Python backend can be run and tested independently of the Tauri shell. diff --git a/docs/developer-guide.md b/docs/developer-guide.md index e44582b..60fb7d0 100644 --- a/docs/developer-guide.md +++ b/docs/developer-guide.md @@ -99,8 +99,8 @@ The `build.ps1` script automates the entire release pipeline. |---|---| | **Version sync** | Updates the version string in `tauri.conf.json`, `package.json`, and `Cargo.toml` | | **Win32 metadata** | Generates `file_version_info.txt` so the compiled EXE has correct version metadata in Windows Explorer | -| **PyInstaller** | Runs `pyinstaller stasis-backend.spec` → `dist/stasis-backend.exe` | -| **Copy sidecar** | Moves backend EXE to `frontend/src-tauri/bin/` so Tauri bundles it | +| **PyInstaller** | Runs `pyinstaller stasis-backend.spec` → `dist/stasis-backend/` (onedir) | +| **Copy sidecar** | Copies backend directory to `frontend/src-tauri/bin/stasis-backend/` so Tauri bundles it | | **npm install** | Installs frontend dependencies (skipped if `node_modules` is up to date) | | **Tauri build** | Runs `npm run tauri:build` inside `frontend/` — compiles Vite + Rust + generates NSIS installer | @@ -108,7 +108,7 @@ The `build.ps1` script automates the entire release pipeline. ``` dist/ - stasis-backend-v1.2.3.exe ← Standalone backend (~100 MB) + stasis-backend-v1.2.3.zip ← Standalone backend directory (zipped) frontend/src-tauri/target/release/bundle/ nsis/ Stasis-1.2.3-setup.exe ← Full NSIS installer @@ -124,10 +124,10 @@ Key settings in the spec file: | Setting | Value | Reason | |---|---|---| | `console = False` | Windowed mode | No terminal window pops up | -| `upx = True` | Compress with UPX | Reduces EXE size (requires UPX in PATH) | +| `upx = True` | Compress with UPX | Reduces binary sizes (requires UPX in PATH) | | `hidden_imports` | flask, psutil, win32api, … | Ensure PyInstaller bundles all dynamic imports | | `excludes` | unittest, matplotlib, scipy, pandas, … | Strips unused heavy libraries | -| `datas` | `app_categories.json`, `ignored_apps.json` | Bundle config JSONs into the EXE | +| `datas` | `app_categories.json`, `ignored_apps.json` | Bundle config JSONs into the output dir | --- diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index 5f9da94..696decf 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -259,7 +259,7 @@ fn start_backend(app: &AppHandle) { // Resolve the bundled backend EXE path relative to the Resources dir let resource_path = app .path() - .resolve("bin/stasis-backend.exe", tauri::path::BaseDirectory::Resource) + .resolve("bin/stasis-backend/stasis-backend.exe", tauri::path::BaseDirectory::Resource) .expect("Failed to resolve backend EXE path"); #[cfg(not(debug_assertions))] diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index 5da5538..93469b0 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -47,9 +47,9 @@ "silent": true } }, - "resources": { - "bin/stasis-backend.exe": "bin/stasis-backend.exe" - }, + "resources": [ + "bin/stasis-backend/**/*" + ], "icon": [ "icons/32x32.png", "icons/128x128.png", diff --git a/stasis-backend.spec b/stasis-backend.spec index 1585613..2ce4bad 100644 --- a/stasis-backend.spec +++ b/stasis-backend.spec @@ -37,8 +37,6 @@ pyz = PYZ(a.pure) exe = EXE( pyz, a.scripts, - a.binaries, - a.datas, [], name='stasis-backend', icon='backend-app-icon.ico', @@ -48,12 +46,20 @@ exe = EXE( strip=False, upx=True, upx_exclude=[], - runtime_tmpdir=None, console=False, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, - +) + +coll = COLLECT( + exe, + a.binaries, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='stasis-backend', )