Files
updates/README.md
lafay 3ac1a2ccf5
Some checks failed
Build Updates Server / build (push) Failing after 10s
Build Updates Server / build-docker (push) Has been skipped
feat(apk): 增加公开APK管理接口和CI/CD工作流
- 新增获取最新APK版本信息和下载APK的公开接口
- 更新README文档,添加APK管理接口的使用说明
- 实现CI/CD工作流,支持自动构建和部署
- 优化APK存储逻辑,确保只保留最新APK文件
2026-03-26 03:29:44 +08:00

198 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Expo Updates Server (Go)
这个目录是 `expo-updates-server` 的 Go 版本实现,目标是:
- 保持客户端接口兼容:`GET /api/manifest``GET /api/assets`
- 增加便于上传和 CI 的管理接口:`/admin/publish``/admin/rollback``/admin/releases`
## 运行
```bash
cd expo-updates-server-go
go run ./cmd/server
```
默认监听 `:3001`,可通过环境变量覆盖:
- `PORT`:默认 `3001`
- `HOSTNAME`:默认 `http://localhost:3001`,用于拼接 assets URL
- `UPDATES_ROOT`:默认 `updates`
- `PRIVATE_KEY_PATH`:可选;若客户端请求 `expo-expect-signature`,必须配置
- `ADMIN_TOKEN`:管理接口 Bearer Token
示例(复用现有 `expo-updates-server/updates`
```bash
cd expo-updates-server-go
PORT=3001 \
HOSTNAME=http://localhost:3001 \
UPDATES_ROOT=../expo-updates-server/updates \
PRIVATE_KEY_PATH=../expo-updates-server/code-signing-keys/private-key.pem \
ADMIN_TOKEN=dev-token \
go run ./cmd/server
```
生产环境建议将 `HOSTNAME` 配置为:
```text
https://updates.littlelan.cn
```
## 兼容接口
- `GET /api/manifest`
- 支持 `expo-platform``expo-runtime-version``expo-protocol-version`
- 支持 `rollBackToEmbedded``noUpdateAvailable`
- 支持 `expo-expect-signature`
- `GET /api/assets?asset=...&runtimeVersion=...&platform=...`
## APK 管理接口(公开)
### 获取最新 APK 版本信息
`GET /api/apk/latest`
返回最新 APK 的版本信息,用于客户端检查更新。
```json
{
"runtimeVersion": "1.0.11",
"versionName": "1.0.11",
"size": 52428800,
"downloadUrl": "https://updates.littlelan.cn/api/apk/download?runtimeVersion=1.0.11",
"createdAt": "2026-03-26T00:00:00Z"
}
```
### 下载 APK
`GET /api/apk/download?runtimeVersion=<runtimeVersion>`
下载指定版本的 APK 文件。
## 管理接口(上传/CI
### 1) 发布 zip
`POST /admin/publish?runtimeVersion=<rv>&platform=<ios|android>`
- Header`Authorization: Bearer <ADMIN_TOKEN>`
- Body`expo export` 产物 zipzip 根目录需包含 `metadata.json`
```bash
curl -X POST \
"https://updates.littlelan.cn/admin/publish?runtimeVersion=2&platform=ios" \
-H "Authorization: Bearer dev-token" \
-H "Content-Type: application/zip" \
--data-binary @dist.zip
```
### 2) 创建回滚标记
`POST /admin/rollback`
```bash
curl -X POST "https://updates.littlelan.cn/admin/rollback" \
-H "Authorization: Bearer dev-token" \
-H "Content-Type: application/json" \
-d '{"runtimeVersion":"2","platform":"ios"}'
```
### 3) 查看发布列表
`GET /admin/releases?runtimeVersion=2`
```bash
curl "https://updates.littlelan.cn/admin/releases?runtimeVersion=2" \
-H "Authorization: Bearer dev-token"
```
### 4) 上传 APK
`POST /admin/apk/upload?runtimeVersion=<runtimeVersion>`
- Header`Authorization: Bearer <ADMIN_TOKEN>`
- Content-Type`application/vnd.android.package-archive``application/octet-stream`
- BodyAPK 二进制文件
```bash
curl -X POST \
"https://updates.littlelan.cn/admin/apk/upload?runtimeVersion=1.0.11" \
-H "Authorization: Bearer dev-token" \
-H "Content-Type: application/vnd.android.package-archive" \
--data-binary @app-release.apk
```
## CI 示例思路
1. 在客户端跑 `npx expo export`
2. 打包 `dist` 为 zip
3. 调用 `/admin/publish`
可直接参考根目录新增工作流:`.github/workflows/go-updates-server-ci.yml`
## CI/CD
项目使用 Gitea Actions 进行持续集成和部署:
### Build Workflow (`.gitea/workflows/build.yml`)
- 触发条件push 到 master/main 分支,或 PR
- 步骤:
1. 编译 Go 二进制文件
2. 构建 Docker 镜像
3. 推送到私有镜像仓库 `code.littlelan.cn/carrot_bbs/updates-server`
### Deploy Workflow (`.gitea/workflows/deploy.yml`)
- 触发条件PR 合并到 master/main或手动触发
- 步骤:
1. SSH 到服务器
2. 拉取最新镜像
3. 重启容器
### 所需 Secrets
- `GIT_USERNAME` - Gitea 用户名
- `GIT_TOKEN` - Gitea Token用于推送镜像
- `SERVER_PASSWORD` - 服务器 SSH 密码
- `UPDATES_ADMIN_TOKEN` - 管理接口 Token
## Docker 打包与运行
### 1) 构建镜像并导出 tar
`expo-updates-server-go` 目录执行:
```bash
./build-docker-tar.sh
```
可指定 tag
```bash
./build-docker-tar.sh 20260309-ota
```
执行后会生成:
- 镜像:`carrot-bbs-updates-server:<tag>`
- tar`carrot-bbs-updates-server-<tag>.tar`
### 2) 运行容器(挂载更新目录和密钥)
```bash
docker run -d \
--name carrot-bbs-updates-server \
-p 3001:3001 \
-e PORT=3001 \
-e HOSTNAME=https://updates.littlelan.cn \
-e UPDATES_ROOT=/data/updates \
-e PRIVATE_KEY_PATH=/data/privatekey.pem \
-e ADMIN_TOKEN=dev-token \
-v /opt/carrot-bbs/updates:/data/updates \
-v /opt/carrot-bbs/keys/privatekey.pem:/data/privatekey.pem:ro \
carrot-bbs-updates-server:latest
```