Publish Android packages to an internal F-Droid repository #111

Merged
albert merged 5 commits from docs/fdroid-repository-scope into main 2026-07-27 03:02:10 +00:00
Owner

Fixes #110
Relies on new fahrengit-451 F-Droid hosting at https://github.com/aarmea/fahrengit-451/pull/1

Fixes #110 Relies on new fahrengit-451 F-Droid hosting at https://github.com/aarmea/fahrengit-451/pull/1
Scoping pass for #110. The two hard prerequisites — a stable release
signing key and a monotonic versionCode — are already satisfied, so the
work is hosting and plumbing rather than design.

Forgejo has no F-Droid package registry, so unlike the .deb (where
Forgejo signs the index for us) we generate and sign the index and pick
a host. Compares four hosts and recommends serving a real static tree
from the fahrengit-451 stack, with the repo generated by a service
inside that compose stack reading Forgejo over the internal network —
no credentials, no deploy key, and no publish step in release.yml.

Also records what the ticket cannot deliver: F-Droid's unattended
updates need Android 12+ and F-Droid as installer of record, so the
companion app self-updates on phones but the Fire TV sticks do not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EmC6kNZDqCMWGkmXuwyEFo
The published F-Droid repository is generated on the server that hosts
git.armeafamily.com: a service in the fahrengit-451 stack downloads each
release's APK assets and this repo's dist/fdroid/metadata/ at the release
tag and runs `fdroid update`. So this repo owns the app listings and the
validation, and release.yml gains no publish step.

What lands here:

* dist/fdroid/metadata/*.yml — one listing per applicationId, with no
  version fields (fdroid reads versionCode/versionName from the APK, so
  VERSION stays the single source of truth). Each pins the release
  signing certificate via AllowedAPKSigningKeys.

* `shepherd package fdroid` — generates a repo from built APKs against a
  throwaway index key and asserts every APK reached the index. That
  assertion is the point: a key mismatch makes `fdroid update` log a
  warning, drop the APK, sign an index without it, and exit 0. Verified
  by pinning a wrong key and watching it happen.

* A release.yml step running it in the existing apk job, on dry runs
  too. The server publishes with nobody watching; this is the last place
  a broken listing or a wrongly-signed APK can surface.

* INSTALL.md gains an "Installing the Android apps" section covering
  both the F-Droid path and sideloading, and is explicit that unattended
  updates need Android 12+ with F-Droid as installer of record — so the
  companion app self-updates on phones and the Fire TV sticks do not.

Two footguns are documented where they bite: fdroidserver needs
--no-install-recommends (269 packages/300MB vs 67/78MB, the difference
being matplotlib+tk from androguard), and it signs the index with
/usr/lib/jvm/default-java/bin/jarsigner, preferring that path over every
other JDK and ignoring JAVA_HOME — so the default must be a JDK.

Server-side spec for the fahrengit-451 agent: docs/ai/history/
2026-07-26 003 fdroid-fahrengit-451-spec.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EmC6kNZDqCMWGkmXuwyEFo
The fahrengit-451 side is implemented. Three things changed while
building it, all worth keeping: metadata comes from the tag archive
rather than a git clone, snapshots hardlink only the APKs (a hardlinked
index would let the next run mutate the live repo before verification),
and the service is config-driven so that stack stays generic.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EmC6kNZDqCMWGkmXuwyEFo
keytool prints "SHA-256" with a hyphen, so the documented grep matched
nothing. Same fix as the bootstrap script.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EmC6kNZDqCMWGkmXuwyEFo
Bump to 0.3.1
All checks were successful
CI / Version harmony (pull_request) Successful in 12s
CI / Arch neutrality (pull_request) Successful in 11s
CI / ShellCheck (pull_request) Successful in 15s
CI / CI image (pull_request) Successful in 10m16s
CI / CI image (Android) (pull_request) Successful in 7m13s
CI / CI images (pull_request) Successful in 0s
CI / Rustfmt (pull_request) Successful in 12s
CI / Warm cargo registry (pull_request) Successful in 37s
CI / Android companion (unit tests) (pull_request) Successful in 42s
CI / Android media (cargo-ndk build) (pull_request) Successful in 2m5s
CI / Firewall E2E (pull_request) Successful in 3m50s
CI / Clippy (pull_request) Successful in 2m18s
CI / Build (pull_request) Successful in 5m55s
CI / Package (.deb smoke build) (pull_request) Successful in 3m6s
CI / E2E (pull_request) Successful in 6m37s
CI / Test (pull_request) Successful in 7m18s
3df569cbaa
albert merged commit 9a4789f691 into main 2026-07-27 03:02:10 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
albert/shepherd-launcher!111
No description provided.