iOSBuildServer/README.md
shen 0ba16635df docs: 更新文档反映多用户系统,移除冗余钉钉通知
- README 补充多用户管理、JWT 认证、Web 管理配置等文档
- .env.example 添加 JWT_SECRET 配置
- 移除 notification.py(钉钉通知由 AutoPacking 处理)
- 添加 CLAUDE.md 项目上下文
2026-06-08 22:07:35 +08:00

565 lines
15 KiB
Markdown
Raw Permalink 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.

# iOS 自动打包服务
基于 FastAPI + Vue 3 的 iOS 应用自动打包服务,支持 Ad_Hoc 和 App_Store 两种打包类型,提供 Web 界面操作、实时日志流、构建历史管理、多用户权限和健康监测。
## 目录
- [环境要求](#环境要求)
- [快速开始](#快速开始)
- [配置说明](#配置说明)
- [服务管理](#服务管理)
- [多用户管理](#多用户管理)
- [Watchdog 健康监测](#watchdog-健康监测)
- [macOS 开机自启](#macos-开机自启)
- [开发模式](#开发模式)
- [自动化测试](#自动化测试)
- [项目结构](#项目结构)
- [常见问题](#常见问题)
---
## 环境要求
| 依赖 | 版本要求 | 说明 |
|------|----------|------|
| macOS | 11+ | 必须xcodebuild 依赖 |
| Xcode | 14+ | 必须,含 Command Line Tools |
| Python | 3.9+ | 后端运行 |
| Node.js | 18+ | 前端构建 |
| CocoaPods | - | 项目已有 Podfile 时需要 |
## 快速开始
### 1. 克隆项目
```bash
git clone <repo-url> BuildServer
cd BuildServer
```
### 2. 配置环境变量
```bash
cp .env.example .env
vim .env
```
**必须修改的配置项:**
```bash
# iOS 源码项目路径(包含 readoor.xcworkspace 的目录)
PROJECT_ROOT=/path/to/your/Readoor
# 打包输出目录
BUILD_BASE_DIR=/path/to/build/output
# 管理员密码(建议修改)
ADMIN_PASSWORD=your_secure_password
```
### 3. 构建与启动
```bash
# 一键构建(安装依赖 + 构建前端)
./deploy.sh build
# 启动服务
./deploy.sh start
```
启动后访问 `http://<服务器IP>:8000` 即可使用。
### 4.(可选)初始化分支源码目录
如果需要按分支打包,先准备分支源码目录:
```bash
# 创建分支源码根目录
mkdir -p /path/to/ReadoorBranches
# 手动 clone 主分支(后续自动 pull 更新)
git clone -b main git@github.com:org/repo.git /path/to/ReadoorBranches/main
```
其他分支无需手动 clone首次打包时会自动从远程仓库 clone。
### 5.(可选)启用健康监测
```bash
./deploy.sh watchdog
```
### 6.(可选)设为开机自启
```bash
./deploy/install-service.sh install
```
---
## 配置说明
所有配置通过项目根目录的 `.env` 文件管理,修改后重启服务生效。
### 项目路径
| 变量 | 示例 | 说明 |
|------|------|------|
| `PROJECT_ROOT` | `/Users/shen/Work/Code/Readoor` | iOS 源码项目根目录AutoPacking 脚本路径) |
| `BUILD_BASE_DIR` | `/Users/shen/Documents` | 打包产物输出基础目录 |
| `GIT_SOURCE_BASE` | `/path/to/ReadoorBranches` | 分支源码根目录,每个分支一个子目录 |
| `GIT_REMOTE_URL` | `git@github.com:org/repo.git` | 远程仓库地址,分支目录不存在时自动 clone |
### 服务配置
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `BACKEND_PORT` | `8000` | 后端服务端口 |
| `ADMIN_USERNAME` | `admin` | 初始管理员用户名(首次启动自动创建) |
| `ADMIN_PASSWORD` | `admin123` | 初始管理员密码 |
| `JWT_SECRET` | `ios-build-server-secret-key-change-in-production` | JWT 签名密钥(生产环境务必修改) |
### 打包配置
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `MAX_CONCURRENT_BUILDS` | `2` | 最大并行打包数 |
| `BUILD_DIR_RETENTION_HOURS` | `24` | 打包目录保留时间(小时),超期自动清理 |
| `BUILD_TIMEOUT_HOURS` | `1` | 打包超时时间(小时),超时自动标记失败 |
### Web 管理配置
以下配置通过管理后台 Web 界面管理(存储在 `config.json`
| 配置项 | 说明 |
|--------|------|
| App 管理 | 应用名称、Scheme、服务器环境、upload_key 等 |
| Scheme 管理 | 打包 Scheme 配置 |
| 服务器环境 | 测试/正式/自定义环境的 API 地址、Universal Link 等 |
| 分支管理 | 可打包的代码分支列表 |
| 版本号 | App_Ver 和 Build_Ver写入 AutoPacking 脚本) |
| 上传配置 | OSS / WebDAV 文件上传设置 |
### Watchdog 配置
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `WATCHDOG_INTERVAL` | `30` | 健康检查间隔(秒) |
| `WATCHDOG_TIMEOUT` | `10` | HTTP 健康检查超时(秒) |
| `MAX_RESTART_ATTEMPTS` | `3` | 连续重启上限,超过后进入冷却 |
| `COOLDOWN_SECONDS` | `300` | 冷却时间(秒) |
---
## 服务管理
所有服务管理通过 `deploy.sh` 完成:
```bash
./deploy.sh <command>
```
### 命令一览
| 命令 | 说明 |
|------|------|
| `build` | 构建前端、创建 Python 虚拟环境、安装所有依赖 |
| `start` | 后台启动服务 |
| `stop` | 停止服务和 watchdog |
| `restart` | 重启服务 |
| `status` | 查看服务和 watchdog 运行状态 |
| `test` | 一键运行全部测试(后端 + 前端) |
| `watchdog` | 启动健康监测(后台守护) |
| `watchdog-stop` | 停止健康监测 |
| `watchdog-fg` | 前台运行健康监测(调试用) |
### 常用操作
```bash
# 首次部署
./deploy.sh build && ./deploy.sh start
# 查看状态
./deploy.sh status
# 更新代码后重新部署
git pull
./deploy.sh build
./deploy.sh restart
# 启用健康监测
./deploy.sh watchdog
# 停止所有服务
./deploy.sh stop
```
### 日志
日志文件位于 `logs/` 目录:
```
logs/
├── server.log # 服务运行日志
├── watchdog.log # Watchdog 操作日志(重启记录等)
├── server-stdout.log # launchd 模式下的标准输出
├── server-stderr.log # launchd 模式下的标准错误
├── watchdog-stdout.log # launchd watchdog 标准输出
└── watchdog-stderr.log # launchd watchdog 标准错误
```
---
## 多用户管理
系统支持多用户管理,基于 JWT 认证。首次启动时自动创建 `.env` 中配置的管理员账号。
### 用户角色
| 角色 | 权限 |
|------|------|
| 管理员 | 所有功能 + 用户管理(增删改查、角色切换) |
| 普通用户 | 打包、查看历史、查看配置(不可修改配置、不可管理用户) |
### 管理用户
在管理后台「用户管理」页面(仅管理员可见):
- 创建用户:设置用户名、密码(至少 6 位)、是否管理员
- 修改密码:管理员可修改任意用户密码
- 切换角色:在管理员/普通用户之间切换
- 删除用户:不能删除自己
### 认证流程
1. `POST /api/auth/login` — 用户名+密码登录,返回 JWT token
2. 后续请求在 `Authorization: Bearer <token>` 头中携带 token
3. Token 有效期 24 小时,过期需重新登录
---
## Watchdog 健康监测
Watchdog 定期检查服务健康状态,发现异常自动重启。
### 检测逻辑
```
每 N 秒执行一次
├─ 进程是否存在? (kill -0)
│ └─ 否 → 重启
└─ HTTP /api/health 返回 200
├─ 是 → 正常,继续轮询
└─ 否 → 重启
```
### 重启保护
- 连续失败次数 <= `MAX_RESTART_ATTEMPTS`:立即重启
- 连续失败次数 > `MAX_RESTART_ATTEMPTS`:进入冷却期(`COOLDOWN_SECONDS` 秒),冷却结束后重置计数器重新尝试
### 运行方式
```bash
# 后台守护(推荐)
./deploy.sh watchdog
# 前台运行(调试,可看到实时输出)
./deploy.sh watchdog-fg
# 查看 watchdog 日志
tail -f logs/watchdog.log
# 停止 watchdog
./deploy.sh watchdog-stop
```
---
## macOS 开机自启
通过 macOS 原生的 launchd 实现开机自启和进程守护。
### 安装
```bash
# 前置条件:先完成构建
./deploy.sh build
# 安装服务
./deploy/install-service.sh install
```
安装后会注册两个 launchd 服务:
| 服务 | 说明 |
|------|------|
| `com.readoor.buildserver` | 主服务,进程崩溃自动拉起 |
| `com.readoor.buildserver.watchdog` | 健康监测,检测 HTTP 卡死并重启 |
### 卸载
```bash
./deploy/install-service.sh uninstall
```
### 手动管理 launchd 服务
```bash
# 查看服务状态
launchctl list | grep readoor
# 手动停止
launchctl unload ~/Library/LaunchAgents/com.readoor.buildserver.plist
launchctl unload ~/Library/LaunchAgents/com.readoor.buildserver.watchdog.plist
# 手动启动
launchctl load ~/Library/LaunchAgents/com.readoor.buildserver.plist
launchctl load ~/Library/LaunchAgents/com.readoor.buildserver.watchdog.plist
```
---
## 开发模式
一键启动本地开发环境(后端 + 前端同时运行):
```bash
./start.sh
```
- 前端界面:`http://localhost:3000`(自动代理 API 请求到后端)
- 后端 API`http://localhost:8000`
- 前端修改自动热更新,后端修改自动 reload
- `Ctrl+C` 同时停止所有服务
---
## 自动化测试
### 运行测试
```bash
# 一键运行全部测试(后端 89 + 前端 35 = 124 个)
./deploy.sh test
# 只运行匹配的测试
./deploy.sh test -k test_login
# 单独运行后端测试
.venv/bin/python -m pytest tests/ -v
# 单独运行前端测试
cd frontend && npx vitest run
```
### 测试覆盖
| 测试文件 | 覆盖内容 | 数量 |
|----------|----------|------|
| `test_api_health.py` | 健康检查 | 1 |
| `test_api_auth.py` | 登录认证 | 3 |
| `test_api_config.py` | App/Scheme/Branch/Server/Build 配置 CRUD | 20 |
| `test_api_tasks.py` | 任务创建/列表/详情/取消 | 9 |
| `test_api_apps.py` | 打包选择接口 | 3 |
| `test_websocket.py` | 日志流订阅/发送/完成/清理 | 10 |
| `test_downloads.py` | dSYM/混淆映射/二维码下载 | 11 |
| `test_build_service.py` | 源码更新/拷贝/配置生成/目录清理 | 11 |
| `test_build_queue.py` | 并发控制/任务执行/取消 | 7 |
| `test_edge_cases.py` | 边界情况/无效参数/配置备份 | 14 |
| `App.test.js` | 登录/退出/导航 | 8 |
| `BuildView.test.js` | 打包表单/任务列表/提交 | 8 |
| `ConfigView.test.js` | 配置管理/分支增删/设置保存 | 8 |
| `HistoryView.test.js` | 历史列表/过滤/下载/二维码 | 11 |
---
## 项目结构
```
BuildServer/
├── .env.example # 环境变量模板
├── .env # 实际配置(不入库)
├── .gitignore
├── README.md # 项目文档
├── deploy.sh # 部署与管理脚本
├── start.sh # 开发模式启动脚本(一键启动前后端)
├── requirements.txt # Python 依赖
├── requirements-dev.txt # 测试依赖pytest, httpx
├── pytest.ini # pytest 配置
├── deploy/ # 部署相关
│ └── install-service.sh # macOS launchd 服务安装
├── tests/ # 后端测试pytest
│ ├── conftest.py # 测试 fixtures
│ ├── test_api_*.py # API 接口测试
│ ├── test_websocket.py # WebSocket 测试
│ ├── test_downloads.py # 文件下载测试
│ ├── test_build_service.py # 打包服务测试
│ ├── test_build_queue.py # 队列测试
│ └── test_edge_cases.py # 边界情况测试
├── backend/ # 后端FastAPI
│ ├── main.py # 入口,路由注册,静态文件服务
│ ├── config.py # 配置加载(读取 .env
│ ├── database.py # SQLAlchemy 数据库初始化
│ ├── models.py # 数据库模型Task, BuildConfig, User
│ ├── schemas.py # Pydantic 请求/响应模型
│ ├── deps.py # JWT 认证依赖
│ ├── routers/
│ │ ├── auth.py # 登录认证JWT
│ │ ├── users.py # 用户管理(仅管理员)
│ │ ├── config.py # 配置管理App/Scheme/Server/Upload/Branch/Version CRUD
│ │ ├── apps.py # 打包选择(只读)
│ │ └── tasks.py # 任务管理(创建/列表/取消/下载)
│ └── services/
│ ├── build_service.py # 打包核心流程
│ ├── build_queue.py # 异步任务队列
│ └── log_streamer.py # WebSocket 日志流
└── frontend/ # 前端Vue 3 + Vite
├── vite.config.js # 构建配置,开发代理
├── vitest.config.js # 前端测试配置
├── index.html
└── src/
├── App.vue # 根组件(导航/登录)
├── router/index.js # 路由
├── composables/
│ └── useWebSocket.js
├── views/
│ ├── BuildView.vue # 打包页面
│ ├── HistoryView.vue # 历史记录
│ └── ConfigView.vue # 管理后台
└── __tests__/ # 前端测试vitest
├── App.test.js
├── BuildView.test.js
├── ConfigView.test.js
└── HistoryView.test.js
```
---
## 常见问题
### Q: 打包时提示 "未找到 xcodebuild"
确保安装了 Xcode 和 Command Line Tools
```bash
xcode-select --install
xcodebuild -version
```
### Q: 前端页面打不开
检查前端是否已构建:
```bash
ls backend/static/index.html # 应该存在
# 如果不存在:
./deploy.sh build
./deploy.sh restart
```
### Q: 端口被占用
修改 `.env` 中的 `BACKEND_PORT`,然后重启:
```bash
vim .env
./deploy.sh restart
```
### Q: 打包目录占满磁盘
调整保留时间或手动清理:
```bash
# 缩短保留时间
vim .env # BUILD_DIR_RETENTION_HOURS=12
./deploy.sh restart
# 手动清理所有打包目录
rm -rf /path/to/build/output/build_readoor_*
```
### Q: Watchdog 频繁重启
查看 watchdog 日志定位原因:
```bash
tail -50 logs/watchdog.log
tail -50 logs/server.log
```
常见原因:
- `PROJECT_ROOT` 路径不存在
- 磁盘空间不足
- Python 依赖缺失(重新执行 `./deploy.sh build`
### Q: 如何修改管理员密码
**方法一**:通过管理后台「用户管理」页面修改(推荐)
**方法二**:编辑 `.env` 后重启(仅影响初始管理员账号):
```bash
ADMIN_PASSWORD=new_password
./deploy.sh restart
```
注意:`.env` 中的管理员账号仅在首次启动时创建,之后的密码修改请通过管理后台操作。
### Q: 多台 Mac 部署
每台 Mac 上:
```bash
git clone <repo>
cd BuildServer
cp .env.example .env
# 编辑 .env 配置路径和密码
./deploy.sh build
./deploy.sh start
./deploy.sh watchdog
```
各机器独立运行,配置互不影响。
### Q: 如何按分支打包
1.`.env` 中配置 `GIT_SOURCE_BASE``GIT_REMOTE_URL`
2. 在管理页面「分支管理」中添加需要打包的分支(默认已有 `main`
3. 打包时在「代码分支」下拉框中选择分支
4. 首次打包某个分支时会自动从远程 clone后续打包会自动 `git pull` 更新
5. 每个分支有独立的源码目录,支持并行打包不同分支
### Q: 分支目录占满磁盘怎么办
```bash
# 查看各分支目录大小
du -sh /path/to/ReadoorBranches/*
# 删除不用的分支目录
rm -rf /path/to/ReadoorBranches/old-branch
```
### Q: 如何运行测试
```bash
# 一键运行全部测试(后端 + 前端)
./deploy.sh test
# 只运行后端测试
.venv/bin/python -m pytest tests/ -v
# 只运行前端测试
cd frontend && npx vitest run
# 运行指定测试
./deploy.sh test -k test_login
```