Skip to content

Build and Release

Garot Conklin edited this page Apr 24, 2026 · 1 revision

Build and Release

This page covers production builds, Windows installers, the Node.js backend sidecar, and the GitHub Actions release workflow.

Development vs Production

Mode UI Backend Tauri
node sift.mjs run Vite on :1420 ts-node (runs separately) tauri dev — connects to Vite
tauri build (release) frontend/dist embedded sift-backend-*.exe sidecar Full native bundle + NSIS installer

In development the backend is a separate process you manage via npm start. In production Tauri spawns the pre-bundled backend sidecar automatically on startup and kills it when the app exits.


Step-by-Step: Build a Windows Installer Locally

You need a Windows machine (or windows-latest CI runner) for the final tauri build step. The backend sidecar must be compiled targeting Windows.

1. Install All Dependencies

node sift.mjs deps

2. Bundle the Backend Sidecar

node sift.mjs package
# or: cd backend && npm run package

This runs tsc then pkg and writes:

src-tauri/binaries/sift-backend-x86_64-pc-windows-msvc.exe

Tauri requires the binary to end with the Rust target triple. pkg bundles Node.js 18 + all JS/TS dependencies into a single .exe.

better-sqlite3 note: pkg bundles the prebuilt .node native addon as an asset (configured in backend/package.json under pkg.assets). If the build fails on a native module, make sure npm ci ran in backend/ first so the correct Windows prebuilt is present in node_modules.

3. Build the Frontend

npm run build --prefix frontend

4. Run tauri build

cross-env CI=false npx tauri build

Or from the root:

npm run build

The NSIS installer is written to:

src-tauri/target/release/bundle/nsis/Sift_<version>_x64-setup.exe

CI — cargo check and the Sidecar Stub

Tauri's build script validates that every externalBin entry exists on disk with the correct target-triple suffix before compiling — even during cargo check. Because the real backend binary is only produced in the release workflow (on Windows), CI would fail if it ran cargo check against an empty binaries/ directory.

The tauri-host job in ci.yml works around this by creating a zero-byte stub before cargo check runs:

- name: Create sidecar stub for cargo check
  run: |
    mkdir -p src-tauri/binaries
    touch src-tauri/binaries/sift-backend-x86_64-unknown-linux-gnu
    chmod +x src-tauri/binaries/sift-backend-x86_64-unknown-linux-gnu

Tauri's build script only checks existence, not content, so the type-check passes cleanly. The real binary is built and verified only in release.yml on windows-latest.


Release Workflow

Sift uses a release branch pattern: all feature work lands on main, a dedicated release/vX.Y.Z branch is used to finalise the changelog and bump versions, that branch is PR'd back to main, and the tag is pushed only after the PR merges. This keeps the changelog reviewed and the tag pointing at a clean, deliberate commit.

Step-by-Step Release Process

1. Finish Feature Work on main

Merge all feature PRs to main as normal. CI must be green before proceeding.

2. Create a Release Branch

git checkout main && git pull origin main
git checkout -b release/v0.2.0

3. Bump Versions (Keep All Three in Sync)

File Field
src-tauri/tauri.conf.json "version"
src-tauri/Cargo.toml version
Root package.json "version"

4. Update CHANGELOG.md

Move items from ## [Unreleased] into a new versioned section:

## [0.2.0] -- YYYY-MM-DD

### Added
- ...

### Fixed
- ...

### Changed
- ...

Add the comparison link at the bottom:

[0.2.0]: https://github.com/fleXRPL/sift/compare/v0.1.0...v0.2.0

Update the [Unreleased] link to point from the new tag:

[Unreleased]: https://github.com/fleXRPL/sift/compare/v0.2.0...HEAD

5. Commit and Push the Release Branch

git add CHANGELOG.md src-tauri/tauri.conf.json src-tauri/Cargo.toml package.json
git commit -m "chore: release v0.2.0"
git push origin release/v0.2.0

6. Open a PR: release/v0.2.0 -> main

  • Title: chore: release v0.2.0
  • Body: paste the new CHANGELOG section as context for reviewers
  • Wait for CI to pass, get approval, then Squash and merge

7. Pull main Locally and Tag

git checkout main && git pull origin main
git tag v0.2.0
git push origin v0.2.0

Pushing the tag triggers release.yml automatically.


GitHub Actions — Automated Windows Release

Workflow: .github/workflows/release.yml

The release.yml workflow runs on windows-latest and:

  1. Installs Node 18 + all npm deps
  2. Builds frontend (vite build)
  3. Bundles backend sidecar with pkgsrc-tauri/binaries/
  4. Verifies the .exe exists and prints its size
  5. Runs npx tauri build (with CI=false)
  6. Extracts the matching CHANGELOG.md section for the tag version
  7. Creates a GitHub Release with the changelog body and attaches the NSIS .exe
  8. Also saves the installer as a workflow artifact (30-day retention)

Manual Test Build (No Tag Needed)

Go to Actions → Release — Windows installer → Run workflow on GitHub and trigger it manually. The installer will be available as a downloadable artifact.

Optional: Code-Signing

Set these repository secrets to sign the installer:

Secret Value
TAURI_SIGNING_PRIVATE_KEY PEM-encoded private key from tauri signer generate
TAURI_SIGNING_PRIVATE_KEY_PASSWORD Key password (can be empty)

Unsigned builds work fine for internal distribution but Windows Defender SmartScreen will warn users on first run.


Sidecar Lifecycle (Production)

The Rust code in src-tauri/src/lib.rs handles the backend sidecar automatically:

  • Startup (setup()): spawns sift-backend and polls GET /health for up to 15 seconds before the UI loads.
  • Tray → Quit: kills the child process before calling app.exit(0).
  • Dev builds (cargo build / tauri dev): sidecar code is compiled out via #[cfg(not(debug_assertions))] — the backend runs separately as usual.

Icons

Regenerate all icon sizes from the master SVG:

cd src-tauri
npx @tauri-apps/cli icon ../img/sift-icon.svg

Version Bumps

Update all three in sync before tagging:

File Field
src-tauri/tauri.conf.json "version"
src-tauri/Cargo.toml version
Root package.json "version"

Related Docs

Clone this wiki locally