From f37086978d8ef23f1a7c3535c812bde10cfd7c39 Mon Sep 17 00:00:00 2001 From: littlecodedragon <253116839+littlecodedragon@users.noreply.github.com> Date: Mon, 27 Apr 2026 19:11:42 +0200 Subject: [PATCH] Add optional APK signing via Forgejo secrets. Decode keystore from secrets, sign unsigned APK artifacts with apksigner when configured, and prefer uploading signed APKs. --- .forgejo/workflows/build_release.yml | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/.forgejo/workflows/build_release.yml b/.forgejo/workflows/build_release.yml index f5c137be3..bacb31391 100755 --- a/.forgejo/workflows/build_release.yml +++ b/.forgejo/workflows/build_release.yml @@ -135,6 +135,49 @@ jobs: zip -qr "Komikku-mapping-${version_tag}.zip" app/build/outputs/mapping/release fi + - name: Sign APKs (optional) + shell: bash + env: + SIGNING_KEYSTORE_B64: ${{ secrets.SIGNING_KEYSTORE_B64 }} + SIGNING_KEYSTORE_PASSWORD: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} + SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} + SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} + run: | + set -euo pipefail + + if [ -z "${SIGNING_KEYSTORE_B64}" ] || [ -z "${SIGNING_KEYSTORE_PASSWORD}" ] || [ -z "${SIGNING_KEY_ALIAS}" ] || [ -z "${SIGNING_KEY_PASSWORD}" ]; then + echo "Signing secrets not fully set; keeping unsigned APKs." + exit 0 + fi + + keystore_file="$(mktemp)" + printf '%s' "${SIGNING_KEYSTORE_B64}" | base64 -d > "${keystore_file}" + + apksigner_bin="" + if command -v apksigner >/dev/null 2>&1; then + apksigner_bin="$(command -v apksigner)" + elif [ -n "${ANDROID_HOME:-}" ] && [ -d "${ANDROID_HOME}/build-tools" ]; then + apksigner_bin="$(ls -1 "${ANDROID_HOME}"/build-tools/*/apksigner 2>/dev/null | sort -V | tail -n 1 || true)" + fi + + if [ -z "${apksigner_bin}" ]; then + echo "apksigner not found in PATH or ANDROID_HOME/build-tools." + exit 1 + fi + + for unsigned_apk in Komikku-*-unsigned.apk; do + [ -e "${unsigned_apk}" ] || continue + signed_apk="${unsigned_apk/-unsigned.apk/.apk}" + "${apksigner_bin}" sign \ + --ks "${keystore_file}" \ + --ks-key-alias "${SIGNING_KEY_ALIAS}" \ + --ks-pass "pass:${SIGNING_KEYSTORE_PASSWORD}" \ + --key-pass "pass:${SIGNING_KEY_PASSWORD}" \ + --out "${signed_apk}" \ + "${unsigned_apk}" + "${apksigner_bin}" verify "${signed_apk}" + done + - name: Create or update release id: release shell: bash @@ -255,6 +298,13 @@ jobs: for file in Komikku-*.apk Komikku-mapping-*.zip; do [ -e "$file" ] || continue + if [ "${file#*-unsigned.apk}" != "${file}" ]; then + signed_candidate="${file/-unsigned.apk/.apk}" + if [ -e "${signed_candidate}" ]; then + continue + fi + fi + asset_name="$(basename "$file")" asset_id="$( python3 -c 'import json, sys; assets = json.load(open(sys.argv[1], encoding="utf-8")); name = sys.argv[2]; print(next((str(asset["id"]) for asset in assets if asset.get("name") == name), ""))' \