- Shell 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
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> |
||
| .forgejo/workflows | ||
| apps | ||
| patches | ||
| scripts | ||
| README.md | ||
webos-homebrew-channel-builder
Builds the webOS Homebrew Channel
.ipk, and the apps in apps/, from our own mirrors and publishes
them as releases here.
Nothing is fetched from GitHub at build time. If upstream disappears, the build still works.
Inputs
All are pull mirrors in https://git.owenap.com/webos (keep "Remove obsolete remote-tracking references" off so deleted upstream refs survive):
| Mirror | Upstream |
|---|---|
webos-homebrew-channel |
webosbrew/webos-homebrew-channel |
enyo, moonstone, spotlight, layout, svg, enyo-ilib, enyo-webos |
enyojs/* (the submodules) |
The workflow rewrites https://github.com/enyojs/ to the mirror with a git
insteadOf rule. No patch to upstream is needed.
The apps each have one mirror more, listed under Apps.
Release
Actions -> release -> Run workflow, with an upstream tag such as v0.7.3.
Or push that tag to this repo.
Rebuilds
To publish a change in patches/ for an upstream version that is already
released, add a 4th number: v0.7.3.1, v0.7.3.2, ... (up to .999). That
builds upstream v0.7.3 with the current patches and publishes it as release
v0.7.3.1.
The app on the TV shows "Update" when the version in the index differs from
the installed app's version. ares-package only accepts x.y.z, so the
rebuild number goes into the last part. Rebuild N of 0.7.3 gets app version
0.7.3NNN, so v0.7.3.1 is app version 0.7.3001 and v0.7.3.12 is
0.7.3012. The TV shows that version. A rebuild of an x.y.0 release is
refused, because its app version would be the same as upstream's x.y.N.
Each release carries:
org.webosbrew.hbchannel_<app version>_all.ipkorg.webosbrew.hbchannel.manifest.jsonwebos-homebrew-channel-<release tag>-source.tar.gz(source plus submodules)SHA256SUMS
The release notes list this repo's commit, the upstream commit, every submodule commit and the app version.
Running the workflow again for a release that already exists keeps it as it is. If the release is missing any of its files (an upload failed), the run replaces all of its assets with its own build instead.
release and app runs go one at a time (a shared concurrency group), so
two runs never write the index at once. A run waits while another is going.
Apps
The Jellyfin clients and YouTube AdFree from repo.webosbrew.org, each
built by .forgejo/workflows/app.yaml from a pull mirror in
https://git.owenap.com/webos:
| App | apps/ |
Mirror | Upstream |
|---|---|---|---|
| Breezyfin | breezyfin |
Breezyfin |
botagas/Breezyfin |
| Jellyfin | jellyfin |
jellyfin-webos |
jellyfin/jellyfin-webos |
| Litefin | litefin |
litefin |
MoazSalem/litefin |
| Moonfin | moonfin |
Smart-TV |
Moonfin-Client/Smart-TV |
| OcenFin | ocenfin |
OcenFin |
seluce/OcenFin |
| YouTube AdFree | youtube |
youtube-webos |
webosbrew/youtube-webos |
Actions -> app -> Run workflow, pick the app and enter its upstream tag
(v1.2.2; Moonfin and OcenFin tag without the v: 2.10.0, 2026.10.19).
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.
Each apps/<app>/ has:
app.conf: the mirror, the app id, and the icon the index shows.build.sh: runs in the checked-out source with$VERSIONand$OUTset and leaves one.ipkin$OUT. It follows upstream's own release workflow, minus lint and tests.patches/*.patch, optional: applied before the build, as inpatches/.
scripts/build-app.sh applies the patches, packs the patched source into the
source tarball, runs build.sh, checks that the ipk's appinfo.json has the
id from app.conf and the version of the tag, and writes the manifest. To
build one locally the same way, CI included, check the source out into src/
and run, in node:22-alpine with apk add git curl jq tar coreutils binutils:
sh scripts/build-app.sh jellyfin v1.2.2
The apps have no rebuilds like v0.7.3.1: the tag must be an upstream tag,
and the ipk's version must equal it. To ship a new patch for an app version
that is already released, delete that release (and its tag) and run the
workflow again.
Notes on single apps:
- Litefin has several webOS builds. We build "webOS Legacy", the one
upstream lists in
repo.webosbrew.org. - OcenFin does not bump the version in git;
build.shsets it from the tag. - YouTube AdFree installs as
youtube.leanback.v4, the stock YouTube app's id, so it replaces that app. Itsares-packageis a GitHub fork that its lockfile pins by commit, so itspnpm installdoes fetch from GitHub.
To add an app, add apps/<app>/, its mirror, and the app to the options
and tags lists in app.yaml.
Updates from our Forgejo
The app does not update itself from the manifest. It reads repository indexes
(JSON lists of apps) and offers the version each one lists. The default index
is repo.webosbrew.org, which follows GitHub.
Each release also refreshes our own index, which lists every app this repo
builds. It is an asset of a release tagged index, because the job token
cannot push to a branch:
https://git.owenap.com/oap/webos-homebrew-channel-builder/releases/download/index/apps.json
On the TV, open Homebrew Channel -> Settings -> Repositories -> Add repository
and enter that URL. Turn off the default repository if you want only our
builds. From a shell you can also run
ares-launch org.webosbrew.hbchannel -p '{"launchMode":"addRepository","url":"<index url>"}'.
scripts/update-index.sh rebuilds the index from all releases of this repo
each time, and lists the newest release of each app id, by release tag
(v0.7.3.1 comes after v0.7.3 and before v0.7.4). Rebuilding an older
tag does not move it back.
The release manifest is patched after the build: its icon and project page
point at the mirror instead of GitHub. The .ipk is unchanged by this,
because the manifest is not part of the package. The apps' manifests are
written by scripts/build-app.sh and point at the mirror too.
Forgejo does not send a CORS header on release downloads, and the official index does.
Check on a real TV that the app can load the index. If it cannot, add
Access-Control-Allow-Origin: * for that path in the reverse proxy.
Notes
- The repo must stay owned by
oap. The Actions runner is scoped tooap's repos; an organization-owned repo gets no runner. - The job uses the
dockerrunner label becausenpm ciruns third-party code. It is not byte-for-byte identical to upstream's published.ipk(build output differs slightly), but it has the same files. - The npm dependencies still come from the npm registry. They are not archived.