feat: build the Jellyfin clients and YouTube AdFree from our mirrors #6

Merged
oap merged 2 commits from feat/jellyfin-youtube-apps into mainline 2026-10-25 03:43:58 -07:00
Owner

Adds Breezyfin, Jellyfin, Litefin, Moonfin, OcenFin and YouTube AdFree (the Jellyfin-related apps and YouTube AdFree from repo.webosbrew.org), built from source from the new pull mirrors in https://git.owenap.com/webos.

What changes

  • New app workflow (.forgejo/workflows/app.yaml). Pick an app and its upstream tag in Run workflow, or push a tag <app>-<upstream tag> such as jellyfin-v1.2.2. The release is tagged that way and carries the ipk, <app id>.manifest.json, a source tarball and SHA256SUMS.
  • apps/<app>/ has an app.conf (mirror, app id, icon) and a build.sh that follows upstream's own release workflow, minus lint and tests. Optional patches/*.patch work like the top-level patches/.
  • scripts/build-app.sh runs build.sh, checks the ipk's appinfo.json id and version against app.conf and the tag, and writes a manifest that points at the mirror.
  • scripts/update-index.sh, shared by both workflows, rebuilds apps.json from all releases and lists the newest version of each app id. Two runs that finish together still end up with a correct index. With the current v0.7.3 and v0.7.3.1 releases it picks v0.7.3.1 and produces the live index byte for byte.
  • The newest release is chosen by release tag, not app version, so the v0.7.3.N rebuilds from #3 still sort correctly: v0.7.3.1 (app version 0.7.3001) is below v0.7.4. release.yaml keeps its rebuild logic and calls the shared script for the index.
  • app.yaml checks this repo out the same way release.yaml does, and records the builder commit in the release notes.

Per-app notes

  • Litefin: builds the webOS Legacy ipk, the one upstream lists in repo.webosbrew.org. It needs no .NET; that is only for the server plugin.
  • OcenFin doesn't bump its version in git, so build.sh sets it from the tag.
  • YouTube AdFree installs as youtube.leanback.v4, replacing the stock YouTube app.
    • Its lockfile pins a glibc Node 25 runtime that can't run on Alpine, so build.sh drops it and uses the image's Node 22 (upstream asks for >=22).
    • Its ares-package is a GitHub fork pinned in the lockfile, so its install does reach GitHub.
  • Moonfin and OcenFin tags have no v: 2.10.0, 2026.10.19.

Testing

All six were built locally with scripts/build-app.sh in node:22-alpine (arm64; the runner is x86_64) at the current upstream tags. Compared with upstream's released ipk:

App Tag Files (ours / upstream) Size (ours / upstream)
Breezyfin v0.2.1 6576 / 6576 19 699 694 / 19 703 096
Jellyfin v1.2.2 23 / 23 162 288 / 161 556
Litefin v2.0.20 332 / 332 6 351 380 / 6 353 520
Moonfin 2.10.0 294 / 293 5 879 926 / 5 879 992
OcenFin 2026.10.19 46 / 46 2 526 878 / 2 529 536
YouTube AdFree v0.5.3 17 / 17 479 662 / 479 722

Differences are bundle content hashes, plus one extra ilibmanifest.json that Enact generates in Moonfin. All six mirrors have the tags at the same commits, and every manifest icon URL returns 200.

Not tested: the workflows themselves on the Forgejo runner, the index with more than one app published, and installing on a TV. After merging, run app once per app, then check the index on the TV.

🤖 Generated with Claude Code

