# storebound desktop: Linux (AppImage + deb) and Windows (NSIS, per user, unsigned) installers. # macOS is built, signed and notarized on the owner's Mac (tools/desktop-release.ts mac); the updater signing key # never reaches a runner: the Mac signs these installers after downloading them (tools/desktop-release.ts add). # Runner setup (Forgejo runners on the VDS: Linux in Docker, Windows in a KVM VM): docs/desktop-release.md. # Publishes nothing: the installers are workflow artifacts only (14 days); `tools/desktop-release.ts add` on the Mac # signs and stages them, and only `publish` puts anything on storebound.dev. name: desktop on: workflow_dispatch: inputs: windows: description: Build Windows too (needs a runner with the "windows" label) type: boolean default: false push: tags: ['desktop-v*'] env: BUN_VERSION: '1.4.0' # the path-free build keeps the target folder outside every home folder CARGO_TARGET_DIR: /tmp/storebound-target CARGO_TERM_COLOR: never jobs: linux: # runner label: ubuntu-22.04:docker://ghcr.io/catthehacker/ubuntu:act-22.04 (glibc 2.35: the AppImage and the # deb then run on Ubuntu 22.04 and newer, Debian 12) runs-on: ubuntu-22.04 timeout-minutes: 90 env: # linuxdeploy (AppImage) runs without FUSE inside the container APPIMAGE_EXTRACT_AND_RUN: '1' # linuxdeploy must not strip: the storebound sidecar is a `bun build --compile` executable whose JS payload strip # removes (it then starts as plain bun). The Rust binary is already stripped by Cargo (profile.release strip). NO_STRIP: '1' # WebKitGTK's DMABUF renderer leaves the window blank on some GPU / VM setups; the app sets this itself at # start (src-tauri/src/lib.rs linux_webkit_env) unless the user did; set here too for anything run in CI WEBKIT_DISABLE_DMABUF_RENDERER: '1' steps: - uses: actions/checkout@v4 - name: System packages run: | sudo apt-get update -qq sudo apt-get install -y -qq --no-install-recommends libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev \ librsvg2-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev libssl-dev libxdo-dev patchelf file build-essential \ curl unzip squashfs-tools p7zip-full xz-utils >/dev/null - uses: actions/cache@v4 with: path: | ~/.bun/install/cache ~/.cargo/registry/index ~/.cargo/registry/cache ~/.cargo/git/db key: desktop-${{ runner.os }}-${{ hashFiles('bun.lock', 'apps/desktop/src-tauri/Cargo.lock') }} restore-keys: desktop-${{ runner.os }}- - name: Bun and Rust run: | P="${FORGEJO_PATH:-$GITHUB_PATH}" curl -fsSL https://bun.sh/install | bash -s "bun-v${BUN_VERSION}" >/dev/null echo "$HOME/.bun/bin" >> "$P" command -v rustup || curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal echo "$HOME/.cargo/bin" >> "$P" - name: Install and check run: | bun install --frozen-lockfile bun tools/desktop-version.ts bun tools/build-sidecars.ts --target bun-linux-x64 # linuxdeploy (AppImage) sets the rpath of every executable with its own patchelf, which corrupts the bun # sidecar (segfault, then ldd fails in the gtk plugin). With the rpath already set (Ubuntu's patchelf, which # keeps it working), linuxdeploy leaves the file as it is. The sidecar needs only libc, so the rpath is inert. patchelf --set-rpath '$ORIGIN/../lib' apps/desktop/src-tauri/binaries/storebound-x86_64-unknown-linux-gnu apps/desktop/src-tauri/binaries/storebound-x86_64-unknown-linux-gnu version - name: Build AppImage and deb (path-free) working-directory: apps/desktop run: bun ../../tools/desktop-release.ts exec -- bunx tauri build --bundles appimage,deb --ci - name: Self-test the exact artifacts run: | V=$(bun tools/desktop-version.ts --print) B="$CARGO_TARGET_DIR/release/bundle" mkdir -p out && cp "$B/appimage/storebound_${V}_amd64.AppImage" "$B/deb/storebound_${V}_amd64.deb" out/ chmod +x out/*.AppImage (cd /tmp && rm -rf squashfs-root && "$GITHUB_WORKSPACE/out/storebound_${V}_amd64.AppImage" --appimage-extract >/dev/null && squashfs-root/usr/bin/storebound-desktop --self-test) rm -rf /tmp/deb && dpkg-deb -x "out/storebound_${V}_amd64.deb" /tmp/deb && /tmp/deb/usr/bin/storebound-desktop --self-test dpkg-deb -I "out/storebound_${V}_amd64.deb" | sed -n '1,20p' - name: Start the app under Xvfb (AppImage and deb) # --self-test checks only the sidecar; this opens the real window (GTK, WebKitGTK, the bundled libraries of the # AppImage) on a virtual display. "sidecar started" in host.log means the webview ran the UI and called the host. run: | sudo apt-get install -y -qq --no-install-recommends xvfb xauth dbus-x11 >/dev/null V=$(bun tools/desktop-version.ts --print) smoke() { #