Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# Compile the Tauri shell on Linux.
# Intentionally --no-bundle: installers would be a mute window until the
# Node sidecar is packaged. This job only proves the crate + UI build.
# Linux CI: AppImage with sidecar inside. macOS/Windows stay --no-bundle.
name: ci-linux

on:
Expand All @@ -13,26 +11,30 @@ concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
APPIMAGE_EXTRACT_AND_RUN: "1"

jobs:
build:
name: build (ubuntu-22.04)
runs-on: ubuntu-22.04
name: appimage (ubuntu-24.04)
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Install Linux WebKitGTK deps
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
sudo apt-get install -y libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf

- uses: actions/setup-node@v4
- uses: actions/setup-node@v7
with:
node-version: 20
node-version: 26
cache: npm
cache-dependency-path: |
package-lock.json
app/package-lock.json
sidecar/package-lock.json

- uses: dtolnay/rust-toolchain@stable

Expand All @@ -45,8 +47,8 @@ jobs:
npm ci
npm --prefix app ci

- name: Compile shell (no bundle)
run: npm run build:ci
- name: Bundle AppImage
run: npm run build:appimage

- name: Check release binary
run: test -f src-tauri/target/release/sayit
- name: Check AppImage
run: ls -lh src-tauri/target/release/bundle/appimage/*.AppImage
5 changes: 2 additions & 3 deletions .github/workflows/ci-macos.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Compile the Tauri shell on macOS.
# Intentionally --no-bundle: installers would be a mute window until the
# Node sidecar is packaged. This job only proves the crate + UI build.
# PRs stay --no-bundle. macOS installers are not shipped yet.
name: ci-macos

on:
Expand Down Expand Up @@ -44,4 +43,4 @@ jobs:
run: npm run build:ci

- name: Check release binary
run: test -f src-tauri/target/release/sayit
run: test -f src-tauri/target/release/sayit-desktop
9 changes: 6 additions & 3 deletions .github/workflows/ci-windows.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Compile the Tauri shell on Windows.
# Intentionally --no-bundle: installers would be a mute window until the
# Node sidecar is packaged. This job only proves the crate + UI build.
# PRs stay --no-bundle. Windows installers are not shipped yet.
name: ci-windows

on:
Expand Down Expand Up @@ -40,8 +39,12 @@ jobs:
npm ci
npm --prefix app ci

- name: Ensure sidecar-bundle exists
shell: bash
run: mkdir -p src-tauri/sidecar-bundle

- name: Compile shell (no bundle)
run: npm run build:ci

- name: Check release binary
run: test -f src-tauri/target/release/sayit.exe
run: test -f src-tauri/target/release/sayit-desktop.exe
72 changes: 72 additions & 0 deletions .github/workflows/release-linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Build Linux GUI packages with the Node sidecar inside.
# PR CI stays --no-bundle; this job is tags (and manual dispatch) only.
name: release-linux

on:
push:
tags: ["v*"]
workflow_dispatch:

permissions:
contents: write

concurrency:
group: release-linux-${{ github.ref }}
cancel-in-progress: true

jobs:
linux:
name: deb + rpm (ubuntu-24.04)
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v7

- name: Install Linux WebKitGTK + rpm tooling
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf rpm

- uses: actions/setup-node@v7
with:
node-version: 26
cache: npm
cache-dependency-path: |
package-lock.json
app/package-lock.json
sidecar/package-lock.json

- uses: dtolnay/rust-toolchain@stable

- uses: swatinem/rust-cache@v2
with:
workspaces: ./src-tauri -> target

- name: Install JS deps
run: |
npm ci
npm --prefix app ci

- name: Bundle deb and rpm
run: npx tauri build -b deb,rpm

- uses: actions/upload-artifact@v7
with:
name: linux-packages
path: |
src-tauri/target/release/bundle/deb/*.deb
src-tauri/target/release/bundle/rpm/*.rpm

- name: Publish GitHub Release
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ github.ref_name }}" \
src-tauri/target/release/bundle/deb/*.deb \
src-tauri/target/release/bundle/rpm/*.rpm \
--generate-notes --verify-tag \
|| gh release upload "${{ github.ref_name }}" \
src-tauri/target/release/bundle/deb/*.deb \
src-tauri/target/release/bundle/rpm/*.rpm \
--clobber
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ app/build/
app/.svelte-kit/
src-tauri/target/
src-tauri/gen/
src-tauri/sidecar-bundle/node_modules/
src-tauri/sidecar-bundle/src/
src-tauri/sidecar-bundle/package.json
src-tauri/sidecar-bundle/package-lock.json
*.log

# OS / editor junk
Expand All @@ -14,3 +18,4 @@ Thumbs.db
.idea/
.vscode/
.codegraph/
.zcode/
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ Crucial reminders for future sessions. See LINUX.md for full architecture.
- **Node ≥ 20**, Rust, **mpv** (playback), `wl-paste`/`xclip`/`xsel` (clipboard).
- Root deps: `@tauri-apps/cli`. App and sidecar have their own `package.json`.
- Dev: `npm run dev` starts sidecar + `tauri dev`. `beforeDevCommand` runs from project root with `--prefix app`.
- CI: `npm run build:ci` (`tauri build --no-bundle`) on Ubuntu 22.04, macOS, Windows. Do not add bundling to that job until the sidecar is inside the package.
- Sidecar search order: `$SAYIT_SIDECAR_DIR` → `~/.local/share/sayit/sidecar`.
- CI: `npm run build:ci` (`tauri build --no-bundle`) on PRs (Ubuntu 24.04, Node 26). Local GUI package is `npm run build:linux` (`.deb` only). `npm run build:appimage` / `npm run build:rpm` for the other formats. Tag workflow still ships deb+rpm. `beforeBundleCommand` stages `src-tauri/sidecar-bundle/`.
- GUI binary is `sayit-desktop`. CLI remains `sayit`.
- Sidecar search order: `$SAYIT_SIDECAR_DIR` → bundled resources → `~/.local/share/sayit/sidecar`.

## Gotchas

Expand Down
16 changes: 11 additions & 5 deletions LINUX.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ read_clipboard()` ↔ `sayit-clipboard.sh`).
|---|---|
| `~/.config/sayit/token` | API token, 0600 — shared by app, CLI, scripts |
| `~/.config/sayit/settings.json` | port, host, voice, speed, model, unload timeout |
| `~/.local/share/sayit/sidecar/` | installed sidecar (by `scripts/setup-sidecar.sh`) |
| `~/.local/share/sayit/sidecar/` | installed sidecar (by `scripts/setup-sidecar.sh` / `install.sh`) |
| GUI package `$RESOURCE/sidecar/` | sidecar tree inside the `.deb` / `.rpm` (see `spawn_sidecar`) |
| `~/.local/share/sayit/history.json` | last 200 entries, references WAV files |
| `~/.cache/sayit/models/` | HF model cache (passed as `cache_dir` to kokoro-js) |
| `~/.cache/sayit/audio/` | synthesized WAVs (deleted with history entries) |
Expand All @@ -146,14 +147,19 @@ disk. Anything that needs the API should resolve the token the same way.
- `build.rs` + `tauri-build` exist because `tauri::generate_context!()`
requires `OUT_DIR` — removing them breaks the build with a confusing macro
error.
- `beforeDevCommand`/`beforeBuildCommand` run from the **project root**, so
they use `--prefix app`; `frontendDist` is relative to `src-tauri/`, so it
keeps `../app/build`. Mixing these up produces an ENOENT two directories
away from the real problem.
- `beforeDevCommand`/`beforeBuildCommand`/`beforeBundleCommand` run from the
**project root**, so they use `--prefix app` / `scripts/…`; `frontendDist`
is relative to `src-tauri/`, so it keeps `../app/build`. Mixing these up
produces an ENOENT two directories away from the real problem.
- The tray icon has a 1×1 transparent fallback (`Image::new_owned`) because
`default_window_icon()` can be `None` in some bundling configurations.
- CSP in `tauri.conf.json` must keep `connect-src http://127.0.0.1:7878` or
the webview can't reach the sidecar.
- GUI packages (`npm run build:linux`) run `scripts/prepare-sidecar-bundle.sh`
then embed that tree as `bundle.resources` → `sidecar/`. The window binary
is `sayit-desktop` so it never shadows the CLI `sayit`. Spawn order:
`$SAYIT_SIDECAR_DIR` → bundled resources → `~/.local/share/sayit/sidecar`.
If 7878 is already healthy, the GUI does not spawn a second engine.

## 8. Known limitations (vs the original)

Expand Down
Loading
Loading