Build a macOS desktop app (Tauri)
このコンテンツはまだ日本語訳がありません。
Packaging the tool as a macOS desktop app uses Tauri (Rust + the system
WebView) as the shell and bundles serve.py as a PyInstaller sidecar. The
desktop app bundles only the Playground tool (/ + /api/*) — not the landing
page or docs — so it opens straight into the tool. Everything lives in desktop/.
How it works
Section titled “How it works”- Tauri launches and spawns the
servesidecar with--port 0 --data-dir <appData>. - The sidecar seeds
~/Library/Application Support/vn.fighttech.appstorepreview/from the bundled tool on first run — so writes (.env,listing*.json,assets/new,assets/current) go to a writable dir, not the read-only.app. serve.pybinds a free port and printsREADY http://127.0.0.1:<port>/. With no landing page bundled,/serves the tool directly.- Tauri reads that line and opens the window on the URL — same origin for UI and
/api/*, so Sync / Test / Try template work exactly likerun.sh.
Only the Playground tool is bundled, so Node is not needed for the desktop build. The runtime is the Python sidecar + the WebView.
cd desktopbash scripts/setup-prereqs.sh # one-time: Rust, PyInstaller, Python deps, nodebash scripts/build.sh # icons → sidecar (PyInstaller) → tauri build# → src-tauri/target/release/bundle/dmg/*.dmg| Script | Does |
|---|---|
setup-prereqs.sh | Installs Rust (rustup), PyInstaller + Python store deps, node deps |
build-sidecar.sh | Embeds the Playground tool, PyInstaller → src-tauri/binaries/serve-<triple> |
build.sh | Icons + sidecar + tauri build → .app / .dmg |
Code signing & notarization
Section titled “Code signing & notarization”Unsigned builds trigger a Gatekeeper warning on other Macs (“AppPreview is damaged”).
Auto-setup from an App Store Connect API key (recommended)
Section titled “Auto-setup from an App Store Connect API key (recommended)”Put your ASC API key in desktop/.signing/signing.env (ASC_KEY_ID,
ASC_ISSUER_ID, ASC_KEY_P8) and run:
cd desktop && python3 scripts/setup-signing.pyIt creates the Developer ID Application certificate via the App Store Connect
API, imports it into your keychain, exports DeveloperID.p12, and writes the
APPLE_SIGNING_IDENTITY / APPLE_TEAM_ID / APPLE_CERTIFICATE_* / APPLE_API_*
values. Then bash scripts/build.sh produces a signed + notarized .dmg that
opens with no warning. (Needs Apple Developer Program; the API key must have Admin /
Account Holder access.)
Manual
Section titled “Manual”Or sign + notarize by hand: copy signing.env.example → signing.env and drop your
files in that folder:
desktop/.signing/ signing.env # filled-in config (gitignored) DeveloperID.p12 # "Developer ID Application" cert + key (export from Keychain) AuthKey_XXXXXXXXXX.p8 # App Store Connect API key (for notarization)Key values:
APPLE_SIGNING_IDENTITY— e.g.Developer ID Application: Tran Trung Hieu (TEAMID)(find withsecurity find-identity -v -p codesigning)APPLE_CERTIFICATE_PASSWORD— the.p12export passwordAPPLE_TEAM_ID— your 10-char Team IDAPPLE_API_ISSUER/APPLE_API_KEY/APPLE_API_KEY_PATH— the notary key
bash scripts/build.sh then signs the sidecar (hardened runtime via
entitlements.plist) and tauri build signs + notarizes the .app/.dmg. The
.signing/ folder is gitignored — copy it to another Mac to build there. In CI,
provide the same values as repo secrets (see .github/workflows/release-dmg.yml).
Auto-update (Tauri updater)
Section titled “Auto-update (Tauri updater)”The app updates itself via the Tauri updater — no manual reinstall:
- File ▸ Check for Updates… (and a silent check on launch) queries the latest GitHub release manifest, and if newer, prompts to download + install + relaunch.
- Updates are cryptographically verified with a signing key (separate from Apple
signing). The keypair lives in
desktop/.signing/updater.key(+.pub); the public key is intauri.conf.json → plugins.updater.pubkey.
Set up once:
npx @tauri-apps/cli signer generate -w desktop/.signing/updater.key# put the printed public key into tauri.conf.json → plugins.updater.pubkeyOn release (release-dmg.yml, tag desktop-v*), tauri build produces a signed
AppPreview.app.tar.gz + .sig; the workflow generates latest.json and uploads
all three to the GitHub Release. The updater endpoint
(releases/latest/download/latest.json) serves the manifest, so installed apps see
the new version. CI signs with secrets TAURI_SIGNING_PRIVATE_KEY (+ password).
To ship an update: bump version in tauri.conf.json, push a new desktop-v* tag.
Gotchas
Section titled “Gotchas”- Heavy deps (
cryptography,google-api-python-client) are pulled in with PyInstaller--collect-allflags. After building, open the app and run Test keys to confirm the bundled Python can reach both store APIs. - “AppPreview is damaged and can’t be opened” — this is Gatekeeper blocking an
un-notarized download (quarantine), not a real corruption. Fix:
xattr -dr com.apple.quarantine "/Applications/AppPreview.app"then open. Right-click → Open does not clear “damaged”. The permanent fix is to sign (Developer ID) + notarize — see Code signing & notarization. - The window only appears after the sidecar prints
READY; a loading splash shows meanwhile.
See desktop/README.md for the full
layout.