The TunaOS Flatpak remote: the OCI index that flatpak remote-add tuna-os
resolves against, plus the scripts that maintain it.
Human docs: README.md (app list, and the step-by-step for adding
a new Flatpak), docs/.
The remote is served from tuna-os/docs
via the tunaos-org Cloudflare Worker, which deploys that repository’s static
assets at https://tunaos.org/flatpak/. So publishing is a two-repo operation,
and a correct index here can still be stale in production.
That matters for CI: check-metadata.yml curls the live served index —
run: curl -sSfL -o served-index.json https://tunaos.org/flatpak/index/static
run: ./scripts/enrich-index.py served-index.json --check
— so it validates production, not this branch. A failure there can mean a deploy hasn’t propagated, not that your change is wrong. Read it as a monitoring signal that happens to live in CI.
To read a red run and route a failure, see docs/check-metadata-failure.md.
scripts/update-index.py keeps only labels matching:
KEEP_LABEL_PREFIXES = ("org.flatpak.", "org.freedesktop.appstream.")
Both prefixes are load-bearing. flatpak build-bundle --oci writes the app’s
AppStream catalogue and scaled icons into the image config as
org.freedesktop.appstream.appdata, .icon-64 and .icon-128, and Flatpak
builds the remote’s AppStream catalogue from exactly those. An earlier revision
kept only org.flatpak.* and dropped them — the result was apps rendering in
Bazaar, GNOME Software and Discover as a bare org.tunaos.<app> string with an
“Unknown” licence and no screenshots, despite a complete catalogue already
being published. Do not narrow that tuple.
scripts/oci.py declares the same rule independently as
FLATPAK_LABEL_PREFIX/APPSTREAM_LABEL_PREFIX and keep_label(), used by
enrich-index.py to audit the live remote against the registry.
update-index.py can’t import oci.py (see below), so this is two
declarations of one invariant. tests/test_label_policy.py pins them to each
other — update both together, and let that test tell you if they’ve drifted.
scripts/update-index.py is the canonical single-file script. Application
repositories either vendor it at .github/scripts/update-index.py or consume
the update-flatpak-index composite action from tuna-os/.github — that action
is a byte-identical synced copy of this file, not a second source of truth.
The single source of truth is enforced by
flatpak-tooling-drift-check.yml in tuna-os/.github, which runs weekly and:
tuna-os/flatpak-index/scripts/update-index.py as canonical, and
verifies .github/actions/update-flatpak-index/update-index.py is byte-identical
to it; andmigrated (no local copy, uses the
shared publish-flatpak.yml), in sync (local copy byte-identical to canonical),
drifted (local copy differs — error), or unwired (no copy and no shared
tooling — error).An earlier revision drifted structurally (this copy at 146 lines, the action’s at 118), and this file’s “canonical” docstring was unchecked — the drift check treated the action copy as canonical instead. Both are now reconciled: the copies are byte-identical and the drift check verifies the link, so the docstring claim is backed by CI.
When you change this file, keep the action copy in tuna-os/.github byte-identical
— the drift check fails on any divergence. A fix landing in only one copy is the
failure mode this arrangement invites.
python3 -m unittest discover -s tests -v
ruff check . # config in ruff.toml
CI enforces Ruff and the unittest suite.
tests.ymlrunsruff check ., the unittest suite, and capture-action self-tests. Run both commands locally before opening a PR; keepruff check .clean.
scripts/oci.py holds the registry plumbing, enrich-index.py the validation
used by the live check above.
Adding a new app to the TunaOS remote (the long form is in the README):
tuna-os/ (gh repo fork <upstream> --org tuna-os --fork-name <app>).org.tunaos.<app>.json at that repo’s root. GNOME 50 apps use
org.gnome.Platform / org.gnome.Sdk runtime-version 50.flatpak build-bundle --oci and then
the vendored update-index.py, so the new entry carries both the
org.flatpak.* and org.freedesktop.appstream.* labels.curl -sSfL https://tunaos.org/flatpak/index/static — since this repo is
not what serves it.