mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-05-28 18:11:31 +02:00
a930497e14
* fix(start-scripts): find bundled privacy_core.dll next to script start.bat and start.sh only checked the source-tree DLL path (``privacy-core/target/release/privacy_core.dll``), not the bundled location where MSI/AppImage/DMG installers stage the library directly next to the script in backend-runtime/. Users running start.bat from inside an MSI install dir (a documented workaround when the desktop shell crashes) saw a scary "install Rust" warning even though the DLL was sitting right next to them. See issue #319 for the user-reported confusion. Fix: add a fallback check for the bundled location before falling through to the "build privacy-core from source" warning. Source-tree behavior unchanged — the source path is still preferred when present. Also re-stamps the v0.9.81 source archive: ``release_digests.json`` v0.9.81 zip hash updated to point at the rebuilt source archive that contains these script changes. MSI/EXE/sig hashes are unchanged (the scripts live at the repo root, not inside the desktop bundle). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(#319): bundle start.bat + start.sh into the MSI/EXE installers Follow-up to the start-script DLL fallback fix in the prior commit. ChrisMTheMan's report on #319 made it clear the workaround flow was: 1. MSI install crashes on launch (different bug, fixed in v0.9.81) 2. User goes looking for start.bat to launch the backend manually 3. start.bat isn't in their install dir, so they go fetch it from GitHub 4. They get a working script but it doesn't know about the bundled privacy_core.dll layout, so they see a scary "install Rust" warning The prior commit fixed step 4. This commit fixes step 3 — start.bat and start.sh now ship inside the MSI/EXE installers (staged into backend-runtime/ next to the privacy_core.dll they expect to find). After the rebuild lands, an MSI user looking for these scripts finds them right inside their install dir, already pointing at the correct bundled DLL location. What changed ------------ * ``build-backend-runtime.cjs`` now has a ``stageStartScripts()`` step that copies start.bat and start.sh from the repo root into the staged backend-runtime/. Preserves the executable bit on .sh under POSIX. * ``release_digests.json`` v0.9.81 block hashes refreshed for the rebuilt MSI / EXE / source-zip (the scripts being bundled changed the MSI/EXE contents; the source zip also includes the start-script fix from the prior commit). ShadowBroker_v0.9.81.zip 6.06 MB af8c87ccdece8fbb9aadc6be63cce10d3fcba74e6d87ef83289dda6d555fd270 ShadowBroker_0.9.81_x64_en-US.msi 122.4 MB 8977c9a1c54e1f0d030436be9c4e3d81d766cc0080699eb747649095f360c7ff ShadowBroker_0.9.81_x64-setup.exe 76.5 MB 4e866fa0423c0c2470ed32f4809167a7815dc23ee7762b69e95681c1f3a28250 Post-merge plan --------------- Force-move the v0.9.81 tag to this commit and replace ALL release assets on the GitHub release: zip, msi, exe, both .sig files, latest.json, SHA256SUMS.txt, release-manifest.json. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
214 lines
6.5 KiB
JavaScript
214 lines
6.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const { spawnSync } = require('node:child_process');
|
|
|
|
const scriptDir = __dirname;
|
|
const tauriDir = path.resolve(scriptDir, '..');
|
|
const repoRoot = path.resolve(tauriDir, '..', '..');
|
|
const backendDir = path.join(repoRoot, 'backend');
|
|
const privacyCoreDir = path.join(repoRoot, 'privacy-core');
|
|
const outputDir = path.join(tauriDir, 'src-tauri', 'backend-runtime');
|
|
const venvMarkerPath = path.join(backendDir, '.venv-dir');
|
|
const releaseAttestationPath = path.join(backendDir, 'data', 'release_attestation.json');
|
|
const stagedReleaseAttestationPath = path.join(
|
|
outputDir,
|
|
'data',
|
|
'release_attestation.json',
|
|
);
|
|
|
|
const excludedNames = new Set([
|
|
'.env',
|
|
'.pytest_cache',
|
|
'.ruff_cache',
|
|
'__pycache__',
|
|
'backend.egg-info',
|
|
'build',
|
|
'data',
|
|
'tests',
|
|
'timemachine',
|
|
]);
|
|
|
|
const excludedFiles = new Set([
|
|
'.env.example',
|
|
'ais_cache.json',
|
|
'carrier_cache.json',
|
|
'cctv.db',
|
|
'dm_token_pepper.key',
|
|
'pytest.ini',
|
|
]);
|
|
|
|
function backendPythonPath() {
|
|
let venvDir = 'venv';
|
|
try {
|
|
const persisted = fs.readFileSync(venvMarkerPath, 'utf8').trim();
|
|
if (persisted) {
|
|
venvDir = persisted;
|
|
}
|
|
} catch {}
|
|
|
|
if (process.platform === 'win32') {
|
|
return path.join(backendDir, venvDir, 'Scripts', 'python.exe');
|
|
}
|
|
return path.join(backendDir, venvDir, 'bin', 'python3');
|
|
}
|
|
|
|
function shouldCopy(srcPath) {
|
|
const relativePath = path.relative(backendDir, srcPath);
|
|
if (!relativePath) return true;
|
|
|
|
const parts = relativePath.split(path.sep);
|
|
return parts.every((part, index) => {
|
|
const isLeaf = index === parts.length - 1;
|
|
if (excludedNames.has(part)) return false;
|
|
if (isLeaf && excludedFiles.has(part)) return false;
|
|
if (/^test_.*\.py$/i.test(part)) return false;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
function ensureRuntimePrereqs() {
|
|
if (!fs.existsSync(path.join(backendDir, 'main.py'))) {
|
|
throw new Error(`Missing backend/main.py at ${backendDir}`);
|
|
}
|
|
if (!fs.existsSync(backendPythonPath())) {
|
|
throw new Error(
|
|
`Missing bundled backend Python runtime at ${backendPythonPath()}. ` +
|
|
'Create the backend venv before packaging the desktop app.',
|
|
);
|
|
}
|
|
if (!fs.existsSync(path.join(backendDir, 'node_modules', 'ws'))) {
|
|
throw new Error(
|
|
`Missing backend/node_modules/ws at ${path.join(backendDir, 'node_modules', 'ws')}. ` +
|
|
'Install backend Node dependencies before packaging the desktop app.',
|
|
);
|
|
}
|
|
}
|
|
|
|
function privacyCoreArtifactName() {
|
|
if (process.platform === 'win32') return 'privacy_core.dll';
|
|
if (process.platform === 'darwin') return 'libprivacy_core.dylib';
|
|
return 'libprivacy_core.so';
|
|
}
|
|
|
|
function privacyCoreArtifactPath() {
|
|
return path.join(privacyCoreDir, 'target', 'release', privacyCoreArtifactName());
|
|
}
|
|
|
|
function ensurePrivacyCoreArtifact() {
|
|
const artifact = privacyCoreArtifactPath();
|
|
if (fs.existsSync(artifact)) {
|
|
return artifact;
|
|
}
|
|
console.log('privacy-core release library missing; building it for desktop packaging...');
|
|
const result = spawnSync(
|
|
'cargo',
|
|
['build', '--release', '--manifest-path', path.join(privacyCoreDir, 'Cargo.toml')],
|
|
{
|
|
cwd: repoRoot,
|
|
env: process.env,
|
|
stdio: 'inherit',
|
|
},
|
|
);
|
|
if (result.error || result.status !== 0) {
|
|
throw new Error(
|
|
'Failed to build privacy-core release library. Install Rust/Cargo and rerun the desktop build.',
|
|
);
|
|
}
|
|
if (!fs.existsSync(artifact)) {
|
|
throw new Error(`privacy-core build completed but artifact is missing: ${artifact}`);
|
|
}
|
|
return artifact;
|
|
}
|
|
|
|
function stageBackendRuntime() {
|
|
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
fs.cpSync(backendDir, outputDir, {
|
|
recursive: true,
|
|
filter: shouldCopy,
|
|
});
|
|
stagePrivacyCoreArtifact();
|
|
stageReleaseAttestation();
|
|
stageStartScripts();
|
|
}
|
|
|
|
/**
|
|
* Copy ``start.bat`` and ``start.sh`` from the repo root into the
|
|
* staged backend-runtime/ so they sit next to ``privacy_core.dll``.
|
|
*
|
|
* Why: an MSI/EXE/AppImage user who wants to launch via the dev-style
|
|
* scripts (because the desktop shell is failing, or they prefer the
|
|
* browser frontend at localhost:3000) shouldn't have to clone the
|
|
* source repo just to get the scripts. Having them inside the install
|
|
* directory also means the bundled ``privacy_core.dll`` fallback in
|
|
* those scripts resolves to the SAME directory as the script, which
|
|
* is exactly the layout the v0.9.81 script update is looking for.
|
|
*
|
|
* Tracked from issue #319: users who fell back to start.bat from
|
|
* their MSI install dir had to go fetch it from GitHub, then saw a
|
|
* scary "install Rust" warning because the script didn't know where
|
|
* the bundled DLL was. Bundling the script removes both problems.
|
|
*/
|
|
function stageStartScripts() {
|
|
const scripts = ['start.bat', 'start.sh'];
|
|
for (const name of scripts) {
|
|
const src = path.join(repoRoot, name);
|
|
if (!fs.existsSync(src)) {
|
|
console.warn(`backend-runtime staged without ${name} (not at repo root)`);
|
|
continue;
|
|
}
|
|
const dst = path.join(outputDir, name);
|
|
fs.copyFileSync(src, dst);
|
|
// Preserve executable bit on POSIX systems for the .sh script.
|
|
if (name.endsWith('.sh') && process.platform !== 'win32') {
|
|
try {
|
|
fs.chmodSync(dst, 0o755);
|
|
} catch {
|
|
/* best-effort; not fatal on filesystems that don't honor chmod */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function stagePrivacyCoreArtifact() {
|
|
const artifact = ensurePrivacyCoreArtifact();
|
|
const stagedPath = path.join(outputDir, path.basename(artifact));
|
|
fs.copyFileSync(artifact, stagedPath);
|
|
}
|
|
|
|
function stageReleaseAttestation() {
|
|
if (!fs.existsSync(releaseAttestationPath)) {
|
|
console.warn(`backend-runtime staged without release attestation: ${releaseAttestationPath}`);
|
|
return;
|
|
}
|
|
fs.mkdirSync(path.dirname(stagedReleaseAttestationPath), { recursive: true });
|
|
fs.copyFileSync(releaseAttestationPath, stagedReleaseAttestationPath);
|
|
}
|
|
|
|
function writeBundleVersion() {
|
|
const versionPath = path.join(outputDir, '.bundle-version');
|
|
const pkg = JSON.parse(
|
|
fs.readFileSync(path.join(repoRoot, 'desktop-shell', 'package.json'), 'utf8'),
|
|
);
|
|
fs.writeFileSync(versionPath, `${pkg.version || '0.0.0'}\n`, 'utf8');
|
|
}
|
|
|
|
function fileCount(root) {
|
|
let count = 0;
|
|
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
const fullPath = path.join(root, entry.name);
|
|
if (entry.isDirectory()) {
|
|
count += fileCount(fullPath);
|
|
} else {
|
|
count += 1;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
ensureRuntimePrereqs();
|
|
stageBackendRuntime();
|
|
writeBundleVersion();
|
|
console.log(`backend-runtime staged: ${fileCount(outputDir)} files`);
|