Files
Postiz-android/artifacts/postiz-mobile/build-apk.sh
T
billisdead aaf6b2aa07 fix: force JAVA_HOME to ~/jdk21 when system Java ≥ 25
Gradle 8.x supports up to Java 24. Fedora 44 ships Java 25 by default,
causing "Unsupported class file major version 69" at build time.

build-apk.sh now auto-detects system Java version and falls back to
~/jdk21 (Temurin 21 LTS) when Java ≥ 25 is detected.
README documents the one-time JDK 21 install step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:52:54 +02:00

183 lines
7.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# build-apk.sh — Build a signed release APK locally without expo.dev / EAS.
#
# Prerequisites (first time only):
# 1. Export EAS keystore:
# cd artifacts/postiz-mobile
# eas credentials --platform android
# → "Download existing keystore" → save to ~/.config/postiz-mobile/postiz-mobile.jks
# 2. Fill in signing credentials:
# cp ~/.config/postiz-mobile/signing.env.example ~/.config/postiz-mobile/signing.env
# $EDITOR ~/.config/postiz-mobile/signing.env
# 3. Install Android SDK (if not already):
# ./install-android-sdk.sh
# # then add ANDROID_HOME to your shell profile and reload it
#
# Usage:
# ./build-apk.sh # → dist/postiz-mobile-YYYYMMDD-HHMM.apk
# ./build-apk.sh --aab # → dist/postiz-mobile-YYYYMMDD-HHMM.aab (Play Store)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SIGNING_ENV="$HOME/.config/postiz-mobile/signing.env"
DIST_DIR="$SCRIPT_DIR/dist"
BUILD_TYPE="${1:-}"
# ─── Colours ───────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
info() { echo -e "${GREEN}[build]${NC} $*"; }
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
abort() { echo -e "${RED}[error]${NC} $*" >&2; exit 1; }
# ─── 1. Signing credentials ────────────────────────────────────────────────
if [ ! -f "$SIGNING_ENV" ]; then
abort "Missing signing.env.\n\n cp ~/.config/postiz-mobile/signing.env.example ~/.config/postiz-mobile/signing.env\n # then fill in your keystore path and passwords"
fi
# shellcheck source=/dev/null
source "$SIGNING_ENV"
[ -z "${KEYSTORE_PATH:-}" ] && abort "KEYSTORE_PATH not set in signing.env"
[ -z "${KEYSTORE_ALIAS:-}" ] && abort "KEYSTORE_ALIAS not set in signing.env"
[ -z "${KEYSTORE_STORE_PASSWORD:-}" ] && abort "KEYSTORE_STORE_PASSWORD not set in signing.env"
[ -z "${KEYSTORE_KEY_PASSWORD:-}" ] && abort "KEYSTORE_KEY_PASSWORD not set in signing.env"
KEYSTORE_PATH_EXPANDED="${KEYSTORE_PATH/#\$HOME/$HOME}"
KEYSTORE_PATH_EXPANDED="${KEYSTORE_PATH_EXPANDED/#~/$HOME}"
[ ! -f "$KEYSTORE_PATH_EXPANDED" ] && \
abort "Keystore not found: $KEYSTORE_PATH_EXPANDED\n\nExport it from EAS:\n eas credentials --platform android\n → Download existing keystore → save to $KEYSTORE_PATH_EXPANDED"
# ─── 2. Java 17/21 — Gradle requires Java ≤ 24 (system Java 25 is too new) ──
# Use ~/jdk21 if present, otherwise rely on JAVA_HOME already being set correctly.
if [ -z "${JAVA_HOME:-}" ] || "$JAVA_HOME/bin/java" -version 2>&1 | grep -qE '"(2[5-9]|[3-9][0-9])\.' ; then
if [ -d "$HOME/jdk21" ]; then
export JAVA_HOME="$HOME/jdk21"
export PATH="$JAVA_HOME/bin:$PATH"
info "Using local JDK 21: $JAVA_HOME"
else
abort "Java 25+ detected but Gradle only supports ≤ Java 24.\n\nInstall JDK 21 locally:\n wget -O /tmp/jdk21.tar.gz https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.7%2B6/OpenJDK21U-jdk_x64_linux_hotspot_21.0.7_6.tar.gz\n mkdir -p ~/jdk21 && tar -xzf /tmp/jdk21.tar.gz -C ~/jdk21 --strip-components=1"
fi
fi
info "Java: $("$JAVA_HOME/bin/java" -version 2>&1 | head -1)"
# ─── 3. Android SDK ────────────────────────────────────────────────────────
if [ -z "${ANDROID_HOME:-}" ]; then
for candidate in "$HOME/android-sdk" "$HOME/Android/Sdk" "/opt/android-sdk"; do
if [ -d "$candidate/platform-tools" ]; then
export ANDROID_HOME="$candidate"
break
fi
done
fi
if [ -z "${ANDROID_HOME:-}" ]; then
abort "Android SDK not found.\n\nRun: ./install-android-sdk.sh\nThen: export ANDROID_HOME=\"\$HOME/android-sdk\" && source ~/.bashrc"
fi
export PATH="$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin"
info "Android SDK: $ANDROID_HOME"
# ─── 4. expo prebuild ──────────────────────────────────────────────────────
info "Running expo prebuild (Android)…"
cd "$SCRIPT_DIR"
pnpm exec expo prebuild --platform android --clean --no-install
# ─── 4. Patch build.gradle — inject release signingConfig ──────────────────
info "Patching android/app/build.gradle for release signing…"
python3 - "$SCRIPT_DIR/android/app/build.gradle" << 'PYEOF'
import sys, re
path = sys.argv[1]
with open(path, 'r') as f:
content = f.read()
if 'MYAPP_UPLOAD_STORE_FILE' in content:
print('[patch] build.gradle already patched, skipping.')
sys.exit(0)
release_signing = """\n release {
if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
storeFile file(MYAPP_UPLOAD_STORE_FILE)
storePassword MYAPP_UPLOAD_STORE_PASSWORD
keyAlias MYAPP_UPLOAD_KEY_ALIAS
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
}
}"""
# Insert release block right after the closing brace of the debug signingConfig
content = re.sub(
r'(signingConfigs\s*\{[\s\S]*?debug\s*\{[\s\S]*?\})',
r'\1' + release_signing,
content,
count=1
)
# Switch release buildType from debug signing to release signing
# Only replace the first occurrence after "release {" (not the debug one)
def replace_release_signing(m):
return m.group(0).replace('signingConfig signingConfigs.debug',
'signingConfig signingConfigs.release', 1)
content = re.sub(
r'release\s*\{[^}]*signingConfig\s+signingConfigs\.debug',
replace_release_signing,
content,
count=1,
flags=re.DOTALL
)
with open(path, 'w') as f:
f.write(content)
print('[patch] build.gradle patched for release signing.')
PYEOF
# ─── 5. Inject signing props into gradle.properties ────────────────────────
info "Injecting signing credentials into gradle.properties…"
GRADLE_PROPS="$SCRIPT_DIR/android/gradle.properties"
# Remove any previous signing block left by this script
sed -i '/^# --- postiz release signing/,/^# --- end signing/d' "$GRADLE_PROPS" 2>/dev/null || true
cat >> "$GRADLE_PROPS" << EOF
# --- postiz release signing (injected by build-apk.sh — wiped after build)
MYAPP_UPLOAD_STORE_FILE=$KEYSTORE_PATH_EXPANDED
MYAPP_UPLOAD_STORE_PASSWORD=$KEYSTORE_STORE_PASSWORD
MYAPP_UPLOAD_KEY_ALIAS=$KEYSTORE_ALIAS
MYAPP_UPLOAD_KEY_PASSWORD=$KEYSTORE_KEY_PASSWORD
# --- end signing
EOF
# ─── 6. Gradle build ───────────────────────────────────────────────────────
cd "$SCRIPT_DIR/android"
if [ "$BUILD_TYPE" = "--aab" ]; then
info "Building AAB (release)…"
./gradlew bundleRelease
ARTIFACT="app/build/outputs/bundle/release/app-release.aab"
EXT="aab"
else
info "Building APK (release)…"
./gradlew assembleRelease
ARTIFACT="app/build/outputs/apk/release/app-release.apk"
EXT="apk"
fi
# ─── 7. Wipe credentials from gradle.properties ───────────────────────────
sed -i '/^# --- postiz release signing/,/^# --- end signing/d' "$GRADLE_PROPS"
info "Signing credentials wiped from gradle.properties."
# ─── 8. Copy to dist/ ─────────────────────────────────────────────────────
mkdir -p "$DIST_DIR"
TIMESTAMP="$(date +%Y%m%d-%H%M)"
OUTPUT="$DIST_DIR/postiz-mobile-$TIMESTAMP.$EXT"
cp "$ARTIFACT" "$OUTPUT"
echo ""
info "Build complete!"
echo -e " ${GREEN}$OUTPUT${NC}"
echo ""