Ctrl K
ComunidadGuías…

android/build-apk.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/bin/bash
# =============================================================================
# build-apk.sh — 一键构建安卓 APK 并发布到 releases 目录
#
# 安卓壳远程加载 https://mao.etarch.cn(与 Electron 一致),不再打包 desktop 前端。
# 前端改动部署 Web 即可;仅原生壳变更时需本脚本发 APK OTA。
#
# 用法:
#   ./build-apk.sh                  # 自动从根 CHANGELOG.md 提取版本
#   ./build-apk.sh --version 0.0.2  # 手动指定版本名(versionCode 仍自动递增)
#   ./build-apk.sh --dry-run        # 仅构建,不发布
#
# 环境要求:
#   - ANDROID_HOME 已设置
#   - MAO_KEYSTORE_PATH / MAO_KEYSTORE_PASSWORD / MAO_KEY_ALIAS / MAO_KEY_PASSWORD
#     已设置或写在 /opt/mao/keystore/keystore-credentials.env
#
# 产出:
#   - APK:   /opt/mao-data/uploads/releases/mao-android-<version>.apk
#   - JSON:  /opt/mao-data/uploads/releases/android-latest.json
# =============================================================================
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
ANDROID_DIR="$SCRIPT_DIR"
ANDROID_APP="$ANDROID_DIR/android/app"
RELEASES_DIR="/opt/mao-data/uploads/releases"
CHANGELOG_EXTRACT="$PROJECT_ROOT/scripts/changelog-extract.sh"
CHANGELOG_FILE="$PROJECT_ROOT/CHANGELOG.md"

# ---- 参数解析 ----
DRY_RUN=false
CUSTOM_VERSION=""
while [[ $# -gt 0 ]]; do
  case "$1" in
    --dry-run) DRY_RUN=true; shift ;;
    --version) CUSTOM_VERSION="$2"; shift 2 ;;
    *) echo "未知参数: $1"; exit 1 ;;
  esac
done

# ---- 加载签名凭据 ----
CRED_FILE="/opt/mao/keystore/keystore-credentials.env"
if [ -f "$CRED_FILE" ]; then
  set -a
  # shellcheck disable=SC1090
  source "$CRED_FILE"
  set +a
fi

# ---- 验证环境 ----
export ANDROID_HOME="${ANDROID_HOME:-/opt/android-sdk}"
if [ ! -d "$ANDROID_HOME" ]; then
  echo "错误:ANDROID_HOME 不存在: $ANDROID_HOME"; exit 1
fi
# JDK 21(Capacitor 7 Android 要求)
export JAVA_HOME="${JAVA_HOME:-/usr/lib/jvm/java-21-openjdk-amd64}"
if [ -z "${MAO_KEYSTORE_PATH:-}" ] || [ ! -f "$MAO_KEYSTORE_PATH" ]; then
  echo "错误:MAO_KEYSTORE_PATH 未设置或文件不存在"; exit 1
fi

# ---- 读取版本号 ----
if [ -n "$CUSTOM_VERSION" ]; then
  VERSION_NAME="$CUSTOM_VERSION"
else
  VERSION_NAME=$("$CHANGELOG_EXTRACT" version "$CHANGELOG_FILE")
  if [ -z "$VERSION_NAME" ]; then
    echo "错误:无法从 CHANGELOG.md 提取版本号,请使用 --version 手动指定"; exit 1
  fi
fi

# versionCode:已发布版本中最大 versionCode + 1(首次为 1)
LATEST_APK=$(ls -v "$RELEASES_DIR"/mao-android-*.apk 2>/dev/null | tail -1 || true)
if [ -n "$LATEST_APK" ]; then
  # 从 APK 文件名中提取 versionCode(mao-android-<name>-<code>.apk)
  LATEST_CODE=$(echo "$LATEST_APK" | grep -oP '(?<=-)\d+(?=\.apk$)' || echo "0")
  VERSION_CODE=$((LATEST_CODE + 1))
else
  VERSION_CODE=1
fi

echo "=========================================="
echo "  Mao Android APK 构建"
echo "=========================================="
echo "  版本: $VERSION_NAME (code: $VERSION_CODE)"
echo "  远程: https://mao.etarch.cn"
echo "  签名: $MAO_KEY_ALIAS @ $(basename "$MAO_KEYSTORE_PATH")"
echo "  发布: $RELEASES_DIR"
echo "=========================================="
echo ""

# ---- Step 1: Capacitor sync(web-stub + 远程 server.url)----
echo "[1/3] Capacitor sync..."
cd "$ANDROID_DIR"
npx cap copy android
npx cap update android
echo "      sync 完成"

# ---- Step 2: Gradle assembleRelease ----
echo "[2/3] Gradle assembleRelease..."
cd "$ANDROID_DIR/android"
chmod +x gradlew
export ANDROID_HOME
./gradlew assembleRelease \
  -PMAO_VERSION_CODE="$VERSION_CODE" \
  -PMAO_VERSION_NAME="$VERSION_NAME" \
  --no-daemon -q
APK_OUT="$ANDROID_APP/build/outputs/apk/release/app-release.apk"
if [ ! -f "$APK_OUT" ]; then
  echo "错误:APK 构建失败,产物不存在: $APK_OUT"; exit 1
fi
APK_SIZE=$(du -h "$APK_OUT" | cut -f1)
echo "      构建完成: $APK_SIZE"

# ---- dry-run:到此为止,不发布 ----
if $DRY_RUN; then
  echo ""
  echo "=========================================="
  echo "  DRY-RUN:仅构建,未发布"
  echo "  APK:  $APK_OUT"
  echo "=========================================="
  exit 0
fi

# ---- Step 3: 发布 ----
echo "[3/3] 发布 APK + 清单..."
mkdir -p "$RELEASES_DIR"

APK_NAME="mao-android-${VERSION_NAME}-${VERSION_CODE}.apk"
cp "$APK_OUT" "$RELEASES_DIR/$APK_NAME"

# 提取 changelog(安卓原生壳;无分节时回退 ota-text)
CHANGELOG=$("$CHANGELOG_EXTRACT" apk-ota-text "$VERSION_NAME" "$CHANGELOG_FILE")

# 生成 android-latest.json
cat > "$RELEASES_DIR/android-latest.json" <<ENDJSON
{
  "versionCode": $VERSION_CODE,
  "versionName": "$VERSION_NAME",
  "downloadUrl": "https://mao.etarch.cn/uploads/releases/$APK_NAME",
  "minVersionCode": 0,
  "changelog": "$CHANGELOG",
  "publishedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
ENDJSON

echo ""
echo "=========================================="
echo "  发布完成!"
echo "=========================================="
echo "  APK:  $RELEASES_DIR/$APK_NAME"
echo "  JSON: $RELEASES_DIR/android-latest.json"
echo "  版本: $VERSION_NAME ($VERSION_CODE)"
echo "=========================================="