diff --git a/.forgejo/workflows/desktop.yml b/.forgejo/workflows/desktop.yml new file mode 100644 index 0000000..0c6d9f6 --- /dev/null +++ b/.forgejo/workflows/desktop.yml @@ -0,0 +1,68 @@ +# Tauri desktop (Linux) build — SEPARATE from ci.yml on purpose: this is a heavy +# Rust + AppImage build (~20-40 min) that should NOT run on backend/frontend-only +# pushes. Scoped to desktop/** (+ this file). Produces the .deb and .AppImage. +# +# Toolchain comes from the ci-tauri image (Rust + Node + WebKitGTK 4.1 + tauri-cli); +# runs-on is just a registered scheduling label (Label Model B), not a per-purpose +# runner. The frontend is built here because tauri's generate_context! embeds it. +name: Desktop (Tauri) + +on: + push: + branches: [dev, main] + tags: ["v*"] + paths: + - "desktop/**" + - ".forgejo/workflows/desktop.yml" + workflow_dispatch: + +concurrency: + group: desktop-${{ github.ref }} + cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }} + +permissions: + contents: read + +jobs: + build: + name: Tauri desktop (Linux) + if: github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') + runs-on: python-ci + container: + image: git.fabledsword.com/bvandeusen/ci-tauri:1.97 + env: + # AppImage tooling (linuxdeploy) FUSE-mounts itself by default; CI containers + # have no /dev/fuse, so tell it to extract-and-run instead. Without this the + # AppImage bundle step fails with a FUSE error. + APPIMAGE_EXTRACT_AND_RUN: "1" + steps: + - uses: actions/checkout@v6 + + # tauri's generate_context! embeds the built frontend at compile time, so the + # frontend must exist before any cargo compile (clippy/test/build), not just + # at bundle time. + - name: Build the shared frontend + run: npm ci && npm run build + working-directory: frontend + + # Generate the platform icon set from the committed 1024px source PNG. + - name: Generate app icons + run: cargo tauri icon app-icon.png + working-directory: desktop/src-tauri + + - name: Rust format check + run: cargo fmt --check + working-directory: desktop/src-tauri + + - name: Clippy + run: cargo clippy --all-targets -- -D warnings + working-directory: desktop/src-tauri + + - name: Test + run: cargo test + working-directory: desktop/src-tauri + + # Frontend already built above; skip the beforeBuildCommand rebuild. + - name: Tauri build (deb + AppImage) + run: cargo tauri build --config '{"build":{"beforeBuildCommand":""}}' + working-directory: desktop/src-tauri diff --git a/ci-requirements.md b/ci-requirements.md index cdc4a94..641d06d 100644 --- a/ci-requirements.md +++ b/ci-requirements.md @@ -45,3 +45,22 @@ entirely on `ci-python:3.14`. (family rule 46). - The production runtime `Dockerfile` tracks python:3.12 so test results stay representative of the deployed image. + +## Desktop (Tauri) lane — separate workflow + +The Tauri desktop client (`desktop/`) builds in its own workflow, +`.forgejo/workflows/desktop.yml`, NOT in `ci.yml` — it's a heavy Rust + AppImage +build (~20–40 min) that should only run on `desktop/**` changes, not on every +backend/frontend push. + +- **Image:** `git.fabledsword.com/bvandeusen/ci-tauri:1.97` (Rust + Node + + WebKitGTK 4.1 + Tauri v2 Linux deps + `tauri-cli`). Selected via + `container.image`; `runs-on: python-ci` is only a scheduling label. +- **Steps:** build the shared frontend (embedded by `generate_context!`) → + `cargo tauri icon app-icon.png` (platform icon set from the committed 1024px + source) → `cargo fmt --check` → `cargo clippy -D warnings` → `cargo test` → + `cargo tauri build` (produces `.deb` + `.AppImage`). +- **`APPIMAGE_EXTRACT_AND_RUN=1`** is set: AppImage tooling FUSE-mounts by default + and CI containers have no `/dev/fuse`. +- No Postgres lane (unchanged): the desktop app's local store + sync behavior is + verified on the operator's machine, not in CI. diff --git a/desktop/src-tauri/app-icon.png b/desktop/src-tauri/app-icon.png new file mode 100644 index 0000000..d62b0a8 Binary files /dev/null and b/desktop/src-tauri/app-icon.png differ