Workflow: .github/workflows/tauri-build.yml
Documentation: Full
.mdindex βREADME.mdΒ§ Documentation Hub;AUDIT.mdlists all 15 maintainer guides.
- Manual: Actions β βTauri desktop buildβ β Run workflow
- Tags: pushing
v*(e.g.v1.2.0) starts a build on Ubuntu, Windows, and macOS (Apple Silicon) in parallel.
| Runner | Target arch | Updater platform key |
|---|---|---|
ubuntu-22.04 |
x86_64 (AppImage / deb / rpm) | linux-x86_64 |
windows-latest |
x86_64 (NSIS -setup.exe, MSI fallback) |
windows-x86_64 |
macos-latest |
aarch64 (Apple Silicon) | darwin-aarch64 |
Native Intel-Mac (x86_64) builds are not in the production release matrix. macos-13 (the last
GitHub-hosted Intel runner using that label) was removed from the matrix on 2026-07-28: 3 consecutive
tagged-release runs each had the macos-13 job sit in GitHub's runner queue indefinitely (never
reaching in_progress, so the job's own timeout-minutes: 45 never applied) until GitHub's ~24h
queue ceiling auto-cancelled it β and because the release job's needs: [bundle] only resolves
once every matrix leg reaches a terminal state, this blocked the entire release for 24h even though
Ubuntu/Windows/macOS-ARM all finished in ~12 minutes. This was a GitHub-hosted-runner availability
issue (Intel macOS images were being phased out), not a bug in this repo's build logic.
Update (empirically re-verified): GitHub's replacement label macos-15-intel (introduced
2025-09-18, available through August 2027) does schedule and run successfully on this org's plan β a
throwaway workflow_dispatch probe completed in full. A separate, qualification-only workflow,
tauri-intel-qualification.yml, builds the
app on macos-15-intel to confirm the toolchain still works there; it is deliberately not wired
into the production release matrix or latest.json β one successful build proves the runner label
works, not that it's ready for regular release qualification (soak testing, artifact size/behavior
parity with the ARM build, and a decision on ongoing maintenance cost are still open). Promoting it
into the release matrix is tracked separately β see docs/native/INTEL-MACOS-QUALIFICATION.md and
the Follow-ups section below. The latest.json generator already tolerates a missing arch (per-arch
warning, hard-fail only if no arch signs), so re-adding Intel to the release matrix needs no other
changes once that decision is made.
Each matrix job uploads tauri-bundle-<os> containing src-tauri/target/release/bundle/ (.deb, .msi/.exe, .dmg/.app depending on OS).
When the workflow runs on a v* tag (not on manual workflow_dispatch alone), a follow-up release job downloads all tauri-bundle-* artifacts, collects .deb, .AppImage, .rpm, .msi, .exe, and .dmg files, and publishes them on a GitHub Release for that tag (softprops/action-gh-release). If no matching bundle files are found, the release step is skipped with a warning.
This workflow is independent of the web PWA pipeline (docs/CI.md); it does not gate GitHub Pages deploy.
node scripts/dependency-state.mjs reconcile
pnpm run build # frontend β also runs via Tauri beforeBuildCommand
pnpm exec tauri buildLinux dev deps match the Ubuntu job (WebKitGTK 4.1, AppIndicator, librsvg, patchelf).
The web ci.yml pipeline never compiles src-tauri/. This workflow only runs on
workflow_dispatch / v* tags, and the full crate often will not build on constrained dev hardware
(huge dep tree, WebKitGTK system libs, possible OOM). So a Rust change can merge through a green
web-CI while never having been compiled.
The gate for any src-tauri/ change is to dispatch this workflow on the branch:
git push -u origin <branch>
gh workflow run tauri-build.yml --ref <branch>
gh run watch "$(gh run list --workflow=tauri-build.yml --limit 1 --json databaseId -q '.[0].databaseId')"A run that reaches Finished release profile β¦ target(s) and Finished N bundles at: has compiled
and packaged successfully. The ubuntu and macOS jobs are the meaningful Rust signal; the
Windows job currently fails earlier in the ./.github/actions/setup composite (self-installer
exit 3221226505) β an environment/infra issue, not Rust.
tauri-build.yml history:
- 2026-05-30 β 2026-06-03: Red due to two compile-stage blockers (see
AUDIT.mdΒ§ WorkerBus v2 Phase 3). - 2026-06-03 β 2026-06-12: Ubuntu bundles
.deb/.rpm/.AppImagesuccessfully; macOS/Windows still failed onBuilder::on_event()/RunEvent::Opened/SecondInstance. - 2026-06-12:
src-tauri/src/lib.rsupdated β removed obsoleteBuilder::on_event()andRunEvent::Opened/SecondInstancehandlers that conflicted withtauri_plugin_single_instance. The plugin already emits"deep-link://new-url"for second-instance/file-open events. - 2026-06-12 (post-fix): Full workflow dispatch run green on Ubuntu (
.deb,.rpm,.AppImage), macOS (.dmg), and Windows (.msi,.exe).
| Issue | Status |
|---|---|
src-tauri/Cargo.toml β unused specta = "2" / tauri-specta = "2" |
Fixed β both removed |
src-tauri/src/lora.rs β LoraEnvReport missing Deserialize |
Fixed β Deserialize added |
src-tauri/src/lib.rs β obsolete Builder::on_event() + RunEvent::Opened/SecondInstance |
Fixed β handlers removed; single-instance plugin handles deep links |
| Ubuntu/macOS/Windows bundle jobs | Green on workflow_dispatch |
Remaining non-code blocker for a fully signed release:
- Updater signing secret β for
v*tag releases,TAURI_SIGNING_PRIVATE_KEYmust be a valid minisign key.workflow_dispatchtest builds unset the secret and disable updater artifacts (createUpdaterArtifacts = false), so they build without signing. Regenerate per First-release checklist when ready to publish.
| Feature | Implementation |
|---|---|
| Native menu | src-tauri/src/lib.rs β File (Export, Settings, Quit), Help β emits menu-action |
| Frontend bridge | services/tauriMenuService.ts + App.tsx maps to nav-export, nav-settings, nav-help |
| Window state | tauri-plugin-window-state restores size/position between sessions |
| Data folder | Settings β Data β βOpen data folderβ (services/tauriRuntime.ts) |
- Updater plugin is wired in Rust +
tauri.conf.json; full operational steps (keys,latest.json, CI secrets) are indocs/TAURI-UPDATER.md. - The Tauri desktop build workflow passes
TAURI_SIGNING_PRIVATE_KEYandTAURI_SIGNING_PRIVATE_KEY_PASSWORDwhen configured in repository secrets (optional β omit until keys exist).
Complete these steps once before pushing the first signed release tag:
1. pnpm exec tauri signer generate -- -w ~/.worldscript-tauri.key
# Copy the public key β tauri.conf.json β plugins.updater.pubkey
# Copy the private key material β GitHub repo secret TAURI_SIGNING_PRIVATE_KEY
2. Set GitHub repo secrets (Settings β Secrets β Actions):
- TAURI_SIGNING_PRIVATE_KEY (private key from step 1)
- TAURI_SIGNING_PRIVATE_KEY_PASSWORD (key password or empty string)
3. Push a v*.* tag (e.g. git tag v1.6.0 && git push --tags)
β All 3 matrix jobs build and sign bundles
β release job uploads installers + latest.json to GitHub Release
4. Verify release-assets in the GitHub Release:
- tauri-bundle-ubuntu-22.04 β .deb, .AppImage + .sig files
- tauri-bundle-windows-latest β .msi/.exe + .sig files
- tauri-bundle-macos-latest β .dmg + .app.tar.gz (aarch64) + .sig files
- latest.json (auto-updater manifest with linux/windows/darwin-aarch64 entries β no
darwin-x86_64; Intel Mac builds are deferred, see the Build matrix section above)
5. Download the installer for your OS, install the app, open it.
## Desktop audit checklist (v1.8)
| Area | Check |
|------|--------|
| CSP `connect-src` | OpenAI-compatible URLs, Ollama, WebRTC signaling β no DuckDB network |
| FS parity | Import/export via `storageService`; no direct `@tauri-apps/api` in UI atoms |
| Window / state | Single-window; close saves via listener middleware |
| Pandoc EPUB | `pandoc_markdown_to_epub` optional; JS fallback when unavailable |
| Updater | `docs/TAURI-UPDATER.md` when publishing signed tags |
| Local CI | Heavy builds optional β `infra/low-end-ci/` act + native `pnpm run ci:quick` |
| Version UI | Settings shows app version; matches release tag after install |
| File Associations | `.worldscript` and `.wsst` extensions registered; double-click opens project |
| Single-Instance | Second instance focuses main window + opens file via `RunEvent::SecondInstance` |
## Native File Associations (v1.20)
WorldScript Studio registers `.worldscript` and `.wsst` file extensions for native project opening.
### Configuration
- `tauri.conf.json` β `bundle.fileAssociations` registers both extensions with `role: "Editor"`
- `tauri.conf.json` β `plugins.deep-link.desktop.schemes` enables `worldscript://` (and legacy `storycraft://`) protocol
- `src-tauri/src/lib.rs` β `RunEvent::Opened` and `RunEvent::SecondInstance` handlers
- `services/tauriDeepLink.ts` β Frontend event listener for `open-project-file`
### Behavior
1. **Double-click** a `.worldscript` or `.wsst` file β App opens (or activates existing instance) and loads the project
2. **Drag-drop** file onto app icon β Same behavior as double-click
3. **Second instance** β Main window focused, file opened in existing instance
4. **Error handling** β Toast notification with error details if file cannot be loaded
### Icon Preparation
Create icons in `icons/` directory:
- `icons/worldscript-16x16.png` - File icon for Windows/Linux
- `icons/worldscript-32x32.png` - File icon for Windows/Linux
- `icons/worldscript-48x48.png` - File icon for Windows/Linux
- `icons/worldscript-256x256.png` - File icon for Windows/Linux
macOS uses the existing `icons/icon.icns` for file associations.
**Post-release (updater):**
6. Set `plugins.updater.active = true` in `tauri.conf.json` (commit + push).
7. Push a patch tag (`v*.*.+1`) to test auto-update β installed app should prompt to update.
8. Verify the version shown in Settings matches the tag.
See [`docs/TAURI-UPDATER.md`](TAURI-UPDATER.md) for full secrets reference and platform code-signing details.
## Follow-ups (not automated here)
- macOS notarization requires `APPLE_*` secrets β see [`docs/TAURI-UPDATER.md`](TAURI-UPDATER.md) Β§ macOS code signing.
- Windows Authenticode signing requires a CA-issued Authenticode certificate β track in [`TODO.md`](../TODO.md).
- Promoting `tauri-intel-qualification.yml`'s `macos-15-intel` build into the production release matrix (real `latest.json` entry, `darwin-x86_64` updater key, ongoing soak testing) β see `docs/native/INTEL-MACOS-QUALIFICATION.md` for current status and the tracking issue.