iboard/scripts/ci/android-signing.sh
cheney d5a31e5366
Some checks failed
Android Build & Publish / build-android (push) Failing after 39m54s
修改签名脚本
2026-08-08 08:28:49 +08:00

113 lines
4.6 KiB
Bash

#!/usr/bin/env bash
# CI 专用: 为 Tauri Android release 构建注入 release 签名配置
# 在 `tauri android init` 之后、`tauri android build` 之前运行。
#
# 依赖 (由调用方注入环境变量, 不要写死密钥到脚本/仓库):
# ANDROID_KEYSTORE_B64 - base64 编码的 keystore 文件内容 (CI secret)
# ANDROID_KEY_ALIAS - 密钥别名 (CI secret/variable)
# ANDROID_KEY_PASSWORD - store & key 密码 (CI secret; 本脚本两者用同一个)
#
# 作用:
# 1. 把 base64 密钥解码写到 $RUNNER_TEMP/iboard-release.keystore
# 2. 生成 gen/android/keystore.properties (Tauri 签名约定读取此文件)
# 3. 修改 gen/android/app/build.gradle.kts, 添加 signingConfigs.release
# 并让 buildTypes.release 使用它, 产出已签名 APK
set -euo pipefail
APP_GRADLE="src-tauri/gen/android/app/build.gradle.kts"
echo "[signing] 注入 Android release 签名配置..."
# --- 1. 解码 keystore ---
if [ -z "${ANDROID_KEYSTORE_B64:-}" ]; then
echo "[signing] ERROR: ANDROID_KEYSTORE_B64 未设置, 无法签名 release APK" >&2
exit 1
fi
: "${ANDROID_KEY_ALIAS:?ANDROID_KEY_ALIAS 未设置}"
: "${ANDROID_KEY_PASSWORD:?ANDROID_KEY_PASSWORD 未设置}"
KEYSTORE_FILE="${RUNNER_TEMP:-/tmp}/iboard-release.keystore"
echo "${ANDROID_KEYSTORE_B64}" | base64 -d > "$KEYSTORE_FILE"
# --- 2. 写 keystore.properties (Tauri 官方约定的签名配置文件位置) ---
# 注意: 不能写进 git, 这是运行时生成物
KEYSTORE_PROPERTIES="src-tauri/gen/android/keystore.properties"
cat > "$KEYSTORE_PROPERTIES" <<EOF
keyAlias=${ANDROID_KEY_ALIAS}
password=${ANDROID_KEY_PASSWORD}
storeFile=${KEYSTORE_FILE}
EOF
# --- 3. 修改 build.gradle.kts 注入 signingConfigs ---
if [ ! -f "$APP_GRADLE" ]; then
echo "[signing] ERROR: 找不到 $APP_GRADLE (请先运行 tauri android init)" >&2
exit 1
fi
# 幂等: 已注入则跳过
if grep -q 'create("release")' "$APP_GRADLE" 2>/dev/null; then
echo "[signing] build.gradle.kts 已有 release signingConfigs, 跳过注入"
else
# 在 android { 块内 buildTypes { 之前插入 signingConfigs 块
# 用 Python 处理 Kotlin DSL, 对模板结构做最小侵入
python3 - "$APP_GRADLE" <<'PYEOF'
import sys, re
path = sys.argv[1]
src = open(path, encoding='utf-8').read()
# Gradle Kotlin DSL 默认 import java.util.* (Properties 短名可用), 但没有 java.io.*
# 因此顶部需补 import java.io.FileInputStream, 注入块内全部用短名
if 'import java.io.FileInputStream' not in src:
# 在第一个 import 之后插入; 若无 import 则插到文件顶部
imp = re.search(r'^import .*$', src, flags=re.M)
new_import = 'import java.io.FileInputStream\n'
if imp:
src = src[:imp.end()] + '\n' + new_import + src[imp.end():]
else:
src = new_import + src
# 定位 android { 块内的 buildTypes { (注意 Kotlin 嵌套花括号)
m = re.search(r'(\n[ \t]*)(buildTypes\s*\{)', src)
if not m:
print('[signing] 未找到 buildTypes 块, 中止', file=sys.stderr)
sys.exit(1)
indent = m.group(1) # 含换行, e.g. "\n "
inner_indent = indent + ' '
signing_block = (
f'{inner_indent}signingConfigs {{\n'
f'{inner_indent} create("release") {{\n'
f'{inner_indent} val keystorePropertiesFile = rootProject.file("keystore.properties")\n'
f'{inner_indent} val keystoreProperties = Properties()\n'
f'{inner_indent} if (keystorePropertiesFile.exists()) {{\n'
f'{inner_indent} keystoreProperties.load(FileInputStream(keystorePropertiesFile))\n'
f'{inner_indent} }}\n'
f'{inner_indent} keyAlias = keystoreProperties["keyAlias"] as? String ?: ""\n'
f'{inner_indent} keyPassword = keystoreProperties["password"] as? String ?: ""\n'
f'{inner_indent} storeFile = file(keystoreProperties["storeFile"] as? String ?: "")\n'
f'{inner_indent} storePassword = keystoreProperties["password"] as? String ?: ""\n'
f'{inner_indent} }}\n'
f'{inner_indent}}}\n'
)
# 在 buildTypes { 前插入 signingConfigs 块
src = src.replace(m.group(0), signing_block + m.group(0), 1)
# 让 buildTypes 里的 release 使用该 signingConfig
rel = re.search(r'(\n[ \t]*)(getByName\("release"\)\s*\{)', src)
if not rel:
rel = re.search(r'(\n[ \t]*)(release\s*\{)', src)
if rel:
rel_indent = rel.group(1) + ' '
inject = rel_indent + 'signingConfig = signingConfigs.getByName("release")\n'
src = src.replace(rel.group(0), rel.group(0) + inject, 1)
open(path, 'w', encoding='utf-8').write(src)
print('[signing] build.gradle.kts 已注入 import + signingConfigs + release signingConfig')
PYEOF
fi
echo "[signing] 完成: keystore.properties 已写, build.gradle.kts 已注入"