build(android): add a side-by-side release build for validating R8
R8 has broken release APKs here before by stripping the JNI-loaded player and security classes, and the only way to reproduce that was to build with the real signing key and clobber the install you actually use. `./scripts/build-and-deploy.sh release --device --debug` now builds a fully minified release APK — exactly what ships — into the .debug applicationId slot, signed with the local debug keystore: release com.dtourolle.jellytau 0.5.5 release --debug com.dtourolle.jellytau.debug 0.5.5-debug-release debug com.dtourolle.jellytau.debug 0.5.5-debug It shares the applicationId *and* the signature with the plain debug build, so the two replace each other cleanly rather than colliding, and the versionName suffix says which is currently installed. No real key is needed, so the side-by-side path deliberately skips write-keystore-properties.sh. The flag reaches Gradle as JT_SIDE_BY_SIDE=1. CI never sets it, and the release manifest merges byte-identical without it — verified both ways through processUniversalReleaseMainManifest. deploy-android.sh and build-and-deploy.sh learned the flag too, since the APK path is unchanged but the package to launch is not.
This commit is contained in:
@@ -23,9 +23,18 @@ echo ""
|
||||
# which is what a distributable universal APK needs — but for an on-device test
|
||||
# it means three wasted Rust compiles. Pass --device (or ABI=aarch64) to build
|
||||
# only the connected device's architecture; --abi <t> targets one explicitly.
|
||||
#
|
||||
# Side-by-side: the `debug` build type always installs as
|
||||
# com.dtourolle.jellytau.debug ("JellyTau Debug"), so it never collides with a
|
||||
# real install. `release --debug` puts a *release* build — R8-minified, exactly
|
||||
# what ships — into that same slot, signed with the local debug keystore. That
|
||||
# is how you validate minification (R8 stripping JNI-loaded classes has broken
|
||||
# release APKs here before) without the real signing key and without
|
||||
# uninstalling the app you actually use.
|
||||
BUILD_TYPE="debug"
|
||||
CLEAN="${CLEAN:-0}"
|
||||
ABI="${ABI:-}"
|
||||
SIDE_BY_SIDE="${SIDE_BY_SIDE:-0}"
|
||||
next_is_abi=0
|
||||
for arg in "$@"; do
|
||||
if [ "$next_is_abi" = "1" ]; then
|
||||
@@ -37,10 +46,17 @@ for arg in "$@"; do
|
||||
--clean) CLEAN=1 ;;
|
||||
--abi) next_is_abi=1 ;;
|
||||
--device) ABI="device" ;;
|
||||
--debug|--side-by-side) SIDE_BY_SIDE=1 ;;
|
||||
debug|release) BUILD_TYPE="$arg" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# The debug build type is side-by-side unconditionally; the flag only means
|
||||
# something for a release build.
|
||||
if [ "$BUILD_TYPE" = "debug" ]; then
|
||||
SIDE_BY_SIDE=1
|
||||
fi
|
||||
|
||||
# Resolve --device to the attached device's Rust target triple.
|
||||
if [ "$ABI" = "device" ]; then
|
||||
device_abi="$(adb shell getprop ro.product.cpu.abi 2>/dev/null | tr -d '\r\n')"
|
||||
@@ -78,7 +94,14 @@ echo "🎨 Building frontend..."
|
||||
bun run build
|
||||
|
||||
# Step 2: Build Android APK
|
||||
if [ "$BUILD_TYPE" = "release" ]; then
|
||||
if [ "$BUILD_TYPE" = "release" ] && [ "$SIDE_BY_SIDE" = "1" ]; then
|
||||
# A release build in the debug slot: R8 still runs, but the applicationId is
|
||||
# suffixed and the debug keystore signs it (read by build.gradle.kts from
|
||||
# JT_SIDE_BY_SIDE), so the real key is not needed and it replaces any other
|
||||
# .debug install cleanly. Deliberately does NOT write keystore.properties.
|
||||
echo "📦 Building side-by-side release APK (com.dtourolle.jellytau.debug)..."
|
||||
JT_SIDE_BY_SIDE=1 bun run tauri android build --apk true "${TARGET_ARGS[@]}"
|
||||
elif [ "$BUILD_TYPE" = "release" ]; then
|
||||
# Configure release signing from .env (single source of truth). Must run
|
||||
# after sync-android-sources.sh, since gen/android is (re)generated there.
|
||||
./scripts/write-keystore-properties.sh
|
||||
|
||||
Reference in New Issue
Block a user