docs: 补充「发布与更新」章节,归档 act_runner 安装脚本

- README 新增第 12 节:发版流程(打 tag)、必需 secrets、签名硬约束、
  应用内更新原理、runner 要求(host 模式复用现成 JDK/SDK)
- scripts/install-runner.sh:act_runner 安装与注册(host 模式),
  参数化 GITEA_URL / REG_TOKEN / LABELS,装成 systemd 服务
This commit is contained in:
jkooe committed 2026-11-09 17:32:01 +08:00
1 parent 43275ae7a0
commit 665baa0831
2 files changed
+167 -1

No files matched your search

+63 -1
View File
@@ -212,7 +212,69 @@ DSH_PET=/path/to/dsh-pet python3 scripts/gen_config.py
---
## 12. 参考与借鉴
## 12. 发布与更新
两条链路:**CI 构建**(Gitea Actions → Release)与**应用内更新**(App 读 Release → 下载 → 安装)。
### 发版流程
```bash
git push origin main # 代码先上 main
git tag v1.0.1002 && git push origin v1.0.1002 # 打 tag 触发构建 + 发版
```
打 tag 后 `.gitea/workflows/build.yml` 会:检出当前 ref 的代码 → **从 `full-assets` 分支叠加**
`assets_hq` / `assets_small` / `assets_net`(main 保持轻量,不追踪这三个目录)→ 用 `KEYSTORE_BASE64`
注入的固定密钥签 release 包 → 发布 APK 与 `version.json` 到该 tag 的 Release。
`versionCode = 1000 + run_number`,由 CI 注入。**必须单调递增**——系统只允许更高 versionCode
覆盖安装,版本号回退会导致手机装不上。
### 必需 secrets
仓库 → Settings → Actions,配 4 个:
| Secret | 内容 |
|---|---|
| `KEYSTORE_BASE64` | 发布密钥的 base64:`base64 -i petfloat-release.jks \| tr -d '\n'` |
| `KEYSTORE_PASSWORD` | keystore 口令 |
| `KEY_ALIAS` | `petfloat` |
| `KEY_PASSWORD` | 密钥口令(与上面相同即可) |
`GITEA_TOKEN` 由 Gitea 自动注入,**不需要配**(同名 secret 会被拒 400)。
> **签名是硬约束**:所有版本必须用同一把密钥。换密钥后已装用户无法覆盖升级,只能卸载重装,
> 记忆数据会一起丢。keystore 请离线备份。
### 应用内更新
`UpdateChecker` 的流程:
1. `GET /api/v1/repos/mtfyun/dsh-pet-floating/releases?limit=10`,跳过 draft,取 versionCode 最大的一条
2. 优先读 `version.json` 拿 versionCode / sha256 / 体积;读不到再从 tag 尾段解析
3. 与当前安装版本比 **versionCode**(用 versionName 按字符串比会把 `1.0.9` 判成比 `1.0.10` 新)
4. 下载到 `cacheDir/update/`,校验体积与 SHA256,不一致立即删除
5. 经自带 `ApkProvider`(`content://com.dsh.petfloat.apk/`)交给系统安装器
入口:设置页 → 关于 → 检查更新。Android 8+ 首次需「安装未知来源应用」授权,未授权时**先引导去开**,
而不是下载完才失败。
> 项目零第三方依赖,用不了 `androidx.core` 的 `FileProvider`,所以 `ApkProvider` 是自带的只读
> ContentProvider:只暴露 `cacheDir/update` 下的 `.apk`,路径取 basename 防 `../` 穿越。
### runner
需要一台带 JDK 17 + Android SDK 的 act_runner,标签 `ubuntu-latest`。
推荐 **host 模式**(直接复用机器上现成的 `/opt/jdk17`、`/opt/android-sdk`,不必再做 Android 镜像):
```bash
# 注册令牌:Gitea → 站点管理 → Actions → Runners
REG_TOKEN=<令牌> bash scripts/install-runner.sh
```
---
## 13. 参考与借鉴
本工程并非从零造轮子,素材、行为系统、记忆策略、UI 语言分别借鉴/参考了以下项目:
+104
View File
@@ -0,0 +1,104 @@
#!/bin/bash
# =============================================================================
# 在 Gitea 服务器(123.206.124.151)上安装 act_runner
#
# 为什么用 host 模式(label = self-hosted:host)而不是 Docker 容器模式:
# 这台机器本来就是这个项目的构建机(build.sh 里写死了 /opt/jdk17、
# /opt/android-sdk、/opt/gradle/gradle-8.5),Android SDK 已经装好了。
# 容器模式下 job 跑在 node:16 镜像里,没有 JDK/Android SDK,还得自己
# 构建一个 2GB+ 的 Android 镜像;host 模式直接复用现成环境,零额外体积。
#
# 用法:
# 1) 先拿到 registration token(见文件末尾说明)
# 2) REG_TOKEN=xxxx bash install-runner.sh
# =============================================================================
set -euo pipefail
GITEA_URL="${GITEA_URL:-http://123.206.124.151:3000}"
REG_TOKEN="${REG_TOKEN:-}"
RUNNER_NAME="${RUNNER_NAME:-tencent2}"
LABELS="${LABELS:-self-hosted:host}"
WORK="${WORK:-/opt/act_runner}"
if [ -z "$REG_TOKEN" ]; then
echo "缺少 REG_TOKEN。获取方式:"
echo " Gitea → 站点管理 → Actions → Runners → 创建 Runner / 复制注册令牌"
echo " 或 API: curl -H 'Authorization: token <ADMIN_TOKEN>' \\"
echo " $GITEA_URL/api/v1/admin/actions/runners/registration-token -X POST"
echo
echo "然后:REG_TOKEN=<令牌> bash $0"
exit 1
fi
echo "=== 1/4 检查宿主机构建环境(host 模式要靠它)==="
missing=0
for p in /opt/jdk17 /opt/android-sdk /opt/gradle; do
if [ -d "$p" ]; then echo " ✓ $p"; else echo " ✗ $p 不存在"; missing=1; fi
done
if [ "$missing" = "1" ]; then
echo
echo "警告:上面缺失的路径会导致构建失败。若实际路径不同,"
echo " 请确认 workflow 里「准备构建环境」步骤的探测列表覆盖到了。"
fi
echo "=== 2/4 下载 act_runner ==="
mkdir -p "$WORK" && cd "$WORK"
ARCH=$(uname -m)
case "$ARCH" in
x86_64|amd64) RA_ARCH=amd64 ;;
aarch64|arm64) RA_ARCH=arm64 ;;
*) echo "不支持的架构:$ARCH"; exit 1 ;;
esac
if [ ! -x ./act_runner ]; then
# 优先 gitea.com(官方分发),失败回退 GitHub
curl -fL --retry 3 -o act_runner \
"https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-linux-$RA_ARCH" \
|| curl -fL --retry 3 -o act_runner \
"https://github.com/gitea/act_runner/releases/latest/download/act_runner-linux-$RA_ARCH"
chmod +x act_runner
fi
./act_runner --version || true
echo "=== 3/4 注册到 $GITEA_URL ==="
# host 模式:job 直接在宿主机执行,标签形如 self-hosted:host
if [ -f .runner ]; then
echo " 已存在 .runner 配置,跳过注册(如需重新注册请先删除 $WORK/.runner)"
rm -f "$WORK/.runner"
echo " 已删除旧配置,重新注册…"
fi
./act_runner register --no-interactive \
--instance "$GITEA_URL" \
--token "$REG_TOKEN" \
--name "$RUNNER_NAME" \
--labels "$LABELS"
echo "=== 4/4 安装为 systemd 服务并启动 ==="
if command -v systemctl >/dev/null 2>&1; then
cat > /etc/systemd/system/gitea-act-runner.service <<EOF
[Unit]
Description=Gitea Actions Runner (host mode)
After=network.target
[Service]
Type=simple
WorkingDirectory=$WORK
ExecStart=$WORK/act_runner daemon
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now gitea-act-runner
sleep 2
systemctl --no-pager --lines=15 status gitea-act-runner || true
else
echo " 没有 systemd,前台启动以便观察(Ctrl+C 退出后需自行守护):"
exec ./act_runner daemon
fi
echo
echo "=== 完成 ==="
echo "回 Gitea 确认:$GITEA_URL/-/admin/actions/runners 应能看到 $RUNNER_NAME(idle)"
echo "然后重新跑构建:推送新 tag,或在仓库 Actions 页面点 Re-run。"