CI/CD for a Tauri + React Desktop App with GitHub Actions
Build the React frontend and bundle native Tauri installers across platforms on a tag.
This recipe builds a Tauri desktop app with a React frontend. CI installs Linux WebKit dependencies, builds the frontend, and uses tauri-action to produce native installers for Linux, macOS, and Windows on a tag.
What the pipeline does
- fan out across ubuntu, macos, and windows
- install Linux WebKitGTK system deps
- set up Node and the Rust toolchain
- build the React frontend
- bundle installers and attach to a release with tauri-action
The workflow
tauri-apps/tauri-action runs the frontend build, the Rust bundle, and the release upload. The Linux leg needs WebKitGTK and related packages installed first.
name: CI
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: npm ci
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tagName: ${{ github.ref_name }}
releaseName: "App ${{ github.ref_name }}"Caching and speed
cache: npm restores node_modules and Swatinem/rust-cache restores the Rust build cache per OS. Bundling three platforms with native compilation is slow; cheaper managed runners such as Latchkey $0.0025/min at 2 vCPU against $0.006 GitHub-hosted cut release time and auto-retry a flaky apt or crates.io fetch.
Release output
tauri-action attaches platform installers (.deb/.AppImage, .dmg, .msi) to the GitHub Release for the tag. For signed macOS builds, add APPLE_CERTIFICATE and notarization secrets; for Windows signing, add the certificate secrets tauri-action expects.
Making this reliable in CI
- Pin every tool version. An unpinned toolchain turns a runner image update into a build break on unchanged code.
- Cache what is expensive to produce, and key the cache to the tool version so a restore across a version boundary cannot poison the build.
- Assert on the produced artifact rather than on the command succeeding.
- Set an explicit timeout so a hung step fails fast instead of consuming the whole job budget.
Key takeaways
- Install WebKitGTK system deps on the Linux leg before building.
- Use a three-OS matrix to bundle native installers per platform.
- Let tauri-action build, bundle, and attach assets to the release.