Our own repo, not a submission to f-droid.org — and the difference is not cosmetic. f-droid.org rebuilds from source and signs with their key, so an app already installed under our signature could not be upgraded by it; Android refuses a differently-signed APK over an existing install. This repo indexes the APK we already signed, so everybody who sideloaded from the website upgrades cleanly and then gets updates automatically. The working directory holds a signing keystore and its password and lives outside every checkout, because all four repos are public. The script refuses to run if the keystore is missing rather than re-initialising over a live repo — replacing the index key makes every client that has added the repository reject its updates. Version comes out of the APK via aapt2 rather than being typed, same rule as the update manifest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
3.5 KiB
Bash
Executable File
76 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Publish a built release APK into the Flamenet F-Droid repository.
|
|
#
|
|
# 🔴 **This is OUR OWN repository, not a submission to f-droid.org.** The
|
|
# difference is not cosmetic: f-droid.org rebuilds from source and signs with
|
|
# THEIR key, so an app already installed under our signature could not be
|
|
# upgraded by it — Android refuses a differently-signed APK over an existing
|
|
# install. This repo indexes the APK we already signed, so it upgrades cleanly
|
|
# for everybody who sideloaded from the website.
|
|
#
|
|
# 🔴 **The repo working directory holds a signing keystore and its password.**
|
|
# It lives OUTSIDE every git checkout on purpose — all four repos are public.
|
|
# Never move it in, and never redirect (`>`) over config.yml: that file holds
|
|
# the only on-disk copy of the keystore password, and this project has already
|
|
# clobbered a credentials file that way once.
|
|
#
|
|
# ⚠️ The repo index key is permanent. Replacing it makes every client that has
|
|
# added this repository reject its updates, silently, until they remove and
|
|
# re-add it. Back up ~/flamenet-fdroid off this machine.
|
|
#
|
|
# Usage: scripts/publish-fdroid.sh [path/to/app-release.apk]
|
|
set -euo pipefail
|
|
|
|
FDROID_DIR="${FDROID_DIR:-$HOME/flamenet-fdroid}"
|
|
FDROID_BIN="${FDROID_BIN:-}"
|
|
APK="${1:-app/build/outputs/apk/release/app-release.apk}"
|
|
REMOTE="${FDROID_REMOTE:-ovh}"
|
|
REMOTE_DIR="${FDROID_REMOTE_DIR:-/srv/prod/messenger/fdroid}"
|
|
|
|
[ -f "$APK" ] || { echo "no APK at $APK — build it first" >&2; exit 1; }
|
|
[ -d "$FDROID_DIR" ] || { echo "no repo at $FDROID_DIR" >&2; exit 1; }
|
|
[ -f "$FDROID_DIR/keystore.p12" ] || {
|
|
echo "no keystore in $FDROID_DIR — refusing to re-init over a live repo" >&2; exit 1; }
|
|
|
|
if [ -z "$FDROID_BIN" ]; then
|
|
echo "set FDROID_BIN to the fdroid executable (a venv with fdroidserver)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
export JAVA_HOME="${JAVA_HOME:-/opt/homebrew/opt/openjdk@21}"
|
|
export PATH="$JAVA_HOME/bin:$PATH"
|
|
export ANDROID_HOME="${ANDROID_HOME:-$HOME/Library/Android/sdk}"
|
|
|
|
# Name the file by its real version, read out of the APK rather than typed —
|
|
# same rule as the update manifest.
|
|
aapt2="$(find "$ANDROID_HOME/build-tools" -maxdepth 2 -name aapt2 -type f | sort -V | tail -1)"
|
|
badging="$("$aapt2" dump badging "$APK")"
|
|
name="$(sed -n "s/.*versionName='\([^']*\)'.*/\1/p" <<<"$badging" | head -1)"
|
|
[ -n "$name" ] || { echo "could not read versionName from $APK" >&2; exit 1; }
|
|
|
|
echo "publishing $APK as version $name"
|
|
cp "$APK" "$FDROID_DIR/repo/flamenet-messenger-$name.apk"
|
|
|
|
cd "$FDROID_DIR"
|
|
# `update` re-reads every APK in repo/, rebuilds the index and signs it. Older
|
|
# releases move to archive/ per `archive_older` rather than being deleted, so a
|
|
# version somebody is pinned to does not vanish.
|
|
"$FDROID_BIN" update --pretty
|
|
|
|
echo "syncing to $REMOTE:$REMOTE_DIR"
|
|
rsync -az --delete -e ssh repo/ "$REMOTE:/tmp/fdroid-repo-new/"
|
|
[ -d archive ] && rsync -az --delete -e ssh archive/ "$REMOTE:/tmp/fdroid-archive-new/" || true
|
|
# shellcheck disable=SC2029
|
|
ssh "$REMOTE" "set -e
|
|
sudo rm -rf $REMOTE_DIR/repo && sudo mkdir -p $REMOTE_DIR
|
|
sudo cp -r /tmp/fdroid-repo-new $REMOTE_DIR/repo && rm -rf /tmp/fdroid-repo-new
|
|
if [ -d /tmp/fdroid-archive-new ]; then
|
|
sudo rm -rf $REMOTE_DIR/archive
|
|
sudo cp -r /tmp/fdroid-archive-new $REMOTE_DIR/archive && rm -rf /tmp/fdroid-archive-new
|
|
fi
|
|
sudo chown -R root:root $REMOTE_DIR && sudo chmod -R a+rX $REMOTE_DIR"
|
|
|
|
echo
|
|
echo "published. verify it is actually being served:"
|
|
echo " curl -sS https://flamenetmessenger.com/fdroid/repo/index-v2.json | head -c 200"
|