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)')"
|
if: "!startsWith(github.event.head_commit.message, 'chore(release)')"
|
||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
@@ -187,7 +187,7 @@ jobs:
|
|||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
needs: test
|
needs: test
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
env:
|
env:
|
||||||
ANDROID_HOME: /opt/android-sdk
|
ANDROID_HOME: /opt/android-sdk
|
||||||
ANDROID_SDK_ROOT: /opt/android-sdk
|
ANDROID_SDK_ROOT: /opt/android-sdk
|
||||||
@@ -256,7 +256,7 @@ jobs:
|
|||||||
name: Supply Chain
|
name: Supply Chain
|
||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
name: Run Tests
|
name: Run Tests
|
||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -94,7 +94,7 @@ jobs:
|
|||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
needs: test
|
needs: test
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -190,12 +190,15 @@ jobs:
|
|||||||
# Without nullglob an unmatched pattern stays literal, so test each
|
# Without nullglob an unmatched pattern stays literal, so test each
|
||||||
# candidate instead. Same POSIX-only rule as traceability-check.yml.
|
# candidate instead. Same POSIX-only rule as traceability-check.yml.
|
||||||
#
|
#
|
||||||
# The .AppImage.tar.gz + .sig pair is what the updater downloads and
|
# Tauri v2 signs the .AppImage ITSELF and writes <name>.AppImage.sig
|
||||||
# verifies; the plain .AppImage is what a human downloads. Both ship.
|
# 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 \
|
for bundle in \
|
||||||
src-tauri/target/release/bundle/appimage/*.AppImage \
|
src-tauri/target/release/bundle/appimage/*.AppImage \
|
||||||
src-tauri/target/release/bundle/appimage/*.AppImage.tar.gz \
|
src-tauri/target/release/bundle/appimage/*.AppImage.sig \
|
||||||
src-tauri/target/release/bundle/appimage/*.AppImage.tar.gz.sig \
|
|
||||||
src-tauri/target/release/bundle/deb/*.deb \
|
src-tauri/target/release/bundle/deb/*.deb \
|
||||||
src-tauri/target/release/bundle/rpm/*.rpm; do
|
src-tauri/target/release/bundle/rpm/*.rpm; do
|
||||||
[ -e "$bundle" ] || continue
|
[ -e "$bundle" ] || continue
|
||||||
@@ -232,7 +235,7 @@ jobs:
|
|||||||
# baked into the builder image. No toolchain installs here — the image has
|
# baked into the builder image. No toolchain installs here — the image has
|
||||||
# cargo-xwin, clang/clang-cl, lld, llvm, nsis and the msvc target.
|
# cargo-xwin, clang/clang-cl, lld, llvm, nsis and the msvc target.
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -305,7 +308,7 @@ jobs:
|
|||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
needs: test
|
needs: test
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
env:
|
env:
|
||||||
ANDROID_HOME: /opt/android-sdk
|
ANDROID_HOME: /opt/android-sdk
|
||||||
ANDROID_SDK_ROOT: /opt/android-sdk
|
ANDROID_SDK_ROOT: /opt/android-sdk
|
||||||
@@ -408,7 +411,7 @@ jobs:
|
|||||||
needs: [build-linux, build-windows, build-android]
|
needs: [build-linux, build-windows, build-android]
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -499,8 +502,13 @@ jobs:
|
|||||||
APPIMAGE_URL=""
|
APPIMAGE_URL=""
|
||||||
NSIS_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
|
[ -e "$f" ] || continue
|
||||||
|
case "$f" in *.sig) continue;; esac
|
||||||
APPIMAGE_URL="${BASE}/$(basename "$f")"
|
APPIMAGE_URL="${BASE}/$(basename "$f")"
|
||||||
[ -e "$f.sig" ] && APPIMAGE_SIG="$(cat "$f.sig")"
|
[ -e "$f.sig" ] && APPIMAGE_SIG="$(cat "$f.sig")"
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
name: Build & publish docs to gitea-pages
|
name: Build & publish docs to gitea-pages
|
||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
runs-on: linux/amd64
|
runs-on: linux/amd64
|
||||||
name: Check Requirement Traces
|
name: Check Requirement Traces
|
||||||
container:
|
container:
|
||||||
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08
|
image: gitea.tourolle.paris/dtourolle/jellytau-builder:2026.08.1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- 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
|
For how long each fixed defect had been shipping before it was found, see
|
||||||
[docs/defect-windows.md](docs/defect-windows.md).
|
[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
|
## v0.9.1
|
||||||
|
|
||||||
A one-line fix to the home screen, released on its own because it is the kind of
|
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 \
|
lld \
|
||||||
llvm \
|
llvm \
|
||||||
nsis \
|
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/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
# Ubuntu's clang package ships clang but NOT the clang-cl alias that cc-rs
|
# 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,
|
# 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.
|
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
|
```bash
|
||||||
# 1. Edit Dockerfile.builder. Put new tools in the TRAILING layer: it exists so
|
# 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.
|
# 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
|
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.
|
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
|
## Secrets
|
||||||
|
|
||||||
Managed with the `tea` CLI (`tea actions secrets list`) or the repo settings UI.
|
Managed with the `tea` CLI (`tea actions secrets list`) or the repo settings UI.
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jellytau",
|
"name": "jellytau",
|
||||||
"version": "0.9.1",
|
"version": "0.10.0",
|
||||||
"description": "A cross-platform Jellyfin client built with Tauri, SvelteKit and Rust.",
|
"description": "A cross-platform Jellyfin client built with Tauri, SvelteKit and Rust.",
|
||||||
"author": "Duncan Tourolle <duncan@tourolle.paris>",
|
"author": "Duncan Tourolle <duncan@tourolle.paris>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
# tarball/VCS URL and drop the local-copy prepare() step.
|
# tarball/VCS URL and drop the local-copy prepare() step.
|
||||||
|
|
||||||
pkgname=jellytau
|
pkgname=jellytau
|
||||||
pkgver=0.9.1
|
pkgver=0.10.0
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="A cross-platform Jellyfin client"
|
pkgdesc="A cross-platform Jellyfin client"
|
||||||
arch=('x86_64')
|
arch=('x86_64')
|
||||||
|
|||||||
Generated
+1
-1
@@ -2181,7 +2181,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jellytau"
|
name = "jellytau"
|
||||||
version = "0.9.1"
|
version = "0.10.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jellytau"
|
name = "jellytau"
|
||||||
version = "0.9.1"
|
version = "0.10.0"
|
||||||
description = "A cross-platform Jellyfin client"
|
description = "A cross-platform Jellyfin client"
|
||||||
authors = ["Duncan Tourolle <duncan@tourolle.paris>"]
|
authors = ["Duncan Tourolle <duncan@tourolle.paris>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "JellyTau",
|
"productName": "JellyTau",
|
||||||
"version": "0.9.1",
|
"version": "0.10.0",
|
||||||
"identifier": "com.dtourolle.jellytau",
|
"identifier": "com.dtourolle.jellytau",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "bun run dev",
|
"beforeDevCommand": "bun run dev",
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
},
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": true,
|
"active": true,
|
||||||
|
"createUpdaterArtifacts": true,
|
||||||
"targets": [
|
"targets": [
|
||||||
"deb",
|
"deb",
|
||||||
"rpm",
|
"rpm",
|
||||||
|
|||||||
Reference in New Issue
Block a user