Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c75e74ea3 | ||
|
|
76a2d9609b | ||
|
|
30a9cb32f5 | ||
|
|
88260ab6c9 |
@@ -28,7 +28,7 @@ jobs:
|
||||
if: "!startsWith(github.event.head_commit.message, 'chore(release)')"
|
||||
runs-on: linux/amd64
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -187,7 +187,7 @@ jobs:
|
||||
runs-on: linux/amd64
|
||||
needs: test
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
env:
|
||||
ANDROID_HOME: /opt/android-sdk
|
||||
ANDROID_SDK_ROOT: /opt/android-sdk
|
||||
@@ -256,7 +256,7 @@ jobs:
|
||||
name: Supply Chain
|
||||
runs-on: linux/amd64
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
name: Run Tests
|
||||
runs-on: linux/amd64
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
runs-on: linux/amd64
|
||||
needs: test
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -190,12 +190,15 @@ jobs:
|
||||
# Without nullglob an unmatched pattern stays literal, so test each
|
||||
# candidate instead. Same POSIX-only rule as traceability-check.yml.
|
||||
#
|
||||
# The .AppImage.tar.gz + .sig pair is what the updater downloads and
|
||||
# verifies; the plain .AppImage is what a human downloads. Both ship.
|
||||
# Tauri v2 signs the .AppImage ITSELF and writes <name>.AppImage.sig
|
||||
# beside it -- there is no .AppImage.tar.gz unless
|
||||
# bundle.createUpdaterArtifacts is set to "v1Compatible". The updater
|
||||
# downloads the same AppImage a human does and verifies that .sig, so
|
||||
# both files must ship or the manifest points at a signature nobody
|
||||
# can fetch.
|
||||
for bundle in \
|
||||
src-tauri/target/release/bundle/appimage/*.AppImage \
|
||||
src-tauri/target/release/bundle/appimage/*.AppImage.tar.gz \
|
||||
src-tauri/target/release/bundle/appimage/*.AppImage.tar.gz.sig \
|
||||
src-tauri/target/release/bundle/appimage/*.AppImage.sig \
|
||||
src-tauri/target/release/bundle/deb/*.deb \
|
||||
src-tauri/target/release/bundle/rpm/*.rpm; do
|
||||
[ -e "$bundle" ] || continue
|
||||
@@ -232,7 +235,7 @@ jobs:
|
||||
# baked into the builder image. No toolchain installs here — the image has
|
||||
# cargo-xwin, clang/clang-cl, lld, llvm, nsis and the msvc target.
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -305,7 +308,7 @@ jobs:
|
||||
runs-on: linux/amd64
|
||||
needs: test
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
env:
|
||||
ANDROID_HOME: /opt/android-sdk
|
||||
ANDROID_SDK_ROOT: /opt/android-sdk
|
||||
@@ -408,7 +411,7 @@ jobs:
|
||||
needs: [build-linux, build-windows, build-android]
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -499,8 +502,13 @@ jobs:
|
||||
APPIMAGE_URL=""
|
||||
NSIS_URL=""
|
||||
|
||||
for f in artifacts/linux/*.AppImage.tar.gz; do
|
||||
# Tauri v2 signs the AppImage itself; <name>.AppImage.sig sits beside
|
||||
# it. Verified against a real signed build before tagging -- the
|
||||
# v1-style .AppImage.tar.gz is never produced with
|
||||
# createUpdaterArtifacts: true.
|
||||
for f in artifacts/linux/*.AppImage; do
|
||||
[ -e "$f" ] || continue
|
||||
case "$f" in *.sig) continue;; esac
|
||||
APPIMAGE_URL="${BASE}/$(basename "$f")"
|
||||
[ -e "$f.sig" ] && APPIMAGE_SIG="$(cat "$f.sig")"
|
||||
done
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
name: Build & publish docs to gitea-pages
|
||||
runs-on: linux/amd64
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: linux/amd64
|
||||
name: Check Requirement Traces
|
||||
container:
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
||||
@@ -9,6 +9,105 @@ generated trace matrix lives in [docs/traceability.md](docs/traceability.md).
|
||||
For how long each fixed defect had been shipping before it was found, see
|
||||
[docs/defect-windows.md](docs/defect-windows.md).
|
||||
|
||||
## v0.10.0
|
||||
|
||||
Two things you can see, and a great deal of work on how this project builds and
|
||||
ships itself. The app can now update itself, and it can tell you what it did
|
||||
when something goes wrong — both of which existed as gaps rather than as bugs,
|
||||
which is why they lasted so long.
|
||||
|
||||
### ✨ Changes
|
||||
|
||||
- **JellyTau can update itself.** Anyone who installed an AppImage or ran the
|
||||
Windows installer was frozen on that version permanently: nothing in the app
|
||||
ever mentioned that a newer one existed, and the release page was the only
|
||||
announcement. Settings → Updates now checks, shows what changed, and installs
|
||||
and restarts on request. Each download is verified against JellyTau's signing
|
||||
key before anything is installed, so a substituted file is refused rather than
|
||||
run. Android is deliberately not wired to this — an app may not replace its own
|
||||
APK, that is the system installer's job — and is given a link to the releases
|
||||
page instead of a button that would fail. (UR-077 → DR-217)
|
||||
|
||||
- **You can export a diagnostics bundle.** Until now the app forgot everything it
|
||||
had done the moment it closed. Logs went to standard output, which nobody sees
|
||||
when launching from a desktop icon, and on Android went nowhere at all — so the
|
||||
backend was invisible on the platform where the hardest playback bugs live. A
|
||||
crash left nothing behind. Logs are now kept in a size-capped file that
|
||||
survives a restart, a crash is recorded before the app dies, and Settings →
|
||||
Diagnostics exports the lot as one file to attach to a bug report. Access
|
||||
tokens and passwords are stripped before anything is written to disk, not
|
||||
merely before it is exported. Nothing is transmitted anywhere; you attach the
|
||||
file yourself. (UR-078 → DR-218)
|
||||
|
||||
- **Linux gets an AppImage again.** The release notes have advertised one for
|
||||
months while the build never produced it — the packaging step looked for the
|
||||
file, found nothing, and said nothing. (DR-217)
|
||||
|
||||
### 🐛 Fixes
|
||||
|
||||
- **Releases no longer ship every Windows installer ever built.** Every release
|
||||
from v0.1.0 to v0.8.2 carried its predecessors': sixteen installers on v0.8.2,
|
||||
thirteen of them stale, and a download list on v0.5.0 reaching back to 0.1.0.
|
||||
The build directory is never cleaned and the build machine reuses it, so each
|
||||
release collected whatever was left behind. It went unnoticed for eight months
|
||||
because nothing looked wrong — the files were real and the page merely looked
|
||||
busy. The stale files have been removed from the published releases, the build
|
||||
now clears that directory first, and a check refuses to publish a release
|
||||
containing an artifact from a different version. (DR-220)
|
||||
|
||||
- **Release notes now say what changed.** All 35 previous releases published the
|
||||
same block of generic install instructions, whose "What's New" section was a
|
||||
link to a file that does not resolve from a release page. Every release page
|
||||
now carries its own entry from this changelog, and the past ones have been
|
||||
filled in. (DR-219)
|
||||
|
||||
### 🔒 Security and supply chain
|
||||
|
||||
- **Dependencies are now checked against a vulnerability database on every
|
||||
build.** They never had been. The first run found eight vulnerabilities and one
|
||||
unsoundness in the Rust dependency graph — all of them fixed by an update
|
||||
nobody had a reason to run. Licences are checked against an allow-list too, so
|
||||
nothing gets redistributed inside a release that does not permit it.
|
||||
(DR-216)
|
||||
|
||||
- **Every release publishes checksums and a bill of materials.** `SHA256SUMS`
|
||||
lets you verify a download (`sha256sum -c SHA256SUMS`); the SBOM lists what
|
||||
went into the build, so "does this release contain <vulnerable library>?" has
|
||||
an answer that is not "rebuild it and find out". (DR-216)
|
||||
|
||||
- **Builds are reproducible again.** Every CI job named a container image tag
|
||||
that was rewritten in place, so rebuilding an old release did not necessarily
|
||||
rebuild the same thing. Jobs now pin an immutable tag. The one dependency that
|
||||
comes from a git branch rather than a package registry is pinned to an exact
|
||||
revision, closing a path by which new upstream code could arrive unreviewed in
|
||||
a library linked into the player. (DR-216)
|
||||
|
||||
### 🧹 Under the hood
|
||||
|
||||
- Formatting, linting and type-checking now run in CI. All three were configured
|
||||
and enforced by nothing: 199 files did not match the project's own formatter, a
|
||||
type error could sit on the main branch until somebody cut a release, and the
|
||||
test-coverage command had been broken for months by a dependency mismatch.
|
||||
Coverage now has a floor that only moves up. (DR-215)
|
||||
|
||||
- The traceability matrix counts requirements implemented by configuration.
|
||||
Several carried the necessary annotations and were being counted as uncovered
|
||||
because the extraction tool only read source files. (DR-215)
|
||||
|
||||
- The project now has a security policy, contribution guide, code of conduct,
|
||||
issue and pull-request templates, and an operations document covering the
|
||||
builder image, the release secrets, and what losing the signing key would mean.
|
||||
|
||||
- The app framework moved from Tauri 2.9.5 to 2.11.5. Nothing about this is
|
||||
visible in use, but it is worth recording that it did not go quietly: the
|
||||
windowing layer beneath Tauri quietly stopped publishing the Android JavaVM
|
||||
and application handle that this app's credential storage had been reading for
|
||||
its whole life. Nothing here had changed; a side effect several dependencies
|
||||
down had simply gone away, and the app aborted on launch on every Android
|
||||
device. JellyTau now sets that handle itself rather than relying on someone
|
||||
else to do it. Caught by installing on a real tablet before release — no test
|
||||
suite runs the app. (UR-012 → DR-223)
|
||||
|
||||
## v0.9.1
|
||||
|
||||
A one-line fix to the home screen, released on its own because it is the kind of
|
||||
|
||||
@@ -141,6 +141,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
lld \
|
||||
llvm \
|
||||
nsis \
|
||||
# AppImage bundling. linuxdeploy embeds xdg-open into the AppImage and
|
||||
# aborts the whole bundle if it is missing:
|
||||
# failed to bundle project: xdg-open binary not found
|
||||
# It is present on most desktop distros, which is why the AppImage built on
|
||||
# a developer machine and failed here. desktop-file-utils and zsync are the
|
||||
# other two linuxdeploy commonly wants (desktop-file-validate, and zsync for
|
||||
# delta updates), added together so a missing one does not cost another
|
||||
# image rebuild and another failed release build.
|
||||
xdg-utils \
|
||||
desktop-file-utils \
|
||||
zsync \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
# Ubuntu's clang package ships clang but NOT the clang-cl alias that cc-rs
|
||||
# invokes for MSVC targets. clang-cl is the same binary in MSVC-compat mode,
|
||||
|
||||
Vendored
+24
@@ -61,6 +61,11 @@ filled. Keep a couple of dated tags live and prune the rest.
|
||||
|
||||
The order matters — CI breaks if the workflow lands before the image exists.
|
||||
|
||||
A caveat learned the hard way: the *trailing* layer is only fast for `cargo
|
||||
install` tools. Adding an **apt** package invalidates the packaging layer, which
|
||||
sits above the `cargo-xwin`/`cargo-deny` installs, so those recompile too — a
|
||||
~20 minute rebuild rather than ~2.
|
||||
|
||||
```bash
|
||||
# 1. Edit Dockerfile.builder. Put new tools in the TRAILING layer: it exists so
|
||||
# a tool change is a ~2 min rebuild instead of ~15.
|
||||
@@ -103,6 +108,25 @@ transitive upgrade (bumping `tauri-plugin-log` to 2.9.0 also moved `wry`,
|
||||
therefore video playback. That is a change to make deliberately, with a full
|
||||
build and a playback check — not one to slip into a release.
|
||||
|
||||
## AppImage needs more than the Rust toolchain
|
||||
|
||||
`linuxdeploy` (which Tauri downloads at build time to assemble the AppImage)
|
||||
shells out to distro tools that a minimal server image does not have. It aborts
|
||||
the whole bundle on the first one missing:
|
||||
|
||||
```
|
||||
failed to bundle project: xdg-open binary not found
|
||||
```
|
||||
|
||||
The image therefore carries `xdg-utils`, `desktop-file-utils` and `zsync`. This
|
||||
is a class of failure that **cannot be caught by building locally**: a developer
|
||||
machine is a desktop and has all three, so the AppImage builds there and fails in
|
||||
CI. It cost one release build to find.
|
||||
|
||||
Tauri's AppImage bundler also downloads `linuxdeploy`, `AppRun` and two plugin
|
||||
scripts from GitHub during the build. That is Tauri's behaviour, not ours, but it
|
||||
means an AppImage build depends on GitHub being reachable from the runner.
|
||||
|
||||
## Secrets
|
||||
|
||||
Managed with the `tea` CLI (`tea actions secrets list`) or the repo settings UI.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jellytau",
|
||||
"version": "0.9.1",
|
||||
"version": "0.10.0",
|
||||
"description": "A cross-platform Jellyfin client built with Tauri, SvelteKit and Rust.",
|
||||
"author": "Duncan Tourolle <duncan@tourolle.paris>",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# tarball/VCS URL and drop the local-copy prepare() step.
|
||||
|
||||
pkgname=jellytau
|
||||
pkgver=0.9.1
|
||||
pkgver=0.10.0
|
||||
pkgrel=1
|
||||
pkgdesc="A cross-platform Jellyfin client"
|
||||
arch=('x86_64')
|
||||
|
||||
Generated
+1
-1
@@ -2181,7 +2181,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jellytau"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"async-trait",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "jellytau"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
description = "A cross-platform Jellyfin client"
|
||||
authors = ["Duncan Tourolle <duncan@tourolle.paris>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "JellyTau",
|
||||
"version": "0.9.1",
|
||||
"version": "0.10.0",
|
||||
"identifier": "com.dtourolle.jellytau",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run dev",
|
||||
@@ -44,6 +44,7 @@
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"createUpdaterArtifacts": true,
|
||||
"targets": [
|
||||
"deb",
|
||||
"rpm",
|
||||
|
||||
Reference in New Issue
Block a user