152 lines
5.0 KiB
Markdown
152 lines
5.0 KiB
Markdown
# Gitea 生产部署
|
|
|
|
Ubuntu 宝塔面板全新服务器请优先阅读 [Ubuntu + 宝塔面板从零部署](BAOTA_UBUNTU_FROM_ZERO.md)。本文只描述自动发布机制。
|
|
|
|
PR 质量门禁由 `.gitea/workflows/ci.yml` 执行:
|
|
|
|
1. Ruff 静态检查。
|
|
2. 迁移文件、Django 和 ASGI 导入检查。
|
|
3. SQLite 单元测试,覆盖率不得低于 75%。
|
|
4. MySQL 8.0.35 全量迁移和测试。
|
|
|
|
同一 PR 推送新提交时,旧 CI 会自动取消。单次 CI 最多运行 20 分钟。
|
|
|
|
生产发布由 `.gitea/workflows/deploy.yml` 执行。目标为 `main` 的 PR 被真正合并后:
|
|
|
|
1. Runner 检出 `main` 并在临时 MySQL 8.0.35 上执行发布迁移检查。
|
|
2. 检查通过后 SSH 到生产服务器。
|
|
3. 服务器备份 MySQL,安装依赖,执行迁移并收集静态资源。
|
|
4. systemd 重启 Django ASGI 服务。
|
|
5. 验证应用 HTTP、Redis Channel Layer 和直连 WebSocket。
|
|
6. 通过 Nginx 验证健康接口、首页、后台、视频目录和 WebSocket。
|
|
7. Runner 从外部容器网络再次验证 Nginx 健康接口。
|
|
8. 失败时回退应用代码;数据库备份保留,不自动执行破坏性反向迁移。
|
|
|
|
关闭但未合并的 PR 不会部署。同一时间只允许一个生产部署任务执行。
|
|
|
|
## main 分支保护
|
|
|
|
仓库必须保护 `main` 分支:
|
|
|
|
- 禁止直接推送,所有改动必须通过 PR。
|
|
- 合并前必须通过状态检查 `CI / test`。
|
|
- 禁止在检查未完成时合并。
|
|
- 管理员也应遵守分支保护。
|
|
|
|
完整测试只在 PR 阶段执行。合并后发布流程不重复运行全量测试,因此分支保护是生产发布的必要条件。
|
|
|
|
## Gitea Secrets
|
|
|
|
在仓库 `Settings > Actions > Secrets` 配置:
|
|
|
|
| Secret | 内容 |
|
|
| --- | --- |
|
|
| `DEPLOY_HOST` | 生产服务器 IP 或域名 |
|
|
| `DEPLOY_USER` | SSH 用户,要求 root 或具备免密 sudo |
|
|
| `DEPLOY_SSH_KEY` | 对应用户的 SSH 私钥全文 |
|
|
|
|
## 首次切换
|
|
|
|
自动部署前,服务器必须满足:
|
|
|
|
- Gitea 仓库为 `http://117.72.28.96:8765/Jacky/Hulumath-Web.git`。
|
|
- 项目目录为 `/www/wwwroot/Hulumath-Web`。
|
|
- Python 位于 `/www/server/pyporject_evn/versions/3.12.13/bin/python3` 或同目录 `python`。
|
|
- 已安装 MySQL 8 客户端命令 `mysqldump`。
|
|
- MySQL 8.0.35 数据库和用户已经创建。
|
|
- Redis 正在运行。
|
|
- 项目根目录存在 `.env.production`。
|
|
- Nginx 已反向代理 `127.0.0.1:8000`。
|
|
|
|
创建生产环境文件:
|
|
|
|
```bash
|
|
cd /www/wwwroot/Hulumath-Web
|
|
cp .env.production.example .env.production
|
|
chmod 600 .env.production
|
|
```
|
|
|
|
替换其中的域名、密钥、MySQL 密码和 Redis 地址。该文件只保留在服务器,不提交 Git。
|
|
|
|
首次从 Flask 切换时,需要先在宝塔或原进程管理器中停止旧 Flask Gunicorn,释放 `127.0.0.1:8000`。部署脚本不会强杀未知进程。
|
|
|
|
代码合并到 `main` 后,可以等待 workflow 自动执行,也可以首次手动执行:
|
|
|
|
```bash
|
|
cd /www/wwwroot/Hulumath-Web
|
|
git remote set-url origin http://117.72.28.96:8765/Jacky/Hulumath-Web.git
|
|
git fetch origin main
|
|
PREVIOUS_REVISION="$(git rev-parse HEAD)"
|
|
git reset --hard origin/main
|
|
|
|
PROJECT_DIR="$PWD" \
|
|
PREVIOUS_REVISION="$PREVIOUS_REVISION" \
|
|
bash scripts/deploy_production.sh
|
|
```
|
|
|
|
首次空数据库还需导入官方内容:
|
|
|
|
```bash
|
|
cd /www/wwwroot/Hulumath-Web
|
|
set -a
|
|
source .env.production
|
|
set +a
|
|
|
|
.venv-production/bin/python backend/manage.py seed_initial_content
|
|
.venv-production/bin/python backend/manage.py seed_contests
|
|
```
|
|
|
|
种子命令不放在每次自动部署中,避免覆盖运营后台后续修改的内容。
|
|
|
|
## Nginx
|
|
|
|
现有 Flask 反向代理可改为:
|
|
|
|
```nginx
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
location /ws/ {
|
|
proxy_pass http://127.0.0.1:8000;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_read_timeout 120s;
|
|
}
|
|
```
|
|
|
|
应用静态资源由 WhiteNoise 提供,无需额外暴露项目目录。
|
|
|
|
## 运维命令
|
|
|
|
```bash
|
|
systemctl status hulumath-web
|
|
journalctl -u hulumath-web -n 200 --no-pager
|
|
journalctl -u hulumath-web -f
|
|
systemctl restart hulumath-web
|
|
```
|
|
|
|
健康检查:
|
|
|
|
```bash
|
|
curl -H 'Host: 你的域名' -H 'X-Forwarded-Proto: https' \
|
|
http://127.0.0.1:8000/health/
|
|
```
|
|
|
|
MySQL 压缩 SQL 备份默认保存在 `/www/backup/hulumath/`,保留 14 天。
|
|
|
|
## 数据迁移边界
|
|
|
|
旧 Flask 的 `data/miniapp_v3.db` 不会再进入自动部署,也不会覆盖 MySQL。若旧生产 SQLite 中存在必须保留的账号或运行数据,需要在首次公开切换前单独执行一次数据迁移和核对。
|
|
|
|
数据库迁移应采用“先扩展、后清理”策略。不要在同一次发布中删除旧字段并立即依赖新字段,以保证应用代码可回退。
|