feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
#!/usr/bin/env bash
|
2026-10-05 20:41:54 +02:00
|
|
|
# Updates the F-Droid repository at https://halkyon.app/fdroid/repo and
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
# uploads it: adds an APK if one is given, signs the index with the repository's
|
2026-10-13 23:11:40 +02:00
|
|
|
# key, and uploads everything to the halkyon.app server as the user fdroid, whose key can only
|
2026-10-23 15:09:31 +02:00
|
|
|
# write into the folder Caddy serves (rrsync). tool/release.dart runs it with each
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
# release's APK; run alone, it publishes the repository as it is, e.g. after its
|
|
|
|
|
# settings changed.
|
|
|
|
|
#
|
|
|
|
|
# tool/fdroid_repo.sh [APK]
|
|
|
|
|
# tool/fdroid_repo.sh --check (the tools, the key and its password only)
|
|
|
|
|
#
|
|
|
|
|
# The repository's working folder, outside Git, keeps every APK released so far:
|
|
|
|
|
# $HALKYON_FDROID_DIR (default below). Its settings and the apps' listings come
|
|
|
|
|
# from tool/release/fdroid/, copied in at every run. The index key is a PKCS #12
|
|
|
|
|
# keystore at $HALKYON_FDROID_KEYSTORE, alias halkyon-fdroid, whose certificate's
|
|
|
|
|
# SHA-256 is pinned in tool/release/fdroid-index-certificate.sha256: an index
|
|
|
|
|
# signed otherwise would make the F-Droid app refuse the repository. Its password
|
|
|
|
|
# comes from $HALKYON_FDROID_KEYSTORE_PASSWORD, or is asked for; it's never
|
2026-10-30 17:05:02 +01:00
|
|
|
# written down. Needs fdroidserver v2.4.5 (pipx), rsync, curl, jq, a JDK, the Android
|
|
|
|
|
# SDK, and the ssh host ramiel-fdroid. APKs released before that the working folder
|
|
|
|
|
# lacks come from the repository first (restore, below).
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
set -euo pipefail
|
|
|
|
|
cd "$(git rev-parse --show-toplevel)"
|
|
|
|
|
|
|
|
|
|
readonly working="${HALKYON_FDROID_DIR:-$HOME/.local/share/halkyon-learn/fdroid}"
|
|
|
|
|
keystore="${HALKYON_FDROID_KEYSTORE:-$HOME/.local/share/halkyon-learn/fdroid-index.p12}"
|
|
|
|
|
readonly key_alias='halkyon-fdroid'
|
|
|
|
|
readonly pinned_file='tool/release/fdroid-index-certificate.sha256'
|
2026-10-14 00:30:26 +02:00
|
|
|
readonly upload_host='ramiel-fdroid'
|
2026-10-05 20:41:54 +02:00
|
|
|
readonly repo_url='https://halkyon.app/fdroid/repo'
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
|
|
|
|
|
fail() {
|
|
|
|
|
echo "✗ $*" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
step() { echo "▸ $*"; }
|
|
|
|
|
|
|
|
|
|
[ $# -le 1 ] || fail 'Usage: tool/fdroid_repo.sh [APK | --check]'
|
|
|
|
|
check_only=false
|
|
|
|
|
apk=''
|
|
|
|
|
case "${1:-}" in
|
|
|
|
|
--check) check_only=true ;;
|
|
|
|
|
'') ;;
|
|
|
|
|
*) apk="$1" ;;
|
|
|
|
|
esac
|
|
|
|
|
|
2026-10-30 17:05:02 +01:00
|
|
|
for tool in fdroid rsync curl jq; do
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
command -v "$tool" >/dev/null || fail "$tool is missing."
|
|
|
|
|
done
|
|
|
|
|
# fdroid takes jarsigner and keytool from the PATH, apksigner from the SDK.
|
|
|
|
|
jdk_bin=$(dirname "$(command -v java || echo /snap/android-studio/current/jbr/bin/java)")
|
|
|
|
|
[ -x "$jdk_bin/jarsigner" ] && [ -x "$jdk_bin/keytool" ] ||
|
|
|
|
|
fail 'No JDK found (jarsigner, keytool).'
|
|
|
|
|
export PATH="$jdk_bin:$PATH"
|
|
|
|
|
export ANDROID_HOME="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-$HOME/Android/Sdk}}"
|
|
|
|
|
|
|
|
|
|
[ -f "$keystore" ] || fail "No keystore at $keystore (HALKYON_FDROID_KEYSTORE)."
|
|
|
|
|
keystore=$(realpath "$keystore")
|
|
|
|
|
export HALKYON_FDROID_KEYSTORE="$keystore"
|
|
|
|
|
[ -f "$pinned_file" ] || fail "$pinned_file is missing."
|
|
|
|
|
pinned=$(grep -v '^#' "$pinned_file" | tr -d ' :\n' | tr 'a-f' 'A-F' || true)
|
|
|
|
|
[[ "$pinned" =~ ^[0-9A-F]{64}$ ]] || fail "$pinned_file holds no SHA-256."
|
|
|
|
|
|
|
|
|
|
if [ -z "${HALKYON_FDROID_KEYSTORE_PASSWORD:-}" ]; then
|
|
|
|
|
read -rsp "Password of $keystore: " HALKYON_FDROID_KEYSTORE_PASSWORD
|
|
|
|
|
echo
|
|
|
|
|
fi
|
|
|
|
|
export HALKYON_FDROID_KEYSTORE_PASSWORD
|
|
|
|
|
# The F-Droid app knows the repository by this fingerprint: the certificate's
|
|
|
|
|
# SHA-256 in capitals, without colons.
|
|
|
|
|
fingerprint=$(keytool -list -v -keystore "$keystore" -alias "$key_alias" \
|
|
|
|
|
-storepass:env HALKYON_FDROID_KEYSTORE_PASSWORD 2>/dev/null |
|
|
|
|
|
sed -n 's/^.*SHA256: *//p' | head -n 1 | tr -d ':' | tr 'a-f' 'A-F' || true)
|
|
|
|
|
[ -n "$fingerprint" ] || fail "Wrong password, or no key $key_alias in $keystore."
|
|
|
|
|
[ "$fingerprint" = "$pinned" ] ||
|
|
|
|
|
fail "The key $key_alias in $keystore isn't the one in $pinned_file."
|
|
|
|
|
if $check_only; then
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
step 'Updating the F-Droid repository'
|
|
|
|
|
mkdir -p "$working/repo"
|
2026-10-30 17:05:02 +01:00
|
|
|
|
|
|
|
|
# A working folder on another laptop, or a new one, holds none of the APKs released
|
|
|
|
|
# before, and the upload below mirrors it with --delete-after: so every APK the
|
|
|
|
|
# published indexes name (repo and archive) comes from the repository first, unless the
|
|
|
|
|
# folder has it, its SHA-256 checked against the index's either way. The index is the
|
|
|
|
|
# repository's own, over HTTPS; the check guards against a broken download, not
|
|
|
|
|
# against the halkyon.app server.
|
|
|
|
|
restore() {
|
|
|
|
|
local dir="$1" status name hash type
|
|
|
|
|
mkdir -p "$working/$dir"
|
|
|
|
|
status=$(curl -sSL -o "$working/$dir/.published-index" -w '%{http_code}' \
|
|
|
|
|
"${repo_url%/repo}/$dir/index-v1.json") || fail "Can't reach the published $dir index."
|
|
|
|
|
case "$status" in
|
|
|
|
|
200) ;;
|
|
|
|
|
404) return 0 ;; # nothing published there yet
|
|
|
|
|
*) fail "The published $dir index answered $status." ;;
|
|
|
|
|
esac
|
|
|
|
|
jq -r '.packages[][] | [.apkName, .hash, .hashType] | @tsv' "$working/$dir/.published-index" |
|
|
|
|
|
while IFS=$'\t' read -r name hash type; do
|
|
|
|
|
[ "$type" = sha256 ] || fail "$name: the index gives no SHA-256."
|
|
|
|
|
[[ "$name" =~ ^[A-Za-z0-9._-]+\.apk$ ]] || fail "An APK named $name in the index."
|
|
|
|
|
if [ ! -f "$working/$dir/$name" ]; then
|
|
|
|
|
echo " $dir/$name from the repository"
|
|
|
|
|
curl -sSfL -o "$working/$dir/$name.part" "${repo_url%/repo}/$dir/$name"
|
|
|
|
|
mv "$working/$dir/$name.part" "$working/$dir/$name"
|
|
|
|
|
fi
|
|
|
|
|
echo "$hash $working/$dir/$name" | sha256sum --check --quiet ||
|
|
|
|
|
fail "$dir/$name isn't the APK the index names."
|
|
|
|
|
done
|
|
|
|
|
rm "$working/$dir/.published-index"
|
|
|
|
|
}
|
|
|
|
|
restore repo
|
|
|
|
|
restore archive
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
cp -r tool/release/fdroid/. "$working/"
|
feat(app): what's new after an update, drafted by the release tool (ADR 0030, D61)
halkyon_app's WhatsNew reads what each release changed from the app's
assets/whats_new/ (<version>.<language>.txt, English and German, a change
a line): after an update a sheet lists every release since the one the
device showed last, newest first, once; Settings shows the running
version's again, above About. Nothing on a fresh install.
tool/release.dart drafts the missing texts from the commits that count
after "Go on?" (German marked TRANSLATE:), opens them in the editor until
they fit (no mark left, F-Droid's 500 characters) and commits them with
the version. The English is the Forgejo notes' What's new, each language
F-Droid's changelog of the build, written at publishing and copied in by
tool/fdroid_repo.sh. Learn and Train bundle their texts, Learn's 0.22.0
and Train's 0.1.0 written to start.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-31 19:36:20 +01:00
|
|
|
# What's new in the release as each language's changelog of its build
|
|
|
|
|
# (metadata/<app id>/<locale>/changelogs/<build>.txt), which tool/release.dart
|
|
|
|
|
# writes from the app's texts and names here; kept in the working folder after.
|
|
|
|
|
if [ -n "${HALKYON_FDROID_METADATA:-}" ]; then
|
|
|
|
|
cp -r "$HALKYON_FDROID_METADATA/." "$working/metadata/"
|
|
|
|
|
fi
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
# fdroid refuses a config.yml others can read.
|
|
|
|
|
chmod 600 "$working/config.yml"
|
2026-10-30 16:40:12 +01:00
|
|
|
# Each app's own icon in the F-Droid app (the repository's is the kingfisher,
|
build(todo): Todo deployable beside Learn's server, and released as an APK, on F-Droid and as a snap (ADR 0033, step 5)
deploy/compose.todo.yaml adds Todo's server at todo.halkyon.eu, a member
of Learn's register, its database halkyon_todo in the instance's
PostgreSQL, its image built as Train's. redeploy.sh and backup.sh go over
every app server .env switches on (train, todo). Each compose file names
its server to the register in a variable of its own
(INSTANCE_MEMBER_TRAIN, INSTANCE_MEMBER_TODO), which halkyon_base adds to
INSTANCE_MEMBERS, each address once, as a second compose file's default
would have replaced Train's.
apps/todo/release.dart configures the release tool for Todo's APK and
snap: a key of its own (pinned once made; until then nothing is
released), the F-Droid listing (Time, NonFreeNet), and the snap from
apps/todo/snap/, which the tool builds in a clone of the repository at the
tag with that folder in place of snap/, as snapcraft builds one recipe a
folder and the root's is Learn's. What's new for 0.1.0 in English and
German, now shown. Android's backup and transfer are off, as Train's
(D53): the reminders scheduled keep their tasks' titles unsealed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-02 15:35:40 +01:00
|
|
|
# halkyon.png in tool/release/fdroid/): Learn's and Todo's their snaps', Train's its
|
|
|
|
|
# launcher's source. fdroid can't find the launcher icon in a release APK, whose build shortens
|
2026-10-30 16:40:12 +01:00
|
|
|
# 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 \
|
build(todo): Todo deployable beside Learn's server, and released as an APK, on F-Droid and as a snap (ADR 0033, step 5)
deploy/compose.todo.yaml adds Todo's server at todo.halkyon.eu, a member
of Learn's register, its database halkyon_todo in the instance's
PostgreSQL, its image built as Train's. redeploy.sh and backup.sh go over
every app server .env switches on (train, todo). Each compose file names
its server to the register in a variable of its own
(INSTANCE_MEMBER_TRAIN, INSTANCE_MEMBER_TODO), which halkyon_base adds to
INSTANCE_MEMBERS, each address once, as a second compose file's default
would have replaced Train's.
apps/todo/release.dart configures the release tool for Todo's APK and
snap: a key of its own (pinned once made; until then nothing is
released), the F-Droid listing (Time, NonFreeNet), and the snap from
apps/todo/snap/, which the tool builds in a clone of the repository at the
tag with that folder in place of snap/, as snapcraft builds one recipe a
folder and the root's is Learn's. What's new for 0.1.0 in English and
German, now shown. Android's backup and transfer are off, as Train's
(D53): the reminders scheduled keep their tasks' titles unsealed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-02 15:35:40 +01:00
|
|
|
app.halkyon.train:apps/train/halkyon_train_flutter/assets/icon/halkyon_train_icon.png \
|
|
|
|
|
app.halkyon.todo:apps/todo/snap/gui/halkyon-todo.png; do
|
2026-10-30 16:40:12 +01:00
|
|
|
mkdir -p "$working/metadata/${icon%%:*}/en-US"
|
|
|
|
|
cp "${icon#*:}" "$working/metadata/${icon%%:*}/en-US/icon.png"
|
|
|
|
|
done
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
if [ -n "$apk" ]; then
|
|
|
|
|
[ -f "$apk" ] || fail "No APK at $apk."
|
fix(release): F-Droid's upload resumable alone, by content, and Forgejo asked again
Train's first release (31 Oct 2026) stopped twice after its tag was pushed:
- Forgejo answered 500 (a unique constraint) to the release: it enters a
pushed tag in its releases itself, a moment after the push. Asked again a
few seconds later, it makes the release of that entry.
- The F-Droid upload filled the halkyon.app server's disk: rsync compared by
time, and this laptop's working folder, restored from the repository, had
every APK anew, so all 1.9 GB went again. It compares by content now.
tool/with_signing_keys.sh fdroid [APK] runs tool/fdroid_repo.sh alone with
the index's key, for an upload that failed after its release was made, and
the script skips an APK the working folder holds already rather than adding
a second file of the same build, which fdroid refuses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-31 23:28:49 +01:00
|
|
|
# Once in the working folder (an earlier run whose upload failed), the same APK
|
|
|
|
|
# again would be a second file of the same build, which fdroid refuses.
|
|
|
|
|
apk_hash=$(sha256sum "$apk" | cut -d' ' -f1)
|
|
|
|
|
if sha256sum "$working"/repo/*.apk "$working"/archive/*.apk 2>/dev/null |
|
|
|
|
|
grep -q "^$apk_hash "; then
|
|
|
|
|
echo " $(basename "$apk") is in the repository already"
|
|
|
|
|
else
|
|
|
|
|
cp "$apk" "$working/repo/"
|
|
|
|
|
fi
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
fi
|
|
|
|
|
# Names every APK as F-Droid does (<app id>_<version code>.apk) and signs the
|
|
|
|
|
# indexes with the repository's key.
|
|
|
|
|
(cd "$working" && fdroid update --rename-apks)
|
|
|
|
|
|
|
|
|
|
step "Uploading it to $upload_host"
|
|
|
|
|
# The APKs and icons first, the indexes last, so the F-Droid app never reads an
|
fix(release): F-Droid's upload resumable alone, by content, and Forgejo asked again
Train's first release (31 Oct 2026) stopped twice after its tag was pushed:
- Forgejo answered 500 (a unique constraint) to the release: it enters a
pushed tag in its releases itself, a moment after the push. Asked again a
few seconds later, it makes the release of that entry.
- The F-Droid upload filled the halkyon.app server's disk: rsync compared by
time, and this laptop's working folder, restored from the repository, had
every APK anew, so all 1.9 GB went again. It compares by content now.
tool/with_signing_keys.sh fdroid [APK] runs tool/fdroid_repo.sh alone with
the index's key, for an upload that failed after its release was made, and
the script skips an APK the working folder holds already rather than adding
a second file of the same build, which fdroid refuses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-31 23:28:49 +01:00
|
|
|
# index naming a file that isn't there yet. By their contents (--checksum), not their
|
|
|
|
|
# times: a working folder restored on another laptop has every APK with a new time,
|
|
|
|
|
# and would send them all again (1.9 GB in October 2026, on a disk with less free).
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
for dir in repo archive; do
|
|
|
|
|
[ -d "$working/$dir" ] || continue
|
fix(release): F-Droid's upload resumable alone, by content, and Forgejo asked again
Train's first release (31 Oct 2026) stopped twice after its tag was pushed:
- Forgejo answered 500 (a unique constraint) to the release: it enters a
pushed tag in its releases itself, a moment after the push. Asked again a
few seconds later, it makes the release of that entry.
- The F-Droid upload filled the halkyon.app server's disk: rsync compared by
time, and this laptop's working folder, restored from the repository, had
every APK anew, so all 1.9 GB went again. It compares by content now.
tool/with_signing_keys.sh fdroid [APK] runs tool/fdroid_repo.sh alone with
the index's key, for an upload that failed after its release was made, and
the script skips an APK the working folder holds already rather than adding
a second file of the same build, which fdroid refuses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-31 23:28:49 +01:00
|
|
|
rsync -a --checksum --chmod=D755,F644 --exclude='index*' --exclude='entry.*' \
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
"$working/$dir/" "$upload_host:$dir/"
|
|
|
|
|
done
|
|
|
|
|
for dir in repo archive; do
|
|
|
|
|
[ -d "$working/$dir" ] || continue
|
fix(release): F-Droid's upload resumable alone, by content, and Forgejo asked again
Train's first release (31 Oct 2026) stopped twice after its tag was pushed:
- Forgejo answered 500 (a unique constraint) to the release: it enters a
pushed tag in its releases itself, a moment after the push. Asked again a
few seconds later, it makes the release of that entry.
- The F-Droid upload filled the halkyon.app server's disk: rsync compared by
time, and this laptop's working folder, restored from the repository, had
every APK anew, so all 1.9 GB went again. It compares by content now.
tool/with_signing_keys.sh fdroid [APK] runs tool/fdroid_repo.sh alone with
the index's key, for an upload that failed after its release was made, and
the script skips an APK the working folder holds already rather than adding
a second file of the same build, which fdroid refuses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-31 23:28:49 +01:00
|
|
|
rsync -a --checksum --chmod=D755,F644 --delete-after "$working/$dir/" "$upload_host:$dir/"
|
feat: an F-Droid repository at learn.halkyon.app
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>
2026-10-05 20:25:02 +02:00
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo " $repo_url?fingerprint=$fingerprint"
|