Adds Breezyfin, Jellyfin, Litefin, Moonfin, OcenFin and YouTube AdFree (the Jellyfin-related apps and YouTube AdFree from repo.webosbrew.org), built from source from the new pull mirrors in https://git.owenap.com/webos. ## What changes - **New `app` workflow** (`.forgejo/workflows/app.yaml`). Pick an app and its upstream tag in Run workflow, or push a tag `<app>-<upstream tag>` such as `jellyfin-v1.2.2`. The release is tagged that way and carries the ipk, `<app id>.manifest.json`, a source tarball and `SHA256SUMS`. - **`apps/<app>/`** has an `app.conf` (mirror, app id, icon) and a `build.sh` that follows upstream's own release workflow, minus lint and tests. Optional `patches/*.patch` work like the top-level `patches/`. - **`scripts/build-app.sh`** runs `build.sh`, checks the ipk's `appinfo.json` id and version against `app.conf` and the tag, and writes a manifest that points at the mirror. - **`scripts/update-index.sh`**, shared by both workflows, rebuilds `apps.json` from all releases and lists the newest version of each app id. Two runs that finish together still end up with a correct index. With the current `v0.7.3` and `v0.7.3.1` releases it picks `v0.7.3.1` and produces the live index byte for byte. - **The newest release is chosen by release tag**, not app version, so the `v0.7.3.N` rebuilds from #3 still sort correctly: `v0.7.3.1` (app version `0.7.3001`) is below `v0.7.4`. `release.yaml` keeps its rebuild logic and calls the shared script for the index. - `app.yaml` checks this repo out the same way `release.yaml` does, and records the builder commit in the release notes. ## Per-app notes - **Litefin:** builds the webOS Legacy ipk, the one upstream lists in repo.webosbrew.org. It needs no .NET; that is only for the server plugin. - **OcenFin** doesn't bump its version in git, so `build.sh` sets it from the tag. - **YouTube AdFree** installs as `youtube.leanback.v4`, replacing the stock YouTube app. - Its lockfile pins a glibc Node 25 runtime that can't run on Alpine, so `build.sh` drops it and uses the image's Node 22 (upstream asks for >=22). - Its `ares-package` is a GitHub fork pinned in the lockfile, so its install does reach GitHub. - **Moonfin and OcenFin** tags have no `v`: `2.10.0`, `2026.10.19`. ## Testing All six were built locally with `scripts/build-app.sh` in `node:22-alpine` (arm64; the runner is x86_64) at the current upstream tags. Compared with upstream's released ipk: | App | Tag | Files (ours / upstream) | Size (ours / upstream) | |---|---|---|---| | Breezyfin | v0.2.1 | 6576 / 6576 | 19 699 694 / 19 703 096 | | Jellyfin | v1.2.2 | 23 / 23 | 162 288 / 161 556 | | Litefin | v2.0.20 | 332 / 332 | 6 351 380 / 6 353 520 | | Moonfin | 2.10.0 | 294 / 293 | 5 879 926 / 5 879 992 | | OcenFin | 2026.10.19 | 46 / 46 | 2 526 878 / 2 529 536 | | YouTube AdFree | v0.5.3 | 17 / 17 | 479 662 / 479 722 | Differences are bundle content hashes, plus one extra `ilibmanifest.json` that Enact generates in Moonfin. All six mirrors have the tags at the same commits, and every manifest icon URL returns 200. **Not tested:** the workflows themselves on the Forgejo runner, the index with more than one app published, and installing on a TV. After merging, run `app` once per app, then check the index on the TV. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add Breezyfin, Jellyfin, Litefin, Moonfin, OcenFin and YouTube AdFree,
the Jellyfin-related apps and YouTube AdFree from repo.webosbrew.org.
A new `app` workflow builds one of them from its pull mirror in
git.owenap.com/webos at an upstream tag and publishes it as a release
tagged `<app>-<tag>`. Each apps/<app>/ holds an app.conf (mirror, app
id, icon) and a build.sh that follows upstream's release workflow,
minus lint and tests. scripts/build-app.sh checks the ipk's app id and
version and writes the manifest, pointing at the mirror.

The index now lists every app. scripts/update-index.sh, shared by both
workflows, rebuilds apps.json from all releases and keeps the newest
version of each app id, so two runs finishing together still converge.
With only the v0.7.3 release it produces the live index byte for byte.

release.yaml never checked this repo out, so patches/ was missing at
build time and the dropbear patch step would fail on the next release.
Both workflows now run actions/checkout, without persisted
credentials, as npm runs third-party code.

App-specific notes:
- Litefin: we build the webOS Legacy ipk, the one upstream lists in
  repo.webosbrew.org. It needs no .NET; that is the server plugin's.
- OcenFin does not bump its version in git; build.sh sets it from the
  tag.
- YouTube AdFree: its lockfile pins a glibc Node 25 runtime that cannot
  run on Alpine, so build.sh installs with scripts off, drops it, and
  runs the dependency builds on the image's Node 22.

All six were built locally in node:22-alpine; each ipk has the same
file list as upstream's release and its size within 0.5% (Moonfin
carries one extra Enact ilibmanifest.json).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oap force-pushed feat/jellyfin-youtube-apps from 0cc0090c55 to 1e4cea799f 2026-10-25 03:35:10 -07:00 Compare
Two runs updating the index at once could each list the releases
before the other's existed, so the last upload dropped the other's app,
and both deleting before either uploaded left two apps.json assets.
release.yaml and app.yaml now share a `publish` concurrency group, so
runs queue instead of overlapping.

Publishing moves to scripts/publish-release.sh, shared by both
workflows. A release that lacks any of this run's files (an upload
failed half-way) now has its assets replaced instead of being kept
broken forever, a failed create stops the step, and a new tag is
created at the commit that was built rather than at mainline.

update-index.sh fails if the release it was called for has no ipk
asset, instead of leaving it out of the index silently, and matches
that tag exactly.

build-app.sh now applies apps/<app>/patches and packs the source
tarball before the build, so a local build matches CI and the tarball
holds the source as built, without build output. It reads appinfo.json
from usr/palm/applications/<id>/ only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oap merged commit 7ae90fa203 into mainline 2026-10-25 03:43:58 -07:00
oap deleted branch feat/jellyfin-youtube-apps 2026-10-25 03:44:00 -07:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
oap/webos-homebrew-channel-builder!6
No description provided.