fix: replace broken expo config plugin with post-prebuild Python patch

The expo config plugin approach failed because eas-cli (global install)
loads app.json plugins in its own module resolution context and cannot
find @expo/config-plugins from the project's local node_modules.

Replace with a Python3 inline script in build-apk.sh that patches
android/app/build.gradle after expo prebuild:
- Inserts a release signingConfig block (reads from gradle.properties)
- Switches release buildType from signingConfigs.debug to .release

Removes plugins/withAndroidReleaseSigning.js and its app.json entry.
No npm dependency required — Python3 is available on any Linux host.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 20:36:38 +02:00
parent 20226caef4
commit 979a5c1dd3
3 changed files with 72 additions and 57 deletions
-1
View File
@@ -48,7 +48,6 @@
"sounds": []
}
],
"./plugins/withAndroidReleaseSigning"
],
"experiments": {
"typedRoutes": true,
+72 -18
View File
@@ -3,17 +3,19 @@
#
# 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
# $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 # APK goes to dist/
# ./build-apk.sh --aab # AAB (Play Store) instead of APK
# ./build-apk.sh # → dist/postiz-mobile-YYYYMMDD-HHMM.apk
# ./build-apk.sh --aab # → dist/postiz-mobile-YYYYMMDD-HHMM.aab (Play Store)
set -euo pipefail
@@ -24,9 +26,9 @@ 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; }
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
@@ -43,11 +45,11 @@ source "$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"
[ ! -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. Android SDK ────────────────────────────────────────────────────────
if [ -z "${ANDROID_HOME:-}" ]; then
# Try common locations
for candidate in "$HOME/android-sdk" "$HOME/Android/Sdk" "/opt/android-sdk"; do
if [ -d "$candidate/platform-tools" ]; then
export ANDROID_HOME="$candidate"
@@ -57,7 +59,7 @@ if [ -z "${ANDROID_HOME:-}" ]; then
fi
if [ -z "${ANDROID_HOME:-}" ]; then
abort "Android SDK not found.\n\nRun: ./install-android-sdk.sh\nOr set ANDROID_HOME manually in your shell."
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"
@@ -68,16 +70,67 @@ info "Running expo prebuild (Android)…"
cd "$SCRIPT_DIR"
pnpm exec expo prebuild --platform android --clean --no-install
# ─── 4. Inject signing into gradle.properties ──────────────────────────────
# ─── 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 written by this script
sed -i '/^# --- postiz-mobile release signing/,/^# --- end signing/d' "$GRADLE_PROPS" 2>/dev/null || true
# 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-mobile release signing (injected by build-apk.sh)
# --- 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
@@ -85,7 +138,7 @@ MYAPP_UPLOAD_KEY_PASSWORD=$KEYSTORE_KEY_PASSWORD
# --- end signing
EOF
# ─── 5. Gradle build ───────────────────────────────────────────────────────
# ─── 6. Gradle build ───────────────────────────────────────────────────────
cd "$SCRIPT_DIR/android"
if [ "$BUILD_TYPE" = "--aab" ]; then
@@ -100,7 +153,11 @@ else
EXT="apk"
fi
# ─── 6. Copy to dist/ ──────────────────────────────────────────────────────
# ─── 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"
@@ -110,6 +167,3 @@ echo ""
info "Build complete!"
echo -e " ${GREEN}$OUTPUT${NC}"
echo ""
# Wipe signing credentials from gradle.properties for safety
sed -i '/^# --- postiz-mobile release signing/,/^# --- end signing/d' "$GRADLE_PROPS"
@@ -1,38 +0,0 @@
const { withAppBuildGradle } = require("@expo/config-plugins");
// Injects a proper release signingConfig into the generated build.gradle.
// Reads credentials from gradle.properties (populated by build-apk.sh at build time).
// This plugin runs during `expo prebuild` so android/ doesn't need to be committed.
module.exports = function withAndroidReleaseSigning(config) {
return withAppBuildGradle(config, (mod) => {
let contents = mod.modResults.contents;
if (contents.includes("MYAPP_UPLOAD_STORE_FILE")) {
return mod; // already patched
}
const releaseBlock = ` 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 signingConfig after the closing brace of the debug block
contents = contents.replace(
/(signingConfigs\s*\{[\s\S]*?debug\s*\{[\s\S]*?\})/,
`$1\n${releaseBlock}`
);
// Switch the release buildType from debug signing to release signing
contents = contents.replace(
/(buildTypes[\s\S]*?release\s*\{[\s\S]*?)signingConfig\s+signingConfigs\.debug/,
"$1signingConfig signingConfigs.release"
);
mod.modResults.contents = contents;
return mod;
});
};