Support Jellyfin 12 alongside 10.11
Jellyfin 12 moved to .NET 10 and changed the IUserManager surface the plugin relies on: Users/UsersIds became GetUsers()/GetUsersIds(), ChangePassword takes a user id, HasPassword left the provider contract, and the user cache is gone, so every lookup is a detached copy. The plugin now multi-targets net9.0 (against 10.11.5) and net10.0 (against 12.0.0). The differences sit behind a JELLYFIN_12 constant in Compat/UserManagerCompat.cs, whose ChangePasswordAsync also carries the stored hash back onto the caller's instance: on 12 the UpdateUserAsync that claims the account would otherwise write the stale null password back over the one provisioning just set. Each release ships one package per generation, with the fourth version segment naming the target (x.y.z.11 and x.y.z.12) so a 12 server picks the 12 package over the 10.11 one. scripts/package.sh wraps jprm for a single generation and the workflows call it twice. The builder image moves to the .NET 10 SDK, which builds both targets; the net9.0 test run rolls forward onto the .NET 10 runtime. CA1873 is a .NET 10 analyzer that flags the same log calls CA1848 does; it is set to Info, as in the upstream Jellyfin 12 tree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -164,8 +164,10 @@ Then install **Watched Together** from the catalogue and restart Jellyfin.
|
||||
|
||||
### Manual
|
||||
|
||||
Download the release `.zip`, extract it into a `WatchedTogether` folder inside your Jellyfin
|
||||
`plugins` directory, and restart the server.
|
||||
Each release ships two `.zip` files: one for Jellyfin **10.11** and one for Jellyfin **12** (the
|
||||
version's last segment says which: `x.y.z.11` or `x.y.z.12`). Download the one matching your
|
||||
server, extract it into a `WatchedTogether` folder inside your Jellyfin `plugins` directory, and
|
||||
restart the server. The plugin repository picks the right one for you automatically.
|
||||
|
||||
---
|
||||
|
||||
@@ -239,18 +241,26 @@ How this plugin bounds what a shared account can reach.
|
||||
|
||||
## Compatibility
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Target ABI | Jellyfin **10.11.x** |
|
||||
| Framework | .NET 9 |
|
||||
| Jellyfin | Framework | Built against | Package version |
|
||||
| --- | --- | --- | --- |
|
||||
| **10.11.x** | .NET 9 | `Jellyfin.Controller` 10.11.5 | `x.y.z.11` |
|
||||
| **12.x** | .NET 10 | `Jellyfin.Controller` 12.0.0 | `x.y.z.12` |
|
||||
|
||||
Verified against the 10.11.5 SDK: `IAuthenticationProvider` + `IRequiresResolvedUser`,
|
||||
`ICryptoProvider.Verify`, `IUserDataManager.UserDataSaved`, and a 255-character username limit.
|
||||
One source tree, one build per server generation. Jellyfin 12 turned `IUserManager.Users` and
|
||||
`UsersIds` into methods, made `ChangePassword` take a user id, dropped `HasPassword` from
|
||||
`IAuthenticationProvider`, and stopped caching users in memory (every lookup is a detached copy).
|
||||
Those differences live behind a `JELLYFIN_12` compile constant in
|
||||
[Compat/UserManagerCompat.cs](Jellyfin.Plugin.WatchedTogether/Compat/UserManagerCompat.cs); the
|
||||
rest of the plugin is identical on both.
|
||||
|
||||
Jellyfin installs the highest manifest version whose `targetAbi` it satisfies, which is why the two
|
||||
packages of a release carry different version numbers: a 10.11 server only sees the `.11` entry,
|
||||
while a 12 server sees both and takes the `.12` one.
|
||||
|
||||
Auto-creation depends on `UserManager.AuthenticateUser` offering unmatched usernames to every
|
||||
enabled provider and re-querying the database afterwards ("the authentication provider might have
|
||||
created it"). That behaviour is present in 10.11.5; if a future release changes it, auto-creation
|
||||
stops working and dashboard provisioning continues to.
|
||||
created it"). That behaviour is present in both 10.11.5 and 12.0; if a future release changes it,
|
||||
auto-creation stops working and dashboard provisioning continues to.
|
||||
|
||||
Jellyfin's plugin API changes across minor versions, `IServerEntryPoint` gave way to
|
||||
`IHostedService` around 10.9, and entity types moved namespaces in 10.11. Expect to rebuild against
|
||||
@@ -260,26 +270,35 @@ the matching SDK when upgrading the server.
|
||||
|
||||
## Building
|
||||
|
||||
The plugin targets .NET 9. If your machine does not have that runtime, build in a container:
|
||||
The solution multi-targets `net9.0` (Jellyfin 10.11) and `net10.0` (Jellyfin 12), so it needs the
|
||||
.NET 10 SDK, which builds both. The test host rolls the `net9.0` run forward onto the .NET 10
|
||||
runtime, so a single runtime is enough. If your machine does not have it, build in a container:
|
||||
|
||||
```bash
|
||||
docker run --rm -v "$PWD":/src -w /src mcr.microsoft.com/dotnet/sdk:9.0 \
|
||||
docker run --rm -v "$PWD":/src -w /src mcr.microsoft.com/dotnet/sdk:10.0 \
|
||||
dotnet test Jellyfin.Plugin.WatchedTogether.sln -c Release
|
||||
```
|
||||
|
||||
Or natively, with the .NET 9 SDK installed:
|
||||
Or natively, with the .NET 10 SDK installed:
|
||||
|
||||
```bash
|
||||
dotnet build Jellyfin.Plugin.WatchedTogether.sln -c Release
|
||||
dotnet test Jellyfin.Plugin.WatchedTogether.sln -c Release
|
||||
```
|
||||
|
||||
To produce an installable plugin zip:
|
||||
Tests run once per framework; the `net10.0` run has one test fewer because `HasPassword` no longer
|
||||
exists on Jellyfin 12's provider contract.
|
||||
|
||||
To produce installable plugin zips, one per Jellyfin generation:
|
||||
|
||||
```bash
|
||||
jprm plugin build .
|
||||
scripts/package.sh 10.11 0.0.5.11 # -> artifacts/watched-together_0.0.5.11.zip
|
||||
scripts/package.sh 12 0.0.5.12 # -> artifacts/watched-together_0.0.5.12.zip
|
||||
```
|
||||
|
||||
The script wraps `jprm plugin build`, stamping `build.yaml` with the right framework and
|
||||
`targetAbi` for the chosen generation and restoring it afterwards.
|
||||
|
||||
### CI
|
||||
|
||||
Gitea Actions workflows live in [.gitea/workflows/](.gitea/workflows/):
|
||||
@@ -287,8 +306,10 @@ Gitea Actions workflows live in [.gitea/workflows/](.gitea/workflows/):
|
||||
| Workflow | Trigger | Does |
|
||||
| --- | --- | --- |
|
||||
| `test.yaml` | push / PR | Debug build and test run, uploads `.trx` results |
|
||||
| `build.yaml` | push / PR to `master` | Release build, tests, and a date-versioned plugin zip |
|
||||
| `release.yaml` | tag `v*.*.*` | Builds, creates a Gitea release, and updates `manifest.json` |
|
||||
| `build.yaml` | push / PR to `master` | Release build, tests, and a date-versioned plugin zip per Jellyfin generation |
|
||||
| `release.yaml` | tag `vX.Y.Z` | Builds `X.Y.Z.11` and `X.Y.Z.12`, creates a Gitea release with both, and adds both to `manifest.json` |
|
||||
|
||||
Release tags are three-part (`v0.0.5`); the fourth segment is reserved for the Jellyfin generation.
|
||||
|
||||
All three run in the builder image defined by [Dockerfile.builder](Dockerfile.builder):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user