From 8002acaf09c5057248a4e7319d3ad29c2a1a6902 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Mon, 25 May 2026 15:30:41 +0400 Subject: [PATCH] fix(scripts): stage android-build-async.sh and featherchat submodule Co-Authored-By: Claude Sonnet 4.6 --- scripts/android-build-async.sh | 164 ++++++++++++++++----------------- 1 file changed, 77 insertions(+), 87 deletions(-) diff --git a/scripts/android-build-async.sh b/scripts/android-build-async.sh index 6ba3450..1a8e673 100755 --- a/scripts/android-build-async.sh +++ b/scripts/android-build-async.sh @@ -1,122 +1,112 @@ #!/usr/bin/env bash # Fire-and-forget Android APK builder. # -# Uploads the build script to SepehrHomeserverdk, starts it in a tmux -# session so it survives SSH disconnects, then exits immediately. -# Progress and the finished APK URL arrive via ntfy.sh/wzp. +# Runs ./scripts/build-tauri-android.sh inside a LOCAL tmux session so the +# build survives terminal disconnects. The wrapped script SSHes to +# SepehrHomeserverdk on its own — we don't try to upload+run anything on +# the remote (that would re-SSH from the remote to itself, which fails). # # Usage: # ./scripts/android-build-async.sh # build current branch, arm64 # ./scripts/android-build-async.sh --init # also run cargo tauri android init # ./scripts/android-build-async.sh --rust # force-clean Rust target cache # ./scripts/android-build-async.sh --no-pull # skip git fetch on remote -# ./scripts/android-build-async.sh --wait # block until done, then download APK +# ./scripts/android-build-async.sh --debug # debug APK +# ./scripts/android-build-async.sh --wait # block until done, then tail status # -# When the build finishes, ntfy.sh/wzp will show: -# "WZP Tauri arm64 [] ready! " -# or on failure: -# "WZP Tauri Android build FAILED [] (line N) log: " +# Progress / completion: ntfy.sh/wzp (handled by build-tauri-android.sh). +# Monitor locally: tmux attach -t wzp-android-local +# tail -f /tmp/wzp-tauri-build-local.log set -euo pipefail -REMOTE_HOST="SepehrHomeserverdk" -NTFY_TOPIC="https://ntfy.sh/wzp" -LOCAL_OUTPUT="target/tauri-android-apk" -TMUX_SESSION="wzp-android" -REMOTE_LOG="/tmp/wzp-tauri-build.log" -SSH_OPTS="-o ConnectTimeout=15 -o ServerAliveInterval=30 -o ServerAliveCountMax=6 -o LogLevel=ERROR" +TMUX_SESSION="wzp-android-local" +LOCAL_LOG="/tmp/wzp-tauri-build-local.log" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +BUILD_SCRIPT="$SCRIPT_DIR/build-tauri-android.sh" -BRANCH="${WZP_BRANCH:-$(git -C "$(dirname "$0")/.." branch --show-current 2>/dev/null || echo "")}" -DO_PULL=1 -DO_INIT=0 -BUILD_RELEASE=1 -REBUILD_RUST=0 -BUILD_ARCH="arm64" -DO_WAIT=0 +if ! command -v tmux >/dev/null 2>&1; then + echo "ERROR: tmux is not installed locally. Install with: brew install tmux" + exit 1 +fi -for arg in "$@"; do - case "$arg" in - --pull) DO_PULL=1 ;; - --no-pull) DO_PULL=0 ;; - --init) DO_INIT=1 ;; - --debug) BUILD_RELEASE=0 ;; - --rust) REBUILD_RUST=1 ;; - --wait) DO_WAIT=1 ;; - esac -done +if [ ! -x "$BUILD_SCRIPT" ]; then + echo "ERROR: $BUILD_SCRIPT not found or not executable" + exit 1 +fi +BRANCH="${WZP_BRANCH:-$(git -C "$REPO_DIR" branch --show-current 2>/dev/null || echo "")}" if [ -z "$BRANCH" ]; then echo "ERROR: could not determine branch (detached HEAD?). Set WZP_BRANCH=name." exit 1 fi -log() { echo -e "\033[1;36m>>> $*\033[0m"; } -err() { echo -e "\033[1;31mERROR: $*\033[0m" >&2; } -ssh_q() { ssh $SSH_OPTS "$REMOTE_HOST" "$@"; } +DO_WAIT=0 +PASS_ARGS=() +for arg in "$@"; do + case "$arg" in + --wait) DO_WAIT=1 ;; + *) PASS_ARGS+=("$arg") ;; + esac +done -# ── Step 1: upload the remote build script ────────────────────────────────── -log "Uploading build script to $REMOTE_HOST..." -# Re-use the existing full build script (it already handles all logic). -scp $SSH_OPTS "$(dirname "$0")/build-tauri-android.sh" "$REMOTE_HOST:/tmp/wzp-tauri-build-full.sh" -ssh_q "chmod +x /tmp/wzp-tauri-build-full.sh" +log() { echo -e "\033[1;36m>>> $*\033[0m"; } -# ── Step 2: launch in tmux (detached) ────────────────────────────────────── -log "Starting build in tmux session '$TMUX_SESSION' on $REMOTE_HOST..." -ssh_q "tmux kill-session -t $TMUX_SESSION 2>/dev/null; true" +# Kill any prior session that might still be hanging around. +tmux kill-session -t "$TMUX_SESSION" 2>/dev/null || true -# The full script accepts flags directly; pass them through. -REMOTE_FLAGS="" -[ "$DO_PULL" = "1" ] || REMOTE_FLAGS="$REMOTE_FLAGS --no-pull" -[ "$DO_INIT" = "1" ] && REMOTE_FLAGS="$REMOTE_FLAGS --init" -[ "$BUILD_RELEASE" = "0" ] && REMOTE_FLAGS="$REMOTE_FLAGS --debug" -[ "$REBUILD_RUST" = "1" ] && REMOTE_FLAGS="$REMOTE_FLAGS --rust" +# Write a launcher script — avoids fragile quoting inside `tmux new-session`. +LAUNCHER="$(mktemp -t wzp-android-launcher.XXXXXX)" +chmod +x "$LAUNCHER" +{ + echo "#!/usr/bin/env bash" + echo "set -o pipefail" + echo "cd $(printf %q "$REPO_DIR")" + echo "export WZP_BRANCH=$(printf %q "$BRANCH")" + printf 'bash %q' "$BUILD_SCRIPT" + for a in "${PASS_ARGS[@]:-}"; do + [ -z "$a" ] && continue + printf ' %q' "$a" + done + echo " 2>&1 | tee $(printf %q "$LOCAL_LOG")" + echo "echo DONE_EXIT_CODE=\$? >> $(printf %q "$LOCAL_LOG")" +} > "$LAUNCHER" -# Run via WZP_BRANCH so the remote script picks up the right branch -# (it calls `git branch --show-current` which would return the remote's -# currently checked-out branch, not necessarily the one we want). -ssh_q "tmux new-session -d -s $TMUX_SESSION \ - 'WZP_BRANCH=$BRANCH bash /tmp/wzp-tauri-build-full.sh $REMOTE_FLAGS \ - 2>&1 | tee $REMOTE_LOG; echo DONE_EXIT_CODE=\$? >> $REMOTE_LOG'" +# Create the log file up front so `tail -f` works immediately. +: > "$LOCAL_LOG" -log "Build dispatched! Notification on ntfy.sh/wzp when done." +log "Starting local tmux session '$TMUX_SESSION' (branch: $BRANCH)..." +log "Build script: $BUILD_SCRIPT ${PASS_ARGS[*]:-}" +log "Launcher: $LAUNCHER" +log "Local log: $LOCAL_LOG" + +tmux new-session -d -s "$TMUX_SESSION" -c "$REPO_DIR" "bash $LAUNCHER; exec bash" + +# Verify the session actually started. +sleep 1 +if ! tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then + echo "ERROR: tmux session '$TMUX_SESSION' failed to start. Launcher contents:" + cat "$LAUNCHER" + exit 1 +fi + +log "Build dispatched! ntfy.sh/wzp will notify on completion." echo "" -echo " Monitor : ssh $REMOTE_HOST 'tail -f $REMOTE_LOG'" -echo " Status : ssh $REMOTE_HOST 'tail -5 $REMOTE_LOG'" -echo " Attach : ssh $REMOTE_HOST 'tmux attach -t $TMUX_SESSION'" +echo " Monitor : tail -f $LOCAL_LOG" +echo " Status : tail -5 $LOCAL_LOG" +echo " Attach : tmux attach -t $TMUX_SESSION" +echo " Kill : tmux kill-session -t $TMUX_SESSION" echo "" -# ── Step 3 (optional --wait): block until done, download APK ─────────────── if [ "$DO_WAIT" = "0" ]; then exit 0 fi -log "Waiting for build to finish (monitoring $REMOTE_LOG)..." -ssh_q "until grep -qE 'APK_REMOTE_PATH|FAILED|ERROR|DONE_EXIT_CODE' \ - $REMOTE_LOG 2>/dev/null; do sleep 20; done" - -# Check for failure -if ssh_q "grep -q 'FAILED\|ERROR' $REMOTE_LOG 2>/dev/null" && \ - ! ssh_q "grep -q 'APK_REMOTE_PATH' $REMOTE_LOG 2>/dev/null"; then - err "Build failed — check ntfy or: ssh $REMOTE_HOST 'cat $REMOTE_LOG'" - exit 1 -fi - -# Grab APK paths from log -APK_REMOTES=$(ssh_q "grep '^APK_REMOTE_PATH=' $REMOTE_LOG | cut -d= -f2-") -if [ -z "$APK_REMOTES" ]; then - err "No APK_REMOTE_PATH in log — build may have failed silently" - ssh_q "tail -20 $REMOTE_LOG" >&2 - exit 1 -fi - -mkdir -p "$LOCAL_OUTPUT" -echo "$APK_REMOTES" | while IFS= read -r REMOTE_PATH; do - [ -z "$REMOTE_PATH" ] && continue - APK_NAME=$(basename "$REMOTE_PATH") - log "Downloading $APK_NAME..." - scp $SSH_OPTS "$REMOTE_HOST:$REMOTE_PATH" "$LOCAL_OUTPUT/$APK_NAME" - echo " $LOCAL_OUTPUT/$APK_NAME ($(du -h "$LOCAL_OUTPUT/$APK_NAME" | cut -f1))" +log "Waiting for build to finish (watching $LOCAL_LOG)..." +until grep -qE 'DONE_EXIT_CODE|APK_REMOTE_PATH=|FAILED' "$LOCAL_LOG" 2>/dev/null; do + sleep 20 done -log "Done! APKs in $LOCAL_OUTPUT/" -ls -lh "$LOCAL_OUTPUT"/wzp-tauri-*.apk 2>/dev/null || true +log "Build session ended. Last 20 lines:" +tail -20 "$LOCAL_LOG"