feat(linux): package OpenLogi as a Flatpak with a signed repository - #767
feat(linux): package OpenLogi as a Flatpak with a signed repository#767AalmanSadath wants to merge 3 commits into
Conversation
Linux is the only platform that cannot update itself. The .deb/.rpm/.pkg.tar.zst packages ship with no repository behind them, and the in-app updater has no Linux artifact to offer: `xtask release latest-json` classifies only .dmg/.msi/.zip while the updater asks for tar.gz on Linux. So every Linux upgrade today is a manual download, which is what AprilNEA#605 runs into. A Flatpak remote closes that. Install once, and `flatpak update` — or GNOME Software and KDE Discover in the background — carries the user forward. It also installs on atomic distributions, where layering an rpm is the current answer (AprilNEA#681). Nothing about the application changes. Only the build environment lives in the manifest, because that part is genuinely packaging's problem: - rustup rather than org.freedesktop.Sdk.Extension.rust-stable. The workspace sets `rust-version` to current stable and the extension trails it by weeks (1.97.1 against a workspace asking for 1.98), which cargo refuses outright. rustup installs what rust-toolchain.toml names. - llvm20, since openlogi-camera pulls v4l2-sys-mit, whose build script runs bindgen and dlopens libclang; the base SDK ships none. - A .desktop file and AppStream metadata, because Flatpak requires both to be named for the application ID and there is no AppStream data in the tree. - Icons rescaled: `flatpak build-export` rejects the 1024x1024 source. The workflow builds both architectures on a published release, merges them into one OSTree repository, signs it, and deploys to Pages. Signing covers the commits as well as the summary, because clients verify the commit they pull and a summary-only signature fails every install with "GPG verification enabled, but no signatures found". Publishing is gated on FLATPAK_GPG_PRIVATE_KEY. Without the secret the build still runs and uploads artifacts, so this is inert rather than red until someone decides to turn it on and supply a key. One caveat, documented in docs/INSTALL-linux.md: a Flatpak cannot write to /etc, so the udev rules must be installed on the host or no devices are detected at all. The rules ship inside the app so no checkout is needed for that step.
Greptile SummaryThe PR adds a self-updating Linux Flatpak distribution backed by a signed GitHub Pages OSTree repository.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the source ref and advertised version are now resolved together, and the previously raised first-party action-pinning concern was explicitly settled.
|
| Filename | Overview |
|---|---|
| .github/workflows/flatpak.yml | Adds the multi-architecture build, signing, and Pages publication workflow; the previously reported version/ref mismatch is fixed. |
| packaging/linux/flatpak/org.openlogi.OpenLogi.yml | Defines the Flatpak runtime permissions, build environment, binaries, desktop integration, icons, udev rules, and licenses. |
| packaging/linux/flatpak/org.openlogi.OpenLogi.metainfo.xml | Adds AppStream metadata for software-center discovery and release presentation. |
| docs/INSTALL-linux.md | Documents Flatpak installation, updates, and required host-side udev setup. |
| .claude/rules/ci.md | Documents that Flatpak builds are outside the PR workflow and provides the local reproduction command. |
Sequence Diagram
sequenceDiagram
participant Trigger as Release or manual dispatch
participant Resolve as Resolve job
participant Build as Architecture builds
participant Publish as Publish job
participant Pages as GitHub Pages
Trigger->>Resolve: Tag, requested version, or selected ref
Resolve-->>Build: Paired source ref and version
Build->>Build: Build x86_64 and aarch64 Flatpak repos
Build-->>Publish: Upload architecture repositories
Publish->>Publish: Merge OSTree refs
Publish->>Publish: Sign commits and repository summary
Publish->>Pages: Deploy repository and descriptors
Reviews (3): Last reviewed commit: "docs(ci): record why the publish job kee..." | Re-trigger Greptile
A manual dispatch took `version` as a label only: `resolve` fed it to the AppStream stamp and the landing page, while both jobs checked out whatever ref the dispatch ran on. Dispatching v0.7.0 from master therefore built master and published it, signed, as 0.7.0 — a repository asserting a release identity its binaries were never built from. `resolve` now emits the ref alongside the version and the two move together: a release builds its tag, a dispatch naming a version builds that tag, and a dispatch naming none builds the ref it ran on and labels it with the workspace version, which is the honest name for that tree. Also records the workflow in .claude/rules/ci.md, including that it never runs on a PR, so a change to the manifest is known to arrive unverified unless someone builds it locally.
The job holds Pages and OIDC permissions and imports the signing key, so the mutable tags read like an oversight to anyone auditing it. They are not. Every action in the job is first-party `actions/*`, on the same tags release.yml and windows-sign-dryrun.yml already use while handling Apple codesign certs and Azure signing credentials. Pinning this one workflow would make it the only pinned one in the tree, and with no Dependabot or Renovate config to bump them, hand-pinned SHAs go stale unnoticed — trading a hypothetical risk for a certain one. The comment says to follow a repo-wide policy here if one is adopted.
|
Both review findings are resolved. Version/ref mismatch (P1). Fixed in Action pinning (P2). Settled as a non-issue for this workflow: every action in the publish job is first-party CI status. Green on |
|
Thanks for the approval. One thing to flag before v0.7.5 ships: publishing is gated on a FLATPAK_GPG_PRIVATE_KEY repository secret. Without it the workflow still builds both architectures and uploads artifacts, but the publish job skips and no repository is deployed, so the remote that users would add based on the docs wouldn't exist yet. Whoever sets the key will also need to set GitHub Pages to deploy from GitHub Actions. Happy to write up the key generation steps if that's useful. |
Great call out @AprilNEA would have the update the ENV variable before going live :) |
|
Just to clarify where it goes, it's a repository secret rather than an env variable, under |
Summary
Linux is the only platform that cannot update itself. The .deb, .rpm and .pkg.tar.zst packages ship with no repository behind them, and the in-app updater has no Linux artifact to offer: xtask release latest-json classifies only .dmg, .msi and .zip while the updater asks for tar.gz on Linux. Every Linux upgrade today is a manual download, which is what #605 runs into.
A Flatpak remote closes that. Install once, and flatpak update, or GNOME Software and KDE Discover in the background, carries the user forward. It also installs on atomic distributions, where layering an rpm is the current answer (#681).
Publishing is gated on a FLATPAK_GPG_PRIVATE_KEY secret. Without it the build still runs and uploads artifacts, so merging this changes nothing until you decide to turn publishing on and supply a key. Hosting and signing are yours to decide: the repository would live on this project's Pages.
Changes
packaging/linux/flatpak/
Only the build environment lives in the manifest, because that part is genuinely packaging's problem:
.github/workflows/flatpak.yml
Builds x86_64 and aarch64 on release: published, merges them into one OSTree repository, signs it, deploys to Pages. workflow_dispatch is build-only unless publishing is explicitly requested. Signing covers the commits as well as the summary: clients verify the commit they pull, and a summary-only signature fails every install with "GPG verification enabled, but no signatures found". The repository is rebuilt per release rather than appended to, since Pages caps a site at 1 GB.
docs/INSTALL-linux.md
A Flatpak section covering install, updates, and the host setup below.
.gitignore
flatpak-builder output and scratch state.
Testing
Also worth stating plainly, and documented in docs/INSTALL-linux.md: a Flatpak cannot write to /etc, so the udev rules must be installed on the host or no devices are detected at all. The app opens to an empty device list, which reads as a broken package rather than a missing setup step. The rules ship inside the app so that step needs no checkout.
Fixes #371