Files
jellytau/package.json
T
dtourolle 3211c96ecf feat(updater): in-app update on desktop, releases link on Android
Anyone who installed an AppImage or ran the Windows installer was frozen
on that version forever. Nothing in the app ever mentioned a new release
existed, and the release notes were the only announcement.

Desktop now checks a signed manifest, shows the version and its notes in
Settings, and installs and relaunches on request. The signature check is
the whole point: it is what stops a substituted download from being
installed by the app itself. Windows binaries stay unsigned for
SmartScreen purposes -- that is a code-signing certificate, a separate
problem -- but the update payload is verified against our own key.

Android is deliberately not wired to the updater. An app may not replace
its own APK; that is the package installer's job, and the plugin has no
Android implementation. It gets a link to the releases page instead of a
button that would throw.

The plugins are gated with a target-triple cfg rather than
cfg(desktop). Cargo only evaluates target cfgs in a [target.'cfg(..)']
table, so cfg(desktop) matches nothing, silently drops the dependency,
and fails much later with "Permission updater:default not found" -- which
is exactly what the first attempt here did.

Where the manifest lives took some finding. This Gitea serves
/releases/download/<tag>/<asset> but 404s on
/releases/latest/download/<asset> (verified against a real asset), so
there is no stable latest-release URL. The gitea-pages branch is
force-pushed wholesale by publish-docs.yml, so it cannot host the file
either. latest.json therefore gets its own orphan branch, read over the
raw-file URL, and is published from a scratch repo in RUNNER_TEMP rather
than by switching branches in the checkout -- doing that would have left
the following steps standing on a one-commit history, and the next step
but one runs release:notes against the real commit range.

Also fixed, all of it release-integrity:

  - "appimage" is in bundle.targets. The release notes have advertised an
    AppImage for months; tauri.conf.json never built one, the artifact
    step globbed for *.AppImage, found nothing, and said nothing. The
    step now fails instead.
  - The .AppImage.tar.gz/.sig pair and the NSIS .sig are collected. A
    manifest referencing a signature that was never uploaded fails only
    on the user's machine, so the manifest step also refuses to write an
    entry with an empty signature.
  - Release notes are generated by release:notes from the traceability
    graph, which is what CLAUDE.md has asked for all along, instead of a
    fixed heredoc that said "see CHANGELOG.md for detailed changes" and
    linked "GitHub Issues" on a Gitea-hosted project.
  - The notes tell users how to verify a download with SHA256SUMS.

Requirements UR-077 / DR-217, tests UT-208 (12 cases over the version
comparison and the platform decision, including that a pre-release does
not offer itself as an upgrade to the matching release).

Verified: 1070 frontend tests, cargo check for both the host and
aarch64-linux-android (confirming the plugins are absent there), clippy
-D warnings, svelte-check 0 errors.
2026-08-21 18:41:50 +02:00

93 lines
3.6 KiB
JSON

{
"name": "jellytau",
"version": "0.9.1",
"description": "A cross-platform Jellyfin client built with Tauri, SvelteKit and Rust.",
"author": "Duncan Tourolle <duncan@tourolle.paris>",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://gitea.tourolle.paris/dtourolle/jellytau"
},
"private": true,
"type": "module",
"packageManager": "bun@1.3.5",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test": "vitest run",
"test:watch": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest run --coverage",
"test:all": "./scripts/test-all.sh",
"test:rust": "./scripts/test-rust.sh",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"check:boundary": "bash scripts/check-frontend-boundary.sh",
"check:links": "bash scripts/check-doc-links.sh",
"hooks:install": "./scripts/install-hooks.sh",
"android:build": "./scripts/build-android.sh",
"android:build:release": "./scripts/build-android.sh release",
"android:build:device": "./scripts/build-android.sh --device",
"android:build:release:device": "./scripts/build-android.sh release --device",
"android:build:clean": "rm -rf node_modules/.vite dist .svelte-kit .next build target src-tauri/target && bun install && bun run build",
"android:deploy": "./scripts/deploy-android.sh",
"android:dev": "./scripts/build-and-deploy.sh",
"android:check": "./scripts/check-android.sh",
"android:logs": "./scripts/logcat.sh",
"desktop:build:linux": "./scripts/build-desktop-linux.sh",
"desktop:build:arch": "./scripts/build-arch.sh",
"desktop:build:windows": "./scripts/build-windows-cross.sh",
"docker:build:linux": "docker compose run --rm desktop-linux-build",
"docker:build:arch": "docker compose run --rm arch-build",
"docker:build:windows": "docker compose run --rm windows-cross",
"clean": "./scripts/clean.sh",
"tauri": "tauri",
"traces": "bun run scripts/extract-traces.ts",
"traces:json": "bun run scripts/extract-traces.ts --format json",
"traces:markdown": "bun run scripts/extract-traces.ts --format markdown > docs/traceability.md",
"traces:coverage": "bun run scripts/extract-traces.ts --format coverage",
"traces:validate": "bun run scripts/extract-traces.ts --format validate",
"release:notes": "bun run scripts/release-notes.ts"
},
"dependencies": {
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-updater": "^2.10.1",
"hls.js": "^1.6.15",
"svelte-dnd-action": "^0.9.69"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@sveltejs/adapter-static": "^3.0.6",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tailwindcss/vite": "^4.1.18",
"@tauri-apps/cli": "^2",
"@testing-library/svelte": "^5.3.1",
"@vitest/coverage-v8": "^4.0.18",
"@vitest/ui": "^4.0.16",
"eslint": "^10.8.1",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-svelte": "^3.23.0",
"globals": "^17.11.0",
"happy-dom": "^20.0.11",
"jsdom": "^27.4.0",
"prettier": "^3.9.6",
"prettier-plugin-svelte": "^4.1.1",
"svelte": "^5.47.1",
"svelte-check": "^4.0.0",
"tailwindcss": "^4.1.18",
"typescript": "~5.6.2",
"typescript-eslint": "^8.67.0",
"vite": "^6.0.3",
"vitest": "^4.1.10"
}
}