feat: an F-Droid repository at learn.halkyon.app
All checks were successful
CI / check (push) Successful in 9m16s
CI / deploy (push) Has been skipped

Releases also publish the APK in the project's own F-Droid repository,
https://learn.halkyon.app/fdroid/repo. tool/fdroid_repo.sh adds the APK,
signs the indexes with the repository's own key and uploads them to
ramiel as the user fdroid, whose key can only write into the folder
Caddy serves (rrsync), the APKs first and the indexes last.
tool/release.sh checks that key and its password before building and
publishes after the Forgejo release.

- tool/release/fdroid/ holds the repository's settings (Halkyon, the
  snap's icon) and the app's listing (the snap's text), with the
  anti-features TetheredNet (learn.halkyon.eu only, for now) and
  NonFreeNet (YouTube, the server's SSPL) declared with their reasons,
  in F-Droid's own definitions and with its icons (fdroiddata, AGPL v3).
- The index key's certificate is pinned: a new key would make the F-Droid
  app refuse the repository.
- fdroidserver v2.4.5, since Ubuntu's v2.2.1 knows neither TetheredNet
  nor reasons.

README and AGENTS.md describe it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-05 20:25:02 +02:00
commit ae2496335d
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -2,17 +2,19 @@
# Builds a release and publishes it: the Android APK (one for every phone, signed with
# the app's key) and the Linux snap, both connecting to learn.halkyon.eu, the project's
# instance; a list of their checksums signed with GPG; all of it as a release on
# code.halkyon.app, and the snap in the Snap Store's edge channel. Run on a developer's
# laptop, never in CI: the app's key never leaves it.
# code.halkyon.app, the APK in the F-Droid repository at learn.halkyon.app
# (tool/fdroid_repo.sh), and the snap in the Snap Store's edge channel. Run on a
# developer's laptop, never in CI: the app's key never leaves it.
#
# tool/release.sh v0.1.0
#
# Before: the version, with a build number above the last release's, in
# halkyon_learn_flutter/pubspec.yaml on main, pushed; the tag signed on that commit and
# pushed (git tag -s v0.1.0 -m 'Halkyon Learn 0.1.0' && git push origin v0.1.0);
# `snapcraft login` with the project's account. The script asks for the key's password
# and a Forgejo token (scope write:repository) first, checks both, and then runs
# unattended until GPG asks for its passphrase; neither is ever written down.
# `snapcraft login` with the project's account. The script asks for the key's password,
# the F-Droid repository key's password and a Forgejo token (scope write:repository)
# first, checks them, and then runs unattended until GPG asks for its passphrase (and
# ssh for the upload key's, unless an agent holds it); none is ever written down.
#
# The app's key is a PKCS #12 keystore at $HALKYON_ANDROID_KEYSTORE (default below), its
# alias $HALKYON_ANDROID_KEY_ALIAS. Its certificate's SHA-256 is committed in
@ -25,6 +27,7 @@ readonly forgejo='https://code.halkyon.app'
readonly repository='project-halkyon/halkyon_learn'
readonly pubspec='halkyon_learn_flutter/pubspec.yaml'
readonly certificate_file='tool/release/android-certificate.sha256'
readonly fdroid_certificate_file='tool/release/fdroid-index-certificate.sha256'
keystore="${HALKYON_ANDROID_KEYSTORE:-$HOME/.local/share/halkyon-learn/android-release.p12}"
readonly key_alias="${HALKYON_ANDROID_KEY_ALIAS:-halkyon-learn}"
@ -111,6 +114,13 @@ key_certificate=$(HALKYON_ANDROID_KEYSTORE_PASSWORD="$password" "$keytool" -list
[ "$key_certificate" = "$certificate" ] ||
fail "The key $key_alias in $keystore isn't the one in $certificate_file."
read -rsp "Password of the F-Droid repository's key: " HALKYON_FDROID_KEYSTORE_PASSWORD
echo
export HALKYON_FDROID_KEYSTORE_PASSWORD
tool/fdroid_repo.sh --check
fdroid_fingerprint=$(grep -v '^#' "$fdroid_certificate_file" | tr -d ' :\n' | tr 'a-f' 'A-F')
readonly fdroid_fingerprint
read -rsp "Forgejo token for $forgejo (write:repository): " token
echo
# The token goes to curl in a configuration read from a file descriptor, so it never
@ -187,6 +197,8 @@ the project's instance.
- **Android:** \`$apk\`, one APK for every phone, signed with the app's key; the \
SHA-256 of its certificate is \`$certificate\`.
- **F-Droid:** the same APK in the repository \
https://learn.halkyon.app/fdroid/repo?fingerprint=$fdroid_fingerprint
- **Linux:** \`$snap\`, also in the Snap Store: \`snap install halkyon-learn --edge\`.
\`SHA256SUMS\` lists the files' checksums, signed with the GPG key \`$signer\` \
@ -201,6 +213,10 @@ for file in "$apk" "$snap" SHA256SUMS SHA256SUMS.asc; do
done
echo " $forgejo/$repository/releases/tag/$tag"
step 'Publishing the APK in the F-Droid repository'
tool/fdroid_repo.sh "$out/$apk"
unset HALKYON_FDROID_KEYSTORE_PASSWORD
# Last, as the Store may hold a revision for review; the release above stands either way.
step "Uploading the snap to the Snap Store's edge channel (as $account)"
snapcraft upload --release=edge "$out/$snap" ||