Skip to content

Packaging: build a from-source Flatpak and submit it to Flathub #341

Description

@EtienneLescot

Split out of #335, whose Flathub half turned out to rest on a premise that does not hold. #335 reads "Flathub needs its own manifest submitted to flathub/flathub", which suggests wrapping what we already build. Flathub does not allow that, and the real shape of the work is a from-source build of the entire native stack, offline, inside the sandbox. Filing it properly rather than half-doing it in a packaging PR.

The upstream prerequisite — the AppStream MetaInfo file, which Flathub will not accept from a packager — landed in #340. Everything below is what remains.

The constraint that decides the design

From Flathub's requirements, verbatim:

All source available submissions must be built entirely from source code. This requirement applies to the main application component defined in the manifest, as well as any runtime dependencies included in the manifest.

There is no network access during the build process so all dependencies used by the application must be supplied by specifying them in the manifest as sources with publicly accessible URLs so that they can be downloaded before the build starts.

So the lazy route — unpack Openscreen-Linux-*.deb into /app — is out. Older Electron apps on Flathub do exactly that and maintainers used to wave it through on Discourse; the current documented rule is what a reviewer applies now, and betting a submission on a stale forum reply costs a rejected PR and a redo.

Two consequences worth stating plainly, because they are the reason this is not a one-afternoon task:

  1. Everything currently produced by a different CI workflow, or downloaded prebuilt, has to be rebuilt inside the manifest. That is most of the native stack.
  2. There is no local iteration on this. flatpak-builder needs Linux; every attempt is a CI round trip on a build measured in tens of minutes.

nix/package.nix is not a shortcut, in case it looks like one: it builds the renderer and wraps system Electron, and compiles none of the native code — no compositor, no PipeWire helper, no STT. A Flatpak built to that standard would reach Flathub unable to record, which is worse than not shipping.

What has to be built from source

Module Today In the manifest
Renderer + main process vite build Same, with npm deps vendored offline
Electron npm prebuilt download org.electronjs.Electron2.BaseApp (confirm the branch matches the chosen runtime)
npm dependencies npm ci flatpak-node-generator over package-lock.json
Rust compositor (crates/compositor, crates/compositor-view-napi) scripts/build-linux-compositor-addon.mjs flatpak-cargo-generator over Cargo.lock
PipeWire capture helper (electron/native/pipewire-capture) scripts/build-linux-pipewire-helper.mjs C module; the freedesktop SDK carries the PipeWire headers
ffmpeg prebuilt shared libs fetched by scripts/fetch-ffmpeg.mjs built from source, then patchelf --rename-dynamic-symbols to osff_* — the rename is not cosmetic, it is what stops the addon binding to Chromium's bundled ffmpeg, and that clash exists inside a Flatpak too
whisper STT (electron/native/whisper-stt) prebuilt binaries staged from build-whisper-stt.yml artifacts by scripts/stage-whisper-stt.sh CMake module, Vulkan backend, needs a shader compiler in the SDK

The STT model is not a build input — electron/stt/modelManager.ts downloads it into userData on first use, and runtime downloads are fine.

App ID and verification

com.getopenscreen.OpenScreen, already the component ID of the MetaInfo file added in #340. Not the Electron appId com.etiennelescot.openscreen: Flathub requires the ID to map to a domain the project controls, getopenscreen.com is that domain, and changing the Electron appId would move the userData directory of every existing install.

The ID differing from Electron's has one consequence to handle in the manifest: the desktop file, MetaInfo file and icon must all be renamed to the app ID, the <launchable> rewritten to match, and StartupWMClass=Openscreen kept as-is — Electron sets WM_CLASS from the product name, so that line is what associates the window with the icon.

Sandbox surface to get right

Capture is the one that decides whether this is worth shipping. Linux capture already goes exclusively through xdg-desktop-portal (X11 included — the helper has no other path), which is the sandbox-native route, so this should be the easy part. It still has to be proven on a real desktop rather than assumed.

Roughly: --socket=wayland, --socket=fallback-x11, --share=ipc, --device=dri for the Vulkan compositor, --socket=pulseaudio, --share=network for the LLM providers and the model download, --talk-name=org.freedesktop.secrets for safeStorage (without it isEncryptionAvailable() is false and saving an API key throws), and filesystem access for exports.

x86_64 only — flathub.json with only-arches, matching what build.yml produces.

Checklist

  • Pick the runtime version and confirm an Electron BaseApp branch exists for it
  • Generate the npm and cargo offline source manifests in CI rather than committing them here
  • ffmpeg module, with the osff_* rename reproduced
  • whisper-stt module
  • PipeWire helper module
  • Rust compositor addon module
  • Rename desktop/MetaInfo/icon to the app ID, rewrite <launchable>
  • flathub.json with only-arches: [x86_64]
  • CI job running flatpak-builder plus flatpak-builder-lint — the only place any of this can be verified
  • Install the built bundle on a real desktop and confirm capture, preview and export actually work
  • Serve /.well-known/org.flathub.VerifiedApps.txt from getopenscreen.com to claim the ID
  • Open the submission against the new-pr base branch of flathub/flathub, titled Add com.getopenscreen.OpenScreen
  • Wire release automation once the ID is accepted (updates never go through the submission process again)

Worth deciding before starting

Whether it is worth it at all, honestly. Flathub is the main Linux discovery surface and that argument from #335 stands. Against it: this adds a fifth Linux packaging path to maintain, and its build is the only one that cannot reuse anything build.yml already does. A first submission that ships without STT — dropping the heaviest module — is a legitimate smaller target, if a degraded one, and would be much faster to land.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions