#!/bin/bash set -euo pipefail # 专用:上传本地 APK 到服务器,覆盖 # /opt/agent/agents/android-webview-app/app/release/app-release.apk # 并同步版本元数据(build.gradle.kts + APP_CHANGELOG.md) # 支持命令行自动打包(assembleRelease)+ 上传 # ===== 可按需覆盖(环境变量优先)===== REMOTE_HOST="${REMOTE_HOST:-59.110.19.30}" REMOTE_USER="${REMOTE_USER:-root}" REMOTE_PORT="${REMOTE_PORT:-22}" REMOTE_APK_PATH="${REMOTE_APK_PATH:-/opt/agent/agents/android-webview-app/app/release/app-release.apk}" REMOTE_GRADLE_PATH="${REMOTE_GRADLE_PATH:-/opt/agent/agents/android-webview-app/app/build.gradle.kts}" REMOTE_CHANGELOG_PATH="${REMOTE_CHANGELOG_PATH:-/opt/agent/agents/android-webview-app/APP_CHANGELOG.md}" REMOTE_PASS="${REMOTE_PASS:-}" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" ANDROID_APP_DIR="${ANDROID_APP_DIR:-$SCRIPT_DIR/android-webview-app}" LOCAL_APK_PATH="${LOCAL_APK_PATH:-}" LOCAL_GRADLE_PATH="${LOCAL_GRADLE_PATH:-$SCRIPT_DIR/android-webview-app/app/build.gradle.kts}" LOCAL_CHANGELOG_PATH="${LOCAL_CHANGELOG_PATH:-$SCRIPT_DIR/android-webview-app/APP_CHANGELOG.md}" BUILD_APK="${BUILD_APK:-1}" # 1=先打包再上传;0=仅上传 SSH_OPTS=( -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ) log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" } need_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "缺少命令: $1"; exit 1; } } main() { need_cmd ssh need_cmd scp if [[ "$BUILD_APK" == "1" ]]; then if [[ ! -d "$ANDROID_APP_DIR" ]]; then echo "Android 工程目录不存在: $ANDROID_APP_DIR" exit 1 fi if [[ ! -x "$ANDROID_APP_DIR/gradlew" ]]; then echo "未找到可执行的 gradlew: $ANDROID_APP_DIR/gradlew" exit 1 fi log "先执行 Android 打包: assembleRelease" ( cd "$ANDROID_APP_DIR" ./gradlew assembleRelease ) fi # 自动探测默认 APK 路径(按优先级) if [[ -z "$LOCAL_APK_PATH" ]]; then if [[ -f "$ANDROID_APP_DIR/app/build/outputs/apk/release/app-release.apk" ]]; then LOCAL_APK_PATH="$ANDROID_APP_DIR/app/build/outputs/apk/release/app-release.apk" elif [[ -f "$ANDROID_APP_DIR/app/build/outputs/apk/release/app-release-unsigned.apk" ]]; then LOCAL_APK_PATH="$ANDROID_APP_DIR/app/build/outputs/apk/release/app-release-unsigned.apk" elif [[ -f "$ANDROID_APP_DIR/app/release/app-release.apk" ]]; then LOCAL_APK_PATH="$ANDROID_APP_DIR/app/release/app-release.apk" fi fi if [[ ! -f "$LOCAL_APK_PATH" ]]; then echo "本地 APK 不存在: $LOCAL_APK_PATH" echo "尝试过路径:" echo " - $ANDROID_APP_DIR/app/build/outputs/apk/release/app-release.apk" echo " - $ANDROID_APP_DIR/app/build/outputs/apk/release/app-release-unsigned.apk" echo " - $ANDROID_APP_DIR/app/release/app-release.apk" echo "可用方式: BUILD_APK=1 bash upload_android_apk.sh" echo "或指定现成包: BUILD_APK=0 LOCAL_APK_PATH=/your/app-release.apk bash upload_android_apk.sh" exit 1 fi if [[ ! -f "$LOCAL_GRADLE_PATH" ]]; then echo "本地版本文件不存在: $LOCAL_GRADLE_PATH" exit 1 fi if [[ ! -f "$LOCAL_CHANGELOG_PATH" ]]; then echo "本地更新说明不存在: $LOCAL_CHANGELOG_PATH" exit 1 fi log "本地 APK: $LOCAL_APK_PATH" if [[ "$LOCAL_APK_PATH" == *"-unsigned.apk" ]]; then log "错误:当前是 unsigned APK,无法用于覆盖安装更新。请先配置签名后重新打包。" log "需要环境变量:ANDROID_KEYSTORE_PATH / ANDROID_KEYSTORE_PASSWORD / ANDROID_KEY_ALIAS / ANDROID_KEY_PASSWORD" exit 1 fi log "本地版本文件: $LOCAL_GRADLE_PATH" log "本地更新说明: $LOCAL_CHANGELOG_PATH" log "目标服务器: $REMOTE_USER@$REMOTE_HOST:$REMOTE_APK_PATH" local remote_apk_dir remote_gradle_dir remote_changelog_dir remote_apk_dir="$(dirname "$REMOTE_APK_PATH")" remote_gradle_dir="$(dirname "$REMOTE_GRADLE_PATH")" remote_changelog_dir="$(dirname "$REMOTE_CHANGELOG_PATH")" if [[ -n "$REMOTE_PASS" ]]; then need_cmd sshpass log "创建远程目录: $remote_apk_dir / $remote_gradle_dir / $remote_changelog_dir" sshpass -p "$REMOTE_PASS" ssh -p "$REMOTE_PORT" "${SSH_OPTS[@]}" "$REMOTE_USER@$REMOTE_HOST" \ "mkdir -p '$remote_apk_dir' '$remote_gradle_dir' '$remote_changelog_dir'" log "上传并覆盖 APK + 版本元数据" sshpass -p "$REMOTE_PASS" scp -P "$REMOTE_PORT" "${SSH_OPTS[@]}" "$LOCAL_APK_PATH" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_APK_PATH" sshpass -p "$REMOTE_PASS" scp -P "$REMOTE_PORT" "${SSH_OPTS[@]}" "$LOCAL_GRADLE_PATH" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_GRADLE_PATH" sshpass -p "$REMOTE_PASS" scp -P "$REMOTE_PORT" "${SSH_OPTS[@]}" "$LOCAL_CHANGELOG_PATH" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_CHANGELOG_PATH" log "远程文件检查" sshpass -p "$REMOTE_PASS" ssh -p "$REMOTE_PORT" "${SSH_OPTS[@]}" "$REMOTE_USER@$REMOTE_HOST" \ "ls -lh '$REMOTE_APK_PATH' '$REMOTE_GRADLE_PATH' '$REMOTE_CHANGELOG_PATH'" else log "使用 SSH Key 模式(未提供 REMOTE_PASS)" log "创建远程目录: $remote_apk_dir / $remote_gradle_dir / $remote_changelog_dir" ssh -p "$REMOTE_PORT" "${SSH_OPTS[@]}" "$REMOTE_USER@$REMOTE_HOST" \ "mkdir -p '$remote_apk_dir' '$remote_gradle_dir' '$remote_changelog_dir'" log "上传并覆盖 APK + 版本元数据" scp -P "$REMOTE_PORT" "${SSH_OPTS[@]}" "$LOCAL_APK_PATH" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_APK_PATH" scp -P "$REMOTE_PORT" "${SSH_OPTS[@]}" "$LOCAL_GRADLE_PATH" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_GRADLE_PATH" scp -P "$REMOTE_PORT" "${SSH_OPTS[@]}" "$LOCAL_CHANGELOG_PATH" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_CHANGELOG_PATH" log "远程文件检查" ssh -p "$REMOTE_PORT" "${SSH_OPTS[@]}" "$REMOTE_USER@$REMOTE_HOST" \ "ls -lh '$REMOTE_APK_PATH' '$REMOTE_GRADLE_PATH' '$REMOTE_CHANGELOG_PATH'" fi log "完成:服务器 APK 与版本信息已更新" } main "$@"