From a494eaa9e43d38153e0fc52ac1e378fe80ff6d4e Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Fri, 10 Jul 2026 19:38:17 -0500 Subject: [PATCH 1/3] packaging(flatpak): CI build/validate check + Flathub auto-update Add .github/workflows/flatpak-check.yml, mirroring aur-check.yml: it runs appstreamcli + desktop-file-validate on every change and a full flatpak-builder against the freedesktop 25.08 runtime once the release AppImage is published, so the package is verified without a Linux box. Add x-checker-data (GitHub releases JSON query) to the manifest so Flathub's flatpak-external-data-checker auto-opens url/sha256 bump PRs on each release. Rewrite the README's publishing section with the real org.zennotes.ZenNotes submission steps and drop the stale com.adibhanna app-id note (the id maps to zennotes.org, which we own). --- .github/workflows/flatpak-check.yml | 72 +++++++++++++++++++++ packaging/flatpak/README.md | 47 +++++++++++++- packaging/flatpak/org.zennotes.ZenNotes.yml | 11 +++- 3 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/flatpak-check.yml diff --git a/.github/workflows/flatpak-check.yml b/.github/workflows/flatpak-check.yml new file mode 100644 index 00000000..2f4c20b5 --- /dev/null +++ b/.github/workflows/flatpak-check.yml @@ -0,0 +1,72 @@ +name: Flatpak package check + +# Verifies packaging/flatpak actually builds and its AppStream/desktop metadata +# is valid, in a real Flatpak runtime container — so the Flathub submission can +# be validated without owning a Linux machine. +on: + push: + paths: + - "packaging/flatpak/**" + - ".github/workflows/flatpak-check.yml" + pull_request: + paths: + - "packaging/flatpak/**" + workflow_dispatch: + +permissions: + contents: read + +jobs: + # Fast feedback: validate the metadata Flathub reviewers (and appstream-compose) + # care about. Runs on every change, no container or build required. + validate: + name: Validate metadata + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Install validators + run: sudo apt-get update && sudo apt-get install -y appstream desktop-file-utils + + - name: Validate AppStream metainfo + run: appstreamcli validate --explain packaging/flatpak/org.zennotes.ZenNotes.metainfo.xml + + - name: Validate desktop entry + run: desktop-file-validate packaging/flatpak/org.zennotes.ZenNotes.desktop + + # Full flatpak-builder run against the same runtime Flathub uses. The manifest + # always points at the upcoming release's AppImage, which does not exist until + # that release is published, so mirror aur-check.yml: skip the build (but keep + # validating metadata above) when the asset isn't up yet. + build: + name: flatpak-builder + runs-on: ubuntu-latest + container: + image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-25.08 + options: --privileged + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Check whether the release AppImage is published + id: asset + run: | + set -uo pipefail + url=$(grep -oE 'https://github.com/[^[:space:]]+\.AppImage' \ + packaging/flatpak/org.zennotes.ZenNotes.yml | head -1) + echo "url=$url" + if curl -fsIL -o /dev/null "$url"; then + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + echo "::notice title=Flatpak build skipped::Release AppImage not published yet ($url). Metadata is still validated; the full flatpak-builder run happens once the release exists." + fi + + - name: Build the Flatpak + if: steps.asset.outputs.exists == 'true' + uses: flatpak/flatpak-github-actions/flatpak-builder@v6 + with: + bundle: zennotes.flatpak + manifest-path: packaging/flatpak/org.zennotes.ZenNotes.yml + cache-key: flatpak-builder-${{ github.sha }} diff --git a/packaging/flatpak/README.md b/packaging/flatpak/README.md index 4ac06bcc..b21e473a 100644 --- a/packaging/flatpak/README.md +++ b/packaging/flatpak/README.md @@ -61,6 +61,51 @@ sha256sum /tmp/ZenNotes.AppImage # 4. rebuild and smoke-test (see above) ``` +## Continuous validation + +`.github/workflows/flatpak-check.yml` validates this directory on every change: +it runs `appstreamcli validate` on the metainfo and `desktop-file-validate` on +the desktop entry, and (once the release AppImage is published) runs a full +`flatpak-builder` against the same freedesktop runtime Flathub uses. This is how +the package is verified without a Linux machine. + +## Publishing to Flathub + +The app-id `org.zennotes.ZenNotes` reverse-maps to `zennotes.org`, which we own, +so authorship can be verified on flathub.org after the app is live. Submission is +a one-time process: + +1. Make sure `flatpak-check.yml` is green on `main` (the full build passes). +2. Fork and create a branch **off the + `new-pr` branch** (not `master`). +3. Copy the four files from this directory to the fork's root, keeping names: + `org.zennotes.ZenNotes.yml`, `zennotes.sh`, `org.zennotes.ZenNotes.desktop`, + `org.zennotes.ZenNotes.metainfo.xml`. +4. Open a PR titled `Add org.zennotes.ZenNotes` against `flathub/flathub`'s + `new-pr` branch. A bot test-builds it; a reviewer then approves. +5. On merge, Flathub creates `flathub/org.zennotes.ZenNotes`, grants maintainer + access, and the build bot publishes. Then claim the verified badge on + flathub.org via the `zennotes.org` domain. + +Likely reviewer feedback to expect: a request to justify or narrow +`--filesystem=home`, and possibly to extract the `.deb` instead of the AppImage. + +## Ongoing updates + +Once on Flathub, the `x-checker-data` block in the manifest lets Flathub's +`flatpak-external-data-checker` bot auto-open a PR that bumps `url` + `sha256` +whenever a new GitHub release appears. The `` entry in the metainfo +still needs a manual note per version. Manual fallback: + +```sh +# 1. bump the `url` in org.zennotes.ZenNotes.yml to the new release tag +# 2. update the `sha256`: +curl -L -o /tmp/ZenNotes.AppImage \ + https://github.com/ZenNotes/zennotes/releases/download/v/ZenNotes--linux-x86_64.AppImage +sha256sum /tmp/ZenNotes.AppImage +# 3. bump the entry in org.zennotes.ZenNotes.metainfo.xml +``` + ## Notes & limitations - **Sandbox permissions:** `--filesystem=home` is granted so notes (plain @@ -69,5 +114,3 @@ sha256sum /tmp/ZenNotes.AppImage - **Auto-update is disabled** inside Flatpak (`electron-updater` cannot replace a read-only `/app`). Update via `flatpak update` once published, or rebuild with a new `url`/`sha256` for a local install. -- **Publishing to Flathub** would be a follow-up: it needs the `com.adibhanna.*` - app-id owner's sign-off plus screenshots in the AppStream metadata. diff --git a/packaging/flatpak/org.zennotes.ZenNotes.yml b/packaging/flatpak/org.zennotes.ZenNotes.yml index cc5492f1..8cef0649 100644 --- a/packaging/flatpak/org.zennotes.ZenNotes.yml +++ b/packaging/flatpak/org.zennotes.ZenNotes.yml @@ -46,11 +46,20 @@ modules: - install -Dm644 org.zennotes.ZenNotes.metainfo.xml /app/share/metainfo/org.zennotes.ZenNotes.metainfo.xml sources: - # Bump `url` + `sha256` on each release (see README.md). + # `url` + `sha256` are auto-bumped on each release by Flathub's + # flatpak-external-data-checker (see x-checker-data below); the manual + # steps in README.md are the fallback. - type: file url: https://github.com/ZenNotes/zennotes/releases/download/v2.13.1/ZenNotes-2.13.1-linux-x86_64.AppImage sha256: bbf3015fbc5fc775ce229e53f7f4977ce20a29fcd82e9737d7b10d5d8f8a4bdb dest-filename: ZenNotes.AppImage + x-checker-data: + type: json + url: https://api.github.com/repos/ZenNotes/zennotes/releases/latest + version-query: .tag_name | sub("^v"; "") + url-query: >- + .assets[] | select(.name | test("linux-x86_64\\.AppImage$")) + | .browser_download_url - type: file path: zennotes.sh - type: file From b93e9f616fe21026936337810de3b64ca12748b9 Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Fri, 10 Jul 2026 20:00:57 -0500 Subject: [PATCH 2/3] packaging(flatpak): narrow sandbox to XDG dirs for Flathub linter Flathub's flatpak-builder-lint rejects broad --filesystem=home (finish-args-home-filesystem-access), which failed the submission's manifest validation. Grant xdg-documents/xdg-download/xdg-desktop instead; vaults kept elsewhere can be re-granted via Flatseal. --- packaging/flatpak/README.md | 9 ++++++--- packaging/flatpak/org.zennotes.ZenNotes.yml | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packaging/flatpak/README.md b/packaging/flatpak/README.md index b21e473a..b0e38524 100644 --- a/packaging/flatpak/README.md +++ b/packaging/flatpak/README.md @@ -108,9 +108,12 @@ sha256sum /tmp/ZenNotes.AppImage ## Notes & limitations -- **Sandbox permissions:** `--filesystem=home` is granted so notes (plain - Markdown files) are reachable. Tighten it to a specific path (e.g. - `--filesystem=~/Notes`) if you prefer. +- **Sandbox permissions:** access is granted to `xdg-documents`, + `xdg-download`, and `xdg-desktop` so notes (plain Markdown files) in the usual + places are reachable. Flathub's linter rejects broad `--filesystem=home` + (`finish-args-home-filesystem-access`), so vaults kept elsewhere (e.g. + `~/Notes`, Dropbox) need the user to widen access with Flatseal or + `flatpak override --user --filesystem=home org.zennotes.ZenNotes`. - **Auto-update is disabled** inside Flatpak (`electron-updater` cannot replace a read-only `/app`). Update via `flatpak update` once published, or rebuild with a new `url`/`sha256` for a local install. diff --git a/packaging/flatpak/org.zennotes.ZenNotes.yml b/packaging/flatpak/org.zennotes.ZenNotes.yml index 8cef0649..be87f0dc 100644 --- a/packaging/flatpak/org.zennotes.ZenNotes.yml +++ b/packaging/flatpak/org.zennotes.ZenNotes.yml @@ -14,8 +14,12 @@ finish-args: - --socket=wayland - --device=dri - --socket=pulseaudio - # Notes are plain Markdown files on disk — allow access to the home dir. - - --filesystem=home + # Notes are plain Markdown files on disk. Flathub's linter blocks broad + # --filesystem=home, so grant the common user document dirs; users whose + # vaults live elsewhere can widen access with Flatseal / `flatpak override`. + - --filesystem=xdg-documents + - --filesystem=xdg-download + - --filesystem=xdg-desktop - --talk-name=org.freedesktop.Notifications modules: From c09619b97f2582f43dfc731d581e072f15bda2ff Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Fri, 10 Jul 2026 20:08:24 -0500 Subject: [PATCH 3/3] packaging(flatpak): per-arch AppImage sources for aarch64 build Flathub builds x86_64 AND aarch64; the manifest hardcoded the x64 AppImage, so the arm build failed with 'Exec format error'. Split into only-arches x86_64/aarch64 sources pointing at the x64 and arm64 AppImages (both already shipped in each release), each with its own x-checker-data. --- packaging/flatpak/org.zennotes.ZenNotes.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packaging/flatpak/org.zennotes.ZenNotes.yml b/packaging/flatpak/org.zennotes.ZenNotes.yml index be87f0dc..5e8c192e 100644 --- a/packaging/flatpak/org.zennotes.ZenNotes.yml +++ b/packaging/flatpak/org.zennotes.ZenNotes.yml @@ -50,10 +50,13 @@ modules: - install -Dm644 org.zennotes.ZenNotes.metainfo.xml /app/share/metainfo/org.zennotes.ZenNotes.metainfo.xml sources: - # `url` + `sha256` are auto-bumped on each release by Flathub's - # flatpak-external-data-checker (see x-checker-data below); the manual - # steps in README.md are the fallback. + # Flathub builds both x86_64 and aarch64, so each arch needs its own + # AppImage — a single-arch source fails the other arch with an + # "Exec format error". `url` + `sha256` are auto-bumped on each release by + # Flathub's flatpak-external-data-checker (per-arch x-checker-data below); + # the manual steps in README.md are the fallback. - type: file + only-arches: [x86_64] url: https://github.com/ZenNotes/zennotes/releases/download/v2.13.1/ZenNotes-2.13.1-linux-x86_64.AppImage sha256: bbf3015fbc5fc775ce229e53f7f4977ce20a29fcd82e9737d7b10d5d8f8a4bdb dest-filename: ZenNotes.AppImage @@ -64,6 +67,18 @@ modules: url-query: >- .assets[] | select(.name | test("linux-x86_64\\.AppImage$")) | .browser_download_url + - type: file + only-arches: [aarch64] + url: https://github.com/ZenNotes/zennotes/releases/download/v2.13.1/ZenNotes-2.13.1-linux-arm64.AppImage + sha256: dd3e8c9a39331b70c65390e3f44a6b8c349f1ce71fbd388aaa7b9b9afeb00a42 + dest-filename: ZenNotes.AppImage + x-checker-data: + type: json + url: https://api.github.com/repos/ZenNotes/zennotes/releases/latest + version-query: .tag_name | sub("^v"; "") + url-query: >- + .assets[] | select(.name | test("linux-arm64\\.AppImage$")) + | .browser_download_url - type: file path: zennotes.sh - type: file