diff --git a/README.md b/README.md index 0449e74..8a4162d 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,24 @@ Build the installer: bun run app:build ``` +Build the installer for a release: + +```bash +bun run release +``` + +A binary embeds the absolute paths of what it was compiled from — Rust panic +locations, and `__FILE__` in the sherpa-onnx library this build compiles with +MSVC — and on a developer's machine those paths hold the account name. The +release build therefore runs through two commands of +[wayBetter](https://git.crt.fyi/CRT/waybetter)'s CLI (set `WAYBETTER_CLI` to its +`packages/waybetter/bin/waybetter.mjs`, or have `waybetter` on the `PATH`): +`build-env` builds with those paths remapped or trimmed, and `privacy-scan` +opens the finished installer and fails the release if the account name, or any +name listed in the file `WAYBETTER_FORBIDDEN_TERMS` points at, is still in it. +Reviewed false positives live in `privacy-allowlist.txt`. It needs CMake and +7-Zip, and only an installer that passed is published. + Run the test suite: ```bash diff --git a/package.json b/package.json index 109f809..74667fb 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "check": "svelte-check --tsconfig ./tsconfig.json", "tauri": "tauri", "app": "tauri dev", - "app:build": "tauri build" + "app:build": "tauri build", + "release": "node scripts/release.mjs" }, "dependencies": { "@tauri-apps/api": "^2.11.1", diff --git a/privacy-allowlist.txt b/privacy-allowlist.txt new file mode 100644 index 0000000..9f18425 --- /dev/null +++ b/privacy-allowlist.txt @@ -0,0 +1,17 @@ +# Reviewed false positives of the release scan (scripts/release.mjs), one per line: +# : > +# +# onnxruntime.dll is Microsoft's prebuilt runtime. It names ONNX operators and quotes their +# documentation, and one operator's name is an ordinary English word that can also be a name. +# None of these is a path or a person. +**/onnxruntime.dll: AtanhMin +**/onnxruntime.dll: onnxruntime::_\d+< +**/onnxruntime.dll: sequence length was +**/onnxruntime.dll: detections to output +**/onnxruntime.dll: is_bidirectional distance +**/onnxruntime.dll: = ?\( +**/onnxruntime.dll: [QX]_[ ,)_] +# +# textream.exe holds the names of the HTTP headers its webview layer knows; one of them carries +# the same English word. +**/textream.exe: Access-Control--Age diff --git a/scripts/release.mjs b/scripts/release.mjs new file mode 100644 index 0000000..e826bac --- /dev/null +++ b/scripts/release.mjs @@ -0,0 +1,39 @@ +// The release build: the installer, built without this machine's paths, then scanned. +// +// A binary embeds the absolute paths of what it was compiled from: Rust panic locations, and +// `__FILE__` in the sherpa-onnx library this build compiles with MSVC. On a developer's machine +// those paths hold the account name. wayBetter's `build-env` runs the build with them remapped or +// trimmed, and its `privacy-scan` opens the finished installer and looks for what must not be in +// it. Nothing is published from here: a clean scan is what makes the installer publishable. +// +// bun run release (WAYBETTER_CLI: path to waybetter's bin/waybetter.mjs, else `waybetter`) +import { spawnSync } from 'node:child_process'; +import { existsSync, readFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = dirname(dirname(fileURLToPath(import.meta.url))); +const { version } = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')); +const installer = join(root, 'target', 'release', 'bundle', 'nsis', `Textream_${version}_x64-setup.exe`); +const waybetter = process.env.WAYBETTER_CLI ? ['node', process.env.WAYBETTER_CLI] : ['waybetter']; + +function run(step, [command, ...args]) { + console.log(`\n== ${step}`); + const quoted = [command, ...args].map(arg => (/\s/.test(arg) ? `"${arg}"` : arg)).join(' '); + const { status } = spawnSync(quoted, { cwd: root, stdio: 'inherit', shell: true }); + if (status !== 0) { + console.error(`\nrelease: "${step}" failed (exit ${status ?? 'none'}). Nothing here is publishable.`); + process.exit(status || 1); + } +} + +// CMake does not recompile objects when only the environment changed, so a sherpa-onnx left over +// from an ordinary build would keep its paths. +run('clean the release profile', ['cargo', 'clean', '--release']); +run('build the installer, path-free', [...waybetter, 'build-env', '--root', root, '--', 'bun', 'run', 'app:build']); +if (!existsSync(installer)) { + console.error(`release: the build left no ${installer}`); + process.exit(1); +} +run('scan the installer', [...waybetter, 'privacy-scan', installer, '--allow', join(root, 'privacy-allowlist.txt')]); +console.log(`\nClean. Publishable: ${installer}`); diff --git a/src-tauri/installer/header.bmp b/src-tauri/installer/header.bmp index 362e065..7665cab 100644 Binary files a/src-tauri/installer/header.bmp and b/src-tauri/installer/header.bmp differ diff --git a/src-tauri/installer/sidebar.bmp b/src-tauri/installer/sidebar.bmp index b15da0f..d5c19ee 100644 Binary files a/src-tauri/installer/sidebar.bmp and b/src-tauri/installer/sidebar.bmp differ