Sign the Android build with a real key, and let package.sh use it too
Benchmarks / CPU and I/O (per commit) (push) Successful in 2m52s
Benchmarks / Frame budget (on demand) (push) Skipped
Build and test / Desktop (Linux) (push) Successful in 44m13s
Build and test / Layer separation (push) Successful in 56s
🐳 Android image / Build and push (push) Successful in 17m16s
Build and test / android-image (push) Successful in 17m17s
Traceability / Requirement traces (push) Successful in 1m6s
Build and test / Android (aarch64) (push) Successful in 23m37s

The release keystore now exists and its four secrets are loaded into
Gitea, so CI produces an APK a device can update in place. Until now
every build, CI and local alike, was signed with a throwaway debug key
-- CI's fresh per run, the local one exactly as durable as the cache
directory it lived in -- and the night that cache was cleared, no build
anywhere could install over the tablet's copy.

package.sh forwards KEYSTORE_PASS, KEY_PASS and KEY_ALIAS into the
container and copies the keystore under the mounted target directory
for the build, so a local release-signed build is one environment line.
The doc records where the local copy of the key lives.
This commit is contained in:
2026-09-11 23:22:28 +02:00
parent 7c44740d9f
commit a2c7789007
2 changed files with 41 additions and 0 deletions
+25
View File
@@ -68,11 +68,36 @@ SO="${CACHE}/target/jniLibs/${ABI}/libdarkroom.so"
# at /work and the cache's target directory at /work/target-android, so every # at /work and the cache's target directory at /work/target-android, so every
# default in that script already points at the right place. # default in that script already points at the right place.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
#
# Release signing, when asked for. assemble-apk.sh selects it by the presence
# of KEYSTORE_PASS (see its header), and the keystore has to be reachable from
# inside the container, so a host path in KEYSTORE is copied under the mounted
# target directory for the duration of the build and removed after. The
# passwords travel as environment, never as arguments -- docs/android-signing.md
# has the incantation.
# ---------------------------------------------------------------------------
echo "==> packaging APK" echo "==> packaging APK"
SIGNING_ENV=()
CONTAINER_KEYSTORE=""
if [[ -n "${KEYSTORE_PASS:-}" ]]; then
[[ -f "${KEYSTORE:-}" ]] || { echo "error: KEYSTORE_PASS is set but KEYSTORE is not a file" >&2; exit 1; }
install -m 600 "${KEYSTORE}" "${CACHE}/target/release.keystore"
CONTAINER_KEYSTORE="${CACHE}/target/release.keystore"
SIGNING_ENV=(
KEYSTORE=/work/target-android/release.keystore
KEYSTORE_PASS="${KEYSTORE_PASS}"
KEY_PASS="${KEY_PASS:-${KEYSTORE_PASS}}"
KEY_ALIAS="${KEY_ALIAS:?KEY_ALIAS is required when KEYSTORE_PASS is set}"
)
fi
"${HERE}/build.sh" env \ "${HERE}/build.sh" env \
ABI="${ABI}" RUST_TARGET="${RUST_TARGET}" \ ABI="${ABI}" RUST_TARGET="${RUST_TARGET}" \
DARKROOM_DEBUGGABLE="${DARKROOM_DEBUGGABLE:-}" \ DARKROOM_DEBUGGABLE="${DARKROOM_DEBUGGABLE:-}" \
"${SIGNING_ENV[@]}" \
/work/docker/android/assemble-apk.sh /work/docker/android/assemble-apk.sh
if [[ -n "${CONTAINER_KEYSTORE}" ]]; then
rm -f "${CONTAINER_KEYSTORE}"
fi
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 3. Install from the host. # 3. Install from the host.
+16
View File
@@ -35,6 +35,22 @@ beyond telling everybody to uninstall and reinstall.
line, which keeps them out of shell history. Back the `.jks` up somewhere that line, which keeps them out of shell history. Back the `.jks` up somewhere that
is not this repository and not the machine that builds it. is not this repository and not the machine that builds it.
**The key exists, since 2026-09-11.** It was made as above, with a random
password, and the four secrets are loaded. The local copy is at
`~/.config/darkroom/signing/` on the development desktop — `darkroom-release.jks`
beside `storepass` and `keypass`, all mode 600 in a mode 700 directory. That
copy is what `package.sh` can sign with locally:
D=~/.config/darkroom/signing
KEYSTORE="$D/darkroom-release.jks" KEYSTORE_PASS="$(cat "$D/storepass")" \
KEY_ALIAS=darkroom ./docker/android/package.sh --install
Before it existed, every build — CI and local alike — was signed with a
throwaway debug key, and a debug key is exactly as durable as the cache
directory it lives in: the local one was regenerated the night the cache was
cleared, at which point no build anywhere could install over the device's copy.
Any device that received a build from before this date has to uninstall once.
## Loading the secrets ## Loading the secrets
base64 -w0 darkroom-release.jks > /tmp/ks.b64 base64 -w0 darkroom-release.jks > /tmp/ks.b64