diff --git a/.github/actions/build-linux/action.yml b/.github/actions/build-linux/action.yml new file mode 100644 index 00000000..ce34df65 --- /dev/null +++ b/.github/actions/build-linux/action.yml @@ -0,0 +1,126 @@ +name: 'Build Linux' +description: 'Builds the Quintodrome desktop app and packages it as a Flatpak and a Snap' +inputs: + arch: + description: 'Architecture name used in artifact names (x86_64 or aarch64)' + required: true + upload-artifact: + description: 'Whether to upload artifacts' + required: false + default: 'true' +runs: + using: 'composite' + steps: + - name: Setup Node + uses: actions/setup-node@v6 + with: + node-version: 24 + cache: npm + cache-dependency-path: ui/package-lock.json + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust build + uses: Swatinem/rust-cache@v2 + with: + workspaces: desktop/src-tauri + + - name: Install Tauri build dependencies + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential file patchelf \ + libwebkit2gtk-4.1-dev libssl-dev librsvg2-dev libxdo-dev + + - name: Install Flatpak build tools + shell: bash + run: | + sudo apt-get install -y flatpak flatpak-builder + flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + + - name: Cache Flatpak runtimes + uses: actions/cache@v5 + with: + path: ~/.local/share/flatpak + key: flatpak-runtimes-${{ runner.os }}-${{ inputs.arch }}-gnome-49 + + - name: Install Snapcraft + shell: bash + run: sudo snap install snapcraft --classic + + - name: Build Navidrome web UI + shell: bash + run: | + cd ui + npm ci --ignore-scripts + npm run build + + - name: Build Navidrome server binary + shell: bash + run: | + GIT_SHA=$(git rev-parse --short HEAD) + if [[ "$GITHUB_REF" == refs/tags/* ]]; then + GIT_TAG="${GITHUB_REF_NAME#v}" + else + GIT_TAG="dev" + fi + + go build \ + -ldflags="-X github.com/navidrome/navidrome/consts.gitSha=$GIT_SHA -X github.com/navidrome/navidrome/consts.gitTag=$GIT_TAG" \ + -tags=netgo,sqlite_fts5 \ + -o navidrome + + # Stage the sidecar under the target-triple name tauri expects. + TRIPLE="$(cd desktop && rustc -vV | sed -n 's/^host: //p')" + mkdir -p desktop/src-tauri/binaries + install -m755 navidrome "desktop/src-tauri/binaries/navidrome-$TRIPLE" + + - name: Build Tauri app (.deb) + # The .deb is only an intermediate: both the Flatpak and Snap repackage it. + shell: bash + run: | + cd desktop + npx --yes @tauri-apps/cli@2 build --bundles deb + cp src-tauri/target/release/bundle/deb/*.deb linux/quintodrome.deb + cp linux/quintodrome.deb linux/snapcraft/quintodrome.deb + + - name: Build Flatpak + shell: bash + run: | + mkdir -p dist + cd desktop/linux + flatpak-builder --user --force-clean --install-deps-from=flathub \ + --repo=flatpak-repo flatpak-build flatpak/com.quintodrome.desktop.yml + flatpak build-bundle \ + --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \ + flatpak-repo "../../dist/Quintodrome-linux-${{ inputs.arch }}.flatpak" com.quintodrome.desktop + + - name: Build Snap + # The runner is Ubuntu 24.04, matching the snap's core24 base, so build + # directly on the host instead of spinning up an LXD container. + shell: bash + run: | + cd desktop/linux/snapcraft + sudo snapcraft pack --destructive-mode \ + --output "../../../dist/Quintodrome-linux-${{ inputs.arch }}.snap" + + - name: List artifacts + shell: bash + run: ls -la dist + + - name: Archive Build Artifacts + if: ${{ inputs.upload-artifact == 'true' }} + uses: actions/upload-artifact@v7 + with: + name: desktop-linux-${{ inputs.arch }} + path: | + dist/*.flatpak + dist/*.snap + retention-days: 7 diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml index 6e7c6f24..0ae85686 100644 --- a/.github/workflows/desktop.yml +++ b/.github/workflows/desktop.yml @@ -1,8 +1,9 @@ name: Desktop Release -# Builds the Quintodrome desktop app (Tauri) for macOS (.app/.dmg) and -# Windows (.exe/.msi), bundling the Navidrome server as a sidecar, and -# attaches the artifacts to the GitHub release on `v*` tags. +# Builds the Quintodrome desktop app (Tauri) for macOS (.app/.dmg), +# Windows (.exe/.msi) and Linux (.flatpak/.snap, x86_64 + aarch64), bundling +# the Navidrome server as a sidecar, and attaches the artifacts to the GitHub +# release on `v*` tags. # # Note: artifacts are unsigned (no Apple/Windows code-signing certs), so users # will hit Gatekeeper/SmartScreen prompts. @@ -141,9 +142,31 @@ jobs: path: dist/* retention-days: 7 + build-linux: + name: Build Linux (${{ matrix.arch }}) + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + arch: x86_64 + - os: ubuntu-24.04-arm + arch: aarch64 + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v6 + + - name: Build + uses: ./.github/actions/build-linux + with: + arch: ${{ matrix.arch }} + upload-artifact: true + release: name: Publish GitHub release - needs: build-desktop + needs: + - build-desktop + - build-linux if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest permissions: diff --git a/.gitignore b/.gitignore index faa0df96..4269407b 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,11 @@ go.work* .worktrees/ .dagger/internal/ .dagger/querybuilder/ +desktop/linux/quintodrome.deb +desktop/linux/snapcraft/quintodrome.deb +desktop/linux/snapcraft/parts/ +desktop/linux/snapcraft/stage/ +desktop/linux/snapcraft/prime/ +desktop/linux/flatpak-build/ +desktop/linux/flatpak-repo/ +desktop/linux/.flatpak-builder/ diff --git a/desktop/linux/flatpak/com.quintodrome.desktop.yml b/desktop/linux/flatpak/com.quintodrome.desktop.yml new file mode 100644 index 00000000..9d420c59 --- /dev/null +++ b/desktop/linux/flatpak/com.quintodrome.desktop.yml @@ -0,0 +1,37 @@ +# Repackages the Tauri-built .deb (staged as ../quintodrome.deb by the CI +# build) into a Flatpak. The GNOME runtime provides webkit2gtk-4.1. +app-id: com.quintodrome.desktop +runtime: org.gnome.Platform +runtime-version: '49' +sdk: org.gnome.Sdk +command: quintodrome +finish-args: + - --share=ipc + - --share=network + - --socket=wayland + - --socket=fallback-x11 + - --socket=pulseaudio + - --device=dri + - --filesystem=xdg-music +modules: + - name: quintodrome + buildsystem: simple + sources: + - type: file + path: ../quintodrome.deb + build-commands: + - ar -x quintodrome.deb + - tar -xf data.tar.* + # Tauri resolves the navidrome sidecar next to its own executable. + - install -Dm755 usr/bin/quintodrome /app/bin/quintodrome + - install -Dm755 usr/bin/navidrome /app/bin/navidrome + - install -Dm644 usr/share/applications/Quintodrome.desktop + /app/share/applications/com.quintodrome.desktop.desktop + - desktop-file-edit --set-icon=com.quintodrome.desktop + /app/share/applications/com.quintodrome.desktop.desktop + - | + for icon in usr/share/icons/hicolor/*x*/apps/quintodrome.png; do + size=$(basename "$(dirname "$(dirname "$icon")")") + case "$size" in *@*) continue ;; esac + install -Dm644 "$icon" "/app/share/icons/hicolor/$size/apps/com.quintodrome.desktop.png" + done diff --git a/desktop/linux/snapcraft/snapcraft.yaml b/desktop/linux/snapcraft/snapcraft.yaml new file mode 100644 index 00000000..69ee7b6c --- /dev/null +++ b/desktop/linux/snapcraft/snapcraft.yaml @@ -0,0 +1,44 @@ +# Repackages the Tauri-built .deb (staged as ./quintodrome.deb by the CI +# build) into a Snap. Built with `snapcraft pack --destructive-mode` on an +# Ubuntu 24.04 host, so the binaries match the core24 base's glibc. +name: quintodrome +base: core24 +adopt-info: quintodrome +summary: Desktop app that hosts the Navidrome music server +description: | + Quintodrome wraps Navidrome in a desktop app: it starts a bundled Navidrome + server and shows its web UI in a native window. +grade: stable +confinement: strict + +# WebKit looks for its helper processes at a compiled-in path. +layout: + /usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.1: + bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.1 + +apps: + quintodrome: + command: usr/bin/quintodrome + desktop: usr/share/applications/Quintodrome.desktop + extensions: [gnome] + environment: + # The snap's $HOME is remapped, so point Navidrome at the real music dir. + QUINTODROME_MUSIC_FOLDER: $SNAP_REAL_HOME/Music + plugs: + - home + - network + - network-bind + - audio-playback + - removable-media + +parts: + quintodrome: + plugin: nil + source: . + stage-packages: + - libwebkit2gtk-4.1-0 + override-build: | + dpkg -x quintodrome.deb "$CRAFT_PART_INSTALL" + craftctl set version="$(dpkg-deb -f quintodrome.deb Version)" + sed -i -e 's|^Icon=.*|Icon=${SNAP}/usr/share/icons/hicolor/128x128/apps/quintodrome.png|' \ + "$CRAFT_PART_INSTALL/usr/share/applications/Quintodrome.desktop"