mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-30 07:37:38 +00:00
Flathub doesn't accept the release manifest, which repackages CI's prebuilt tree. desktopApp/packaging/flatpak/flathub/ builds the tag offline instead: - com.vitorpamplona.amethyst.Amethyst.yml compiles the tag tarball with `:desktopApp:createReleaseDistributable` on the JetBrains Runtime SDK 21.0.11 (prebuilt, as Flathub ships it for com.prof18.feedflow), so the bundled runtime keeps JBR's Wayland toolkit. Sources: the tarball, JBR per arch, Gradle 9.8.0, the init script and gradle-sources.json. - gradle-sources.json: the 2,185 Maven files the build resolves on x86_64 and aarch64 (1,566 Maven Central, 591 Google, 28 JitPack), each with its sha256, laid out as a local Maven repo. - flathub-offline.init.gradle replaces every repository with that repo. - tools/regenerate-gradle-sources.sh reruns the build online per arch in Docker on a fresh Gradle home and turns the module cache into the list (tools/gradle-cache-to-sources.py, which also maps Gradle module metadata's local file names to their published URLs). Checked on aarch64: flatpak-builder builds it without network, the installed Flatpak is 1.19.0 on runtime 26.08 with libawt_wlawt.so, and `flatpak run` reaches the login screen. flatpak-builder-lint passes the manifest and the metainfo; on the build it reports only the two media-URL checks, which expect the absolute dl.flathub.org/media URLs Flathub's builder writes where Debian's AppStream 1.0.5 writes relative ones. Not checked: x86_64 through flatpak-builder, and Flathub's own builder (it can't nest in Docker). The flatpak README's Flathub section now tracks what is left: the AI policy (these files are AI-written, the manifest says so, and the submission must disclose it), domain verification, and submitting from the next tag, whose metainfo has the screenshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
201 lines
10 KiB
Markdown
201 lines
10 KiB
Markdown
# Flatpak packaging for Amethyst Desktop
|
|
|
|
App ID: **`com.vitorpamplona.amethyst.Amethyst`**. Earlier bundles used two
|
|
other IDs:
|
|
|
|
- Up to v1.17.0: `com.vitorpamplona.amethyst.Desktop`. Flathub forbids IDs that
|
|
end in generic terms like `.desktop`, `.app` or `.linux` ("it's fine to repeat
|
|
the application name in such cases", hence `.Amethyst`).
|
|
- v1.18.0: `com.vitorpamplona.amethyst`, the Android package name. Nostr app
|
|
stores (NIP-82) key an app's listing on its native ID: Zapstore lists the
|
|
Android app under `com.vitorpamplona.amethyst`, and Orchard, a Flatpak store,
|
|
would list the Flatpak under its app ID. Both listings are signed by the same
|
|
key, so one shared ID would make each store's publish overwrite the other's
|
|
listing.
|
|
|
|
`BUILDING.md` § Uninstall + state paths explains how users move their data to
|
|
the new ID.
|
|
|
|
Release CI (`.github/workflows/create-release.yml`, `linux-portable` leg)
|
|
builds a single-file bundle from this directory on every tag and attaches it to
|
|
the GitHub Release as `amethyst-desktop-<version>-linux-<x64|arm64>.flatpak`.
|
|
|
|
**Amethyst is not on Flathub.** The manifest here repackages a prebuilt tree,
|
|
which Flathub does not accept; [`flathub/`](flathub/) has the source build. See
|
|
[Flathub](#flathub) below.
|
|
|
|
## Files
|
|
|
|
- `com.vitorpamplona.amethyst.Amethyst.yml`: Flatpak manifest for the GitHub
|
|
Release bundle. It packages the **prebuilt** jpackage tree from
|
|
`./gradlew :desktopApp:createReleaseDistributable`, which bundles its own
|
|
trimmed JRE (hence no openjdk extension). Build that tree on the JetBrains
|
|
Runtime (see [Sandbox notes](#sandbox-notes)), or the bundle can't draw on
|
|
Wayland.
|
|
- `com.vitorpamplona.amethyst.Amethyst.metainfo.xml`: AppStream metadata. It
|
|
keeps the release history: add an entry when tagging (`RELEASE_OPS.md` § Pre-tag
|
|
checklist). CI injects a bare entry for the version it builds if one is
|
|
missing.
|
|
- `com.vitorpamplona.amethyst.Amethyst.desktop`: XDG desktop entry.
|
|
- `icons/512/com.vitorpamplona.amethyst.Amethyst.png`: 512x512 icon (copy of
|
|
`desktopApp/src/jvmMain/resources/icon.png`).
|
|
|
|
Validate after editing:
|
|
|
|
```bash
|
|
appstreamcli validate --pedantic com.vitorpamplona.amethyst.Amethyst.metainfo.xml
|
|
desktop-file-validate com.vitorpamplona.amethyst.Amethyst.desktop
|
|
```
|
|
|
|
Both pass. `--pedantic` prints one hint, `cid-contains-uppercase-letter`: the
|
|
`.Amethyst` component is capitalised, which Flathub's ID rules allow. Flathub's
|
|
own linter (`flatpak-builder-lint` from the `org.flatpak.Builder` app) passed
|
|
on the manifest under the previous ID and has not been re-run since the rename;
|
|
on the built repo it reported only the missing screenshot:
|
|
|
|
```bash
|
|
flatpak install --user flathub org.flatpak.Builder
|
|
flatpak run --command=flatpak-builder-lint org.flatpak.Builder manifest com.vitorpamplona.amethyst.Amethyst.yml
|
|
flatpak run --command=flatpak-builder-lint org.flatpak.Builder repo <path-to>/repo
|
|
```
|
|
|
|
## Local build
|
|
|
|
```bash
|
|
# 1. Build the app tree the manifest packages, on the JetBrains Runtime 21 (jbrsdk)
|
|
JAVA_HOME=/path/to/jbrsdk-21 ./gradlew :desktopApp:createReleaseDistributable
|
|
|
|
# 2. Tooling + Flathub remote (one-time)
|
|
sudo apt-get install -y flatpak flatpak-builder # or distro equivalent
|
|
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
|
|
|
# 3. Build + install locally
|
|
cd desktopApp/packaging/flatpak
|
|
flatpak-builder --user --install --install-deps-from=flathub --force-clean \
|
|
build-dir com.vitorpamplona.amethyst.Amethyst.yml
|
|
flatpak run com.vitorpamplona.amethyst.Amethyst
|
|
```
|
|
|
|
To produce the distributable single-file bundle instead (what CI ships):
|
|
|
|
```bash
|
|
flatpak-builder --user --install-deps-from=flathub --force-clean \
|
|
--repo=repo build-dir com.vitorpamplona.amethyst.Amethyst.yml
|
|
flatpak build-bundle repo amethyst.flatpak com.vitorpamplona.amethyst.Amethyst \
|
|
--runtime-repo=https://dl.flathub.org/repo/flathub.flatpakrepo
|
|
```
|
|
|
|
Installing the bundle: `flatpak install --user ./amethyst.flatpak`. The
|
|
`--runtime-repo` baked in above lets flatpak fetch the freedesktop runtime
|
|
from Flathub automatically on the user's machine.
|
|
|
|
## Runtime
|
|
|
|
`org.freedesktop.Platform` **26.08**. Each freedesktop runtime gets about two
|
|
years of support (a new one ships every August), so bump `runtime-version`
|
|
yearly. CI reads the version from the manifest when it installs the runtime.
|
|
|
|
Codecs: since 25.08 the runtime declares `org.freedesktop.Platform.codecs-extra`
|
|
(the successor of `ffmpeg-full`: H.264/H.265 and friends) and flatpak installs
|
|
it with the runtime, so the manifest declares no codec extension. Don't set
|
|
`GST_PLUGIN_SYSTEM_PATH` in `finish-args`: the runtime's own value already
|
|
lists the codecs-extra plugin directory, and overriding it hides those plugins.
|
|
|
|
## Sandbox notes
|
|
|
|
- `--socket=wayland` + `--socket=fallback-x11`: the app draws natively on
|
|
Wayland and gets X11 only on X11 sessions. This needs the bundled runtime to
|
|
be the JetBrains Runtime (its AWT has a Wayland toolkit, `WLToolkit`; stock
|
|
OpenJDK's AWT is X11-only), which release CI builds the Linux legs on. Skiko's
|
|
window surface needs X11, so on Wayland the app draws through Swing with
|
|
Skiko's CPU renderer (`desktopApp/.../platform/WaylandDisplay.kt`,
|
|
`AppWindow.kt`). `flatpak run --env=AMETHYST_X11=1 --socket=x11
|
|
com.vitorpamplona.amethyst.Amethyst` puts it back on XWayland.
|
|
- File access is limited to Downloads and Pictures. AWT's `FileDialog` calls
|
|
the GTK file chooser directly rather than the file chooser portal, so it can
|
|
only browse what the sandbox can see.
|
|
- `--talk-name=org.freedesktop.secrets`: `java-keyring` stores the account keys
|
|
through the Secret Service API.
|
|
- `--talk-name=org.freedesktop.Notifications`: `NucleusNotificationDispatcher`
|
|
sends desktop notifications over D-Bus through `nucleus.notification-linux`
|
|
(AWT's tray is only its fallback).
|
|
- `--persist=.amethyst` and `--persist=.java`: the app writes accounts,
|
|
drafts, scheduled posts and the local relay under `~/.amethyst`, and Java
|
|
Preferences (relay lists, search history) under `~/.java`. Without home
|
|
access, writes there are lost when the sandbox exits; `--persist` keeps them
|
|
under `~/.var/app/com.vitorpamplona.amethyst.Amethyst/`. Tor state and the
|
|
image cache already follow `XDG_DATA_HOME`/`XDG_CACHE_HOME`.
|
|
- Scheduled posts only publish while the app is open. `OsScheduler` registers
|
|
a systemd user timer (or crontab entry) to publish while the app is closed,
|
|
and neither can be reached from the sandbox.
|
|
- The "now playing" reader (`MprisNowPlayingReader`) queries other players
|
|
over the session bus with `dbus-send`. The sandbox grants no
|
|
`org.mpris.MediaPlayer2.*` access, so it finds nothing in the Flatpak.
|
|
|
|
## Flathub
|
|
|
|
Amethyst has not been submitted yet. [`flathub/`](flathub/) holds a manifest
|
|
that builds from source as Flathub requires, and the tools that keep it current.
|
|
Status against Flathub's
|
|
[requirements](https://docs.flathub.org/docs/for-app-authors/requirements):
|
|
|
|
1. **Build from source: done.** `flathub/com.vitorpamplona.amethyst.Amethyst.yml`
|
|
compiles the release tag offline with `:desktopApp:createReleaseDistributable`.
|
|
Its pinned sources are the tag's tarball, the JetBrains Runtime SDK 21 (it runs
|
|
Gradle and jpackage, so the bundled runtime keeps JBR's Wayland toolkit), the
|
|
Gradle distribution, and `gradle-sources.json`: every Maven file the build
|
|
resolves, for x86_64 and aarch64. `flathub-offline.init.gradle` replaces every
|
|
repository with that local copy. Flathub already ships a prebuilt JBR and
|
|
Skiko's natives in `com.prof18.feedflow`, a Compose Desktop app built the same
|
|
way.
|
|
|
|
Checked on aarch64 with `flatpak-builder` (network-less build, installs,
|
|
`flatpak run` reaches the login screen, bundled runtime has
|
|
`libawt_wlawt.so`); x86_64's dependency list was captured but not built
|
|
through `flatpak-builder`. `flatpak-builder-lint` passes the manifest and the
|
|
metainfo. On the build it reports only `appstream-external-screenshot-url`
|
|
and `appstream-remote-icon-not-mirrored`: Debian's AppStream 1.0.5 writes
|
|
media paths relative to `media_baseurl`, while the linter expects the full
|
|
`https://dl.flathub.org/media` URLs Flathub's own builder writes.
|
|
Flathub's builder (`org.flatpak.Builder`) could not run nested in Docker, so
|
|
that was not checked end to end.
|
|
|
|
Every release: `flathub/tools/regenerate-gradle-sources.sh vX.Y.Z` (about
|
|
35 minutes, both arches in Docker) rewrites `gradle-sources.json` from a real
|
|
online build and prints the tarball's sha256 for the manifest. Flathub's
|
|
update bot can't regenerate that list, so each release is a manual PR to the
|
|
Flathub app repo.
|
|
|
|
Some Maven dependencies ship prebuilt Linux binaries inside their jars (JNA,
|
|
secp256k1, SQLite, the media player, notifications, Skiko, and a `tor`
|
|
executable in kmp-tor). FeedFlow's acceptance covers the Skiko kind; a
|
|
reviewer may still ask about the `tor` executable.
|
|
2. **Generative AI policy: not met.** Flathub manifests "must not contain
|
|
AI-generated or AI-assisted content", AI tools "must not open or automate
|
|
Flathub submission pull requests, or generate their commit messages,
|
|
descriptions, review comments, or replies", and all other AI-generated
|
|
code, documentation or packaging must be disclosed. The `flathub/` files
|
|
were written with Claude Code (the manifest says so), so the submission
|
|
must disclose it and reviewers may decline; a person opens the submission
|
|
PR and answers the review.
|
|
3. **Screenshot: done.** The metainfo lists `docs/screenshots/desktop-home.png`,
|
|
the 1.19.0 Linux build's home feed, from a commit-pinned URL. It landed
|
|
after `v1.19.0`, so submit with the next tag: the `v1.19.0` metainfo has none.
|
|
4. **Domain verification.** `com.vitorpamplona.amethyst.Amethyst` is verified by
|
|
serving the token Flathub provides at
|
|
`https://vitorpamplona.com/.well-known/org.flathub.VerifiedApps.txt`.
|
|
5. **Latest runtime: done.** 26.08 is the newest freedesktop runtime.
|
|
|
|
Once accepted, Flathub creates `flathub/com.vitorpamplona.amethyst.Amethyst`;
|
|
copy the manifest, the init script and `gradle-sources.json` there, and each
|
|
update is a PR to it.
|
|
|
|
## License metadata
|
|
|
|
The metainfo declares
|
|
`MIT AND LGPL-2.1-or-later AND BSD-2-Clause AND Apache-2.0 AND GPL-2.0-only WITH Classpath-exception-2.0`:
|
|
the expression from `rpmLicenseType` in `desktopApp/build.gradle.kts` plus the
|
|
bundled OpenJDK runtime. The manifest installs the repository `LICENSE` to
|
|
`/app/share/licenses/com.vitorpamplona.amethyst.Amethyst/`. The JRE's own notices ship
|
|
inside the jpackage tree under `lib/runtime/legal/`.
|