build(train): Train is released as Learn is, with a key of its own, beside it in the F-Droid repository (ADR 0030, D58)

apps/train/release.dart configures the release tool for Train's APK on
train.halkyon.eu; its release builds sign with its own key when the tool
hands it over. Its F-Droid listing declares NonFreeDep for Polar's SDK and
NonFreeNet; the repository's script copies each app's icon. The key's
certificate is pinned once the key is made.

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-30 16:40:12 +01:00
commit 48951c1e1a
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
7 changed files with 180 additions and 12 deletions

View file

@ -82,12 +82,16 @@ mkdir -p "$working/repo"
cp -r tool/release/fdroid/. "$working/"
# fdroid refuses a config.yml others can read.
chmod 600 "$working/config.yml"
# Learn's own icon in the F-Droid app, the snap's (the repository's is the
# kingfisher, halkyon.png in tool/release/fdroid/): fdroid can't find the launcher
# icon in a release APK, whose build shortens the resources' paths (res/9w.png
# rather than res/mipmap-hdpi/ic_launcher.png; fdroidserver issue 885).
mkdir -p "$working/metadata/app.halkyon.learn/en-US"
cp snap/gui/halkyon-learn.png "$working/metadata/app.halkyon.learn/en-US/icon.png"
# Each app's own icon in the F-Droid app (the repository's is the kingfisher,
# halkyon.png in tool/release/fdroid/): Learn's the snap's, Train's its launcher's
# source. fdroid can't find the launcher icon in a release APK, whose build shortens
# the resources' paths (res/9w.png rather than res/mipmap-hdpi/ic_launcher.png;
# fdroidserver issue 885).
for icon in app.halkyon.learn:snap/gui/halkyon-learn.png \
app.halkyon.train:apps/train/halkyon_train_flutter/assets/icon/halkyon_train_icon.png; do
mkdir -p "$working/metadata/${icon%%:*}/en-US"
cp "${icon#*:}" "$working/metadata/${icon%%:*}/en-US/icon.png"
done
if [ -n "$apk" ]; then
[ -f "$apk" ] || fail "No APK at $apk."
cp "$apk" "$working/repo/"

View file

@ -1,8 +1,12 @@
# The anti-features the repository's apps declare, as the main F-Droid
# repository defines them: names, descriptions and icons from fdroiddata
# (https://gitlab.com/fdroid/fdroiddata, config/antiFeatures.yml and the icons
# beside it). The two icons are F-Droid's, under the GNU AGPL v3, fdroiddata's
# beside it). The icons are F-Droid's, under the GNU AGPL v3, fdroiddata's
# licence. fdroid copies them into the repository's icons.
NonFreeDep:
name: Non-Free Dependencies
description: This app depends on other non-free apps
icon: ic_antifeature_nonfreedep.png
NonFreeNet:
name: Non-Free Network Services
description: This app promotes or depends entirely on a non-free network service

View file

@ -1,3 +1,5 @@
# The categories the repository's apps are listed in.
Education:
name: Education
Sports & Health:
name: Sports & Health

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,40 @@
# Halkyon Train's listing in the F-Droid repository, and its anti-features with their
# reasons (Halkyon Train's ADR 0030, D36).
Categories:
- Sports & Health
License: AGPL-3.0-or-later
AuthorName: Halkyon
AuthorEmail: support@halkyon.app
WebSite: https://halkyon.app/train
SourceCode: https://code.halkyon.app/project-halkyon/halkyon
AntiFeatures:
NonFreeDep: It reads the Polar Loop through Polar's BLE SDK, which isn't free
software; the app's licence carries a permission to link it.
NonFreeNet: The Polar Loop's firmware comes from Polar's firmware service, and the
server's licence (SSPL) isn't a free licence by F-Droid's definition.
Name: Halkyon Train
Summary: Record runs, rides, walks and rows, sealed and synced between your devices
Description: |-
Halkyon Train records your runs, walks, hikes, rides and rows: the track by GPS,
heart rate from a chest strap or the Polar Loop, a bike's speed, cadence and
power sensors, and a rowing machine's strokes. It pauses by itself when you
stop, announces each kilometre, and follows interval plans and routes you plan
on the map, turn by turn.
Music from your Jellyfin server plays in time with your steps. Workouts go to
Health Connect and out as GPX, TCX or FIT.
The Polar Loop's days and nights (steps, sleep, Nightly Recharge, heart rate
around the clock) are read from the band on the phone, never through Polar's
cloud.
Everything is sealed on your phone with your account's keys before it reaches
the instance, which can't read it. You sign in with SimpleLogin, by Proton, or
with an email address, a password and an authenticator app. It connects to
train.halkyon.eu, the project's instance, or to any other: everything an
instance needs is in the repository, to run your own. The app is AGPL-3.0 and
the server SSPL-1.0, so all of its code is public.
Questions and reports: support@halkyon.app

View file

@ -0,0 +1,2 @@
# The SHA-256 of the certificate that signs Halkyon Train's Android releases (key alias
# halkyon-train), as keytool prints it. tool/release.dart releases no APK signed otherwise.

View file

@ -2,9 +2,13 @@
library;
import '../../../apps/learn/release.dart';
import '../../../apps/train/release.dart';
import 'app_release.dart';
/// Every app with a release configuration, by the id the tool takes. A new
/// app's configuration lives beside it (`apps/<id>/release.dart`) and is
/// added here.
final releasedApps = <String, AppRelease>{learnRelease.id: learnRelease};
final releasedApps = <String, AppRelease>{
learnRelease.id: learnRelease,
trainRelease.id: trainRelease,
};