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:
@@ -48,7 +48,6 @@
|
|||||||
"sounds": []
|
"sounds": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"./plugins/withAndroidReleaseSigning"
|
|
||||||
],
|
],
|
||||||
"experiments": {
|
"experiments": {
|
||||||
"typedRoutes": true,
|
"typedRoutes": true,
|
||||||
|
|||||||
@@ -3,17 +3,19 @@
|
|||||||
#
|
#
|
||||||
# Prerequisites (first time only):
|
# Prerequisites (first time only):
|
||||||
# 1. Export EAS keystore:
|
# 1. Export EAS keystore:
|
||||||
|
# cd artifacts/postiz-mobile
|
||||||
# eas credentials --platform android
|
# eas credentials --platform android
|
||||||
# → "Download existing keystore" → save to ~/.config/postiz-mobile/postiz-mobile.jks
|
# → "Download existing keystore" → save to ~/.config/postiz-mobile/postiz-mobile.jks
|
||||||
# 2. Fill in signing credentials:
|
# 2. Fill in signing credentials:
|
||||||
# cp ~/.config/postiz-mobile/signing.env.example ~/.config/postiz-mobile/signing.env
|
# 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):
|
# 3. Install Android SDK (if not already):
|
||||||
# ./install-android-sdk.sh
|
# ./install-android-sdk.sh
|
||||||
|
# # then add ANDROID_HOME to your shell profile and reload it
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# ./build-apk.sh # APK goes to dist/
|
# ./build-apk.sh # → dist/postiz-mobile-YYYYMMDD-HHMM.apk
|
||||||
# ./build-apk.sh --aab # AAB (Play Store) instead of APK
|
# ./build-apk.sh --aab # → dist/postiz-mobile-YYYYMMDD-HHMM.aab (Play Store)
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -24,9 +26,9 @@ BUILD_TYPE="${1:-}"
|
|||||||
|
|
||||||
# ─── Colours ───────────────────────────────────────────────────────────────
|
# ─── Colours ───────────────────────────────────────────────────────────────
|
||||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||||
info() { echo -e "${GREEN}[build]${NC} $*"; }
|
info() { echo -e "${GREEN}[build]${NC} $*"; }
|
||||||
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
|
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
|
||||||
abort() { echo -e "${RED}[error]${NC} $*" >&2; exit 1; }
|
abort() { echo -e "${RED}[error]${NC} $*" >&2; exit 1; }
|
||||||
|
|
||||||
# ─── 1. Signing credentials ────────────────────────────────────────────────
|
# ─── 1. Signing credentials ────────────────────────────────────────────────
|
||||||
if [ ! -f "$SIGNING_ENV" ]; then
|
if [ ! -f "$SIGNING_ENV" ]; then
|
||||||
@@ -43,11 +45,11 @@ source "$SIGNING_ENV"
|
|||||||
KEYSTORE_PATH_EXPANDED="${KEYSTORE_PATH/#\$HOME/$HOME}"
|
KEYSTORE_PATH_EXPANDED="${KEYSTORE_PATH/#\$HOME/$HOME}"
|
||||||
KEYSTORE_PATH_EXPANDED="${KEYSTORE_PATH_EXPANDED/#~/$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 ────────────────────────────────────────────────────────
|
# ─── 2. Android SDK ────────────────────────────────────────────────────────
|
||||||
if [ -z "${ANDROID_HOME:-}" ]; then
|
if [ -z "${ANDROID_HOME:-}" ]; then
|
||||||
# Try common locations
|
|
||||||
for candidate in "$HOME/android-sdk" "$HOME/Android/Sdk" "/opt/android-sdk"; do
|
for candidate in "$HOME/android-sdk" "$HOME/Android/Sdk" "/opt/android-sdk"; do
|
||||||
if [ -d "$candidate/platform-tools" ]; then
|
if [ -d "$candidate/platform-tools" ]; then
|
||||||
export ANDROID_HOME="$candidate"
|
export ANDROID_HOME="$candidate"
|
||||||
@@ -57,7 +59,7 @@ if [ -z "${ANDROID_HOME:-}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${ANDROID_HOME:-}" ]; then
|
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
|
fi
|
||||||
|
|
||||||
export PATH="$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin"
|
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"
|
cd "$SCRIPT_DIR"
|
||||||
pnpm exec expo prebuild --platform android --clean --no-install
|
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…"
|
info "Injecting signing credentials into gradle.properties…"
|
||||||
GRADLE_PROPS="$SCRIPT_DIR/android/gradle.properties"
|
GRADLE_PROPS="$SCRIPT_DIR/android/gradle.properties"
|
||||||
|
|
||||||
# Remove any previous signing block written by this script
|
# Remove any previous signing block left by this script
|
||||||
sed -i '/^# --- postiz-mobile release signing/,/^# --- end signing/d' "$GRADLE_PROPS" 2>/dev/null || true
|
sed -i '/^# --- postiz release signing/,/^# --- end signing/d' "$GRADLE_PROPS" 2>/dev/null || true
|
||||||
|
|
||||||
cat >> "$GRADLE_PROPS" << EOF
|
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_FILE=$KEYSTORE_PATH_EXPANDED
|
||||||
MYAPP_UPLOAD_STORE_PASSWORD=$KEYSTORE_STORE_PASSWORD
|
MYAPP_UPLOAD_STORE_PASSWORD=$KEYSTORE_STORE_PASSWORD
|
||||||
MYAPP_UPLOAD_KEY_ALIAS=$KEYSTORE_ALIAS
|
MYAPP_UPLOAD_KEY_ALIAS=$KEYSTORE_ALIAS
|
||||||
@@ -85,7 +138,7 @@ MYAPP_UPLOAD_KEY_PASSWORD=$KEYSTORE_KEY_PASSWORD
|
|||||||
# --- end signing
|
# --- end signing
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# ─── 5. Gradle build ───────────────────────────────────────────────────────
|
# ─── 6. Gradle build ───────────────────────────────────────────────────────
|
||||||
cd "$SCRIPT_DIR/android"
|
cd "$SCRIPT_DIR/android"
|
||||||
|
|
||||||
if [ "$BUILD_TYPE" = "--aab" ]; then
|
if [ "$BUILD_TYPE" = "--aab" ]; then
|
||||||
@@ -100,7 +153,11 @@ else
|
|||||||
EXT="apk"
|
EXT="apk"
|
||||||
fi
|
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"
|
mkdir -p "$DIST_DIR"
|
||||||
TIMESTAMP="$(date +%Y%m%d-%H%M)"
|
TIMESTAMP="$(date +%Y%m%d-%H%M)"
|
||||||
OUTPUT="$DIST_DIR/postiz-mobile-$TIMESTAMP.$EXT"
|
OUTPUT="$DIST_DIR/postiz-mobile-$TIMESTAMP.$EXT"
|
||||||
@@ -110,6 +167,3 @@ echo ""
|
|||||||
info "Build complete!"
|
info "Build complete!"
|
||||||
echo -e " ${GREEN}→ $OUTPUT${NC}"
|
echo -e " ${GREEN}→ $OUTPUT${NC}"
|
||||||
echo ""
|
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;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user