From 742ad88a296b807c3d74b9bd3c76ea17a9625d81 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Fri, 24 Jul 2026 23:49:50 +0200 Subject: [PATCH] feat(build): cross-platform desktop packaging; bump to 0.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Docker-based packaging for Linux desktop (deb/rpm), Arch (.pkg.tar.zst via makepkg), and Windows. Windows cross-compiles from Linux via the official Tauri path — the x86_64-pc-windows-msvc target driven by cargo-xwin — and produces an NSIS installer (nsis via tauri.conf.json targets, since the CLI rejects --bundles nsis on a Linux host). Verified end to end: builds jellytau.exe + jellytau_x64-setup.exe. Unifies everything on one registry builder image (Dockerfile.builder): Android SDK/NDK, rpm/file, clang(+clang-cl)/lld/llvm/nsis, cargo-xwin and the msvc target. Packaging tools sit in a trailing layer so tool changes rebuild in ~1min instead of ~15. Desktop stages are thin FROM ${BUILDER_IMAGE} layers; Arch uses a separate archlinux image. CLAUDE.md: CI must install no system toolchains — everything lives in the image. Bumps version 0.0.18 -> 0.1.0 (Windows support + webview audio + equalizer). TRACES: UR-003, UR-005 | DR-004 --- CLAUDE.md | 14 +++++ Dockerfile | 31 +++++++++++ Dockerfile.arch | 37 ++++++++++++++ Dockerfile.builder | 34 +++++++++++- docker-compose.yml | 52 +++++++++++++++++++ docs/build-desktop-packages.md | 91 +++++++++++++++++++++++++++++++++ docs/build-windows.md | 78 ++++++++++++++++++++++++++++ package.json | 8 ++- packaging/arch/PKGBUILD | 52 +++++++++++++++++++ packaging/arch/jellytau.desktop | 9 ++++ scripts/build-arch.sh | 36 +++++++++++++ scripts/build-desktop-linux.sh | 44 ++++++++++++++++ scripts/build-windows-cross.sh | 69 +++++++++++++++++++++++++ src-tauri/tauri.conf.json | 4 +- 14 files changed, 555 insertions(+), 4 deletions(-) create mode 100644 Dockerfile.arch create mode 100644 docs/build-desktop-packages.md create mode 100644 docs/build-windows.md create mode 100644 packaging/arch/PKGBUILD create mode 100644 packaging/arch/jellytau.desktop create mode 100755 scripts/build-arch.sh create mode 100755 scripts/build-desktop-linux.sh create mode 100755 scripts/build-windows-cross.sh diff --git a/CLAUDE.md b/CLAUDE.md index 13b5b6cc..c951e393 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,6 +35,20 @@ CI runs on **Gitea Actions** (`.gitea/workflows/`), not GitHub. Use the `gh` CLI only against the mirror if one exists; the canonical remote is `gitea.tourolle.paris`. +> **🔴 CI installs no system tools.** Never add an `apt-get`, `rustup`, +> `sdkmanager`, mingw/nsis, or any other *toolchain/system-package* install to a +> CI workflow step. Every build, test, and packaging **tool** must already live +> in the Docker image the job runs in — the unified builder (`Dockerfile.builder` +> → `gitea.tourolle.paris/dtourolle/jellytau-builder`) for Android/Linux/Windows, +> or `Dockerfile.arch` for Arch. If a job needs a tool the image lacks, **add it +> to the image, rebuild + push it** (`scripts/build-builder-image.sh`), and use +> it from CI — do not install it at job time. This keeps builds reproducible and +> fast, and is why the packaging stages are thin `FROM ${BUILDER_IMAGE}` layers. +> +> `bun install` (fetching the project's own JS deps per the lockfile) is **not** +> a violation — that's project dependencies, not a toolchain. The rule is about +> system tools, not npm/bun/cargo *packages* declared by the project. + ## Before Committing - Frontend: `bun run check` and `bun run test` must pass. diff --git a/Dockerfile b/Dockerfile index c39b1c36..208a561b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,11 @@ # Multi-stage build for JellyTau - Tauri Jellyfin client +# +# The desktop packaging stages (desktop-linux-build, windows-cross) build FROM +# the unified registry builder image, which carries every packaging tool. Declared +# here (before the first FROM) so it's in scope for those stages' FROM lines. +# Override for local iteration: --build-arg BUILDER_IMAGE=jellytau-builder:latest +ARG BUILDER_IMAGE=gitea.tourolle.paris/dtourolle/jellytau-builder:latest + FROM ubuntu:24.04 AS builder ENV DEBIAN_FRONTEND=noninteractive \ @@ -108,6 +115,30 @@ RUN cd src-tauri && cargo fetch && cd .. && \ bun run tauri android build --apk true && \ echo "APK build complete!" +# Desktop packaging stages build FROM the unified registry builder image (see the +# BUILDER_IMAGE ARG at the top), which already carries every packaging tool +# (rpm/file for Linux, mingw-w64 + nsis + the x86_64-pc-windows-gnu rust target +# for Windows). ONE source of dependency truth, shared with CI — no per-stage +# apt/rustup here. + +# Linux desktop packaging environment (deb + rpm; Arch is Dockerfile.arch). +# Thin layer over the builder — the actual build runs at container-run time on +# the bind-mounted source (see docker-compose.yml / scripts/build-desktop-linux.sh), +# matching the `dev` service model. Run standalone with: +# docker run --rm -v "$PWD:/app" -v "$PWD/dist:/app/dist" \ +# bash -c "OUTPUT_DIR=/app/dist scripts/build-desktop-linux.sh" +FROM ${BUILDER_IMAGE} AS desktop-linux-build +WORKDIR /app +CMD ["bash", "-c", "OUTPUT_DIR=/app/dist scripts/build-desktop-linux.sh"] + +# Windows cross-compile environment (MSVC target via cargo-xwin). Video works via +# WebView2 and audio via the webview