将单一 CI/CD 流水线拆成三条互不影响的发布流水线,各有 tag 前缀、独立版本
序列与独立 CHANGELOG:
- client(client-v*):Flutter 全平台 + version.yaml 自更新清单
- site(site-v*):web/ Eleventy 营销站,不含 web 版 app
- server(server-v*):backend Go 服务 + 共享基建 nginx/systemd
新增 3 个 workflow(deploy-client/site/server.yml)替换 deploy.yml;CI 脚本
按 part 拆分为 compile-/release-/deploy-{client,site,server}.sh,抽出公共函数
lib-forgejo.sh;compile-{macos,android,ios,windows}.sh 改去 client-v 前缀;
manual.yml 按前缀路由回滚。
跨流水线解耦:version.yaml 归 client,后端每请求实时读取(不重启、不触发
server 流水线);官网下载页的版本徽章/下载链接/更新日志时间线运行时经
/api/v1/public/release 动态拉取(API 不可达回退构建时静态内容)。为此一次性
扩展后端 changelog 字段(version.go/public.go)与 download.njk 动态渲染。
CHANGELOG.md 重命名为 CHANGELOG-client.md,新增 CHANGELOG-site/server.md;
重写 /release 命令为 /release <part> [version];同步更新 CLAUDE.md 与部署文档。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.8 KiB
NAS + Gitea 部署文档
概述
岩美酒库管理系统使用 群晖 NAS 上自托管的 Gitea(Forgejo) 作为代码仓库和 CI/CD 平台。代码推送到 main 分支后,NAS 上的 Gitea Runner 自动构建并部署到 EC2 服务器。
服务地址
| 服务 | 地址 |
|---|---|
| Gitea Web UI | https://git.51yanmei.com |
| Gitea SSH | ssh://git@git.51yanmei.com:2222 |
| Actions 面板 | https://git.51yanmei.com/wangjia/jiu/actions |
| 线上应用 | https://jiu.51yanmei.com |
| 管理端 Web | https://jiu.51yanmei.com/app/ |
Gitea Runner 说明
Runner 实际运行在本机 Mac(不是 NAS),通过 LaunchAgent 开机自启,连接 NAS 上的 Forgejo。
本机文件布局
| 文件 | 说明 |
|---|---|
/Users/wangjia/bin/act_runner |
act_runner 二进制(v0.2.11) |
/Users/wangjia/bin/act_runner_start.sh |
启动脚本(含 TCP 中继逻辑) |
/Users/wangjia/bin/tcp_relay.py |
Python3 TCP 中继(旧内网方案,现已通过域名直连) |
/Users/wangjia/.act_runner |
Runner 注册信息 |
/Users/wangjia/.act_runner_config.yaml |
Runner 配置(label: mac:host,capacity: 1) |
~/Library/LaunchAgents/com.jiu.act-runner.plist |
LaunchAgent plist,开机自启 |
/tmp/act_runner.log |
运行日志 |
Workflow 标签
.gitea/workflows/deploy-{client,site,server}.yml 中使用 runs-on: mac,对应 runner label mac:host。
检查 Runner 状态
# 查看日志
tail -f /tmp/act_runner.log
# 确认进程在跑
ps aux | grep act_runner | grep -v grep
# 手动重启(LaunchAgent 会自动重启,一般不需要)
kill $(pgrep -f act_runner_start.sh)
Runner 不工作时的排查步骤
- 确认 Gitea 可达:
curl -sf https://git.51yanmei.com/api/v1/version - 查看最近日志:
tail -30 /tmp/act_runner.log - 手动测试:
/Users/wangjia/bin/act_runner daemon --config ~/.act_runner_config.yaml(从终端运行应直接成功) - 强制重启:
kill $(pgrep -f act_runner_start.sh)— LaunchAgent 会在几秒内自动重拉
重新注册 Runner(token 失效时)
# 1. 停止当前 runner
kill $(pgrep -f act_runner_start.sh)
# 2. 删除旧注册文件
rm ~/.act_runner
# 3. 在 Forgejo 获取新 token:
# Settings → Actions → Runners → Create Runner Token
# 4. 注册(从终端运行,不要从 LaunchAgent)
/Users/wangjia/bin/act_runner register \
--no-interactive \
--instance https://git.51yanmei.com \
# SSH remote: ssh://git@git.51yanmei.com:2222/wangjia/jiu.git
--token <新token> \
--name mac-runner \
--labels mac:host
# 5. 重启(LaunchAgent 自动接管)
kill $(pgrep -f act_runner_start.sh)
Workflows
仓库根目录 .gitea/workflows/ 下有三个 workflow 文件:
deploy-{client,site,server}.yml — 三条独立部署流程
发版已拆成三条互不影响的流水线,按 tag 前缀触发:
| workflow | 触发 tag | 范围 |
|---|---|---|
deploy-client.yml |
client-v*.*.* |
Flutter 全平台 + version.yaml |
deploy-site.yml |
site-v*.*.* |
Eleventy 营销站 |
deploy-server.yml |
server-v*.*.* |
Go 后端 + nginx |
步骤(各自): compile-<part>*.sh 编译打包 → test.sh <part> 门禁 → release-<part>.sh 创建 Forgejo Release → deploy-<part>.sh SSH 到 EC2 部署 → Telegram 通知。公共函数在 scripts/ci/lib-forgejo.sh。
manual.yml — 手动部署 / 回滚
触发条件: Forgejo UI 手动触发(workflow_dispatch),输入带前缀 tag(如 client-v1.0.55),按前缀路由到对应 deploy-<part>.sh
步骤: 只运行 deploy.sh,从 Forgejo Release 下载已有产物直接部署,跳过编译和测试。
ci.yml — PR 测试流程
触发条件: 非 main 分支的 push 或 PR
步骤: 只跑测试(go test + flutter test),不构建不部署。
Secrets 配置
在 Gitea 仓库的 Settings → Secrets 中配置以下密钥:
| Secret 名称 | 用途 |
|---|---|
EC2_SSH_KEY |
EC2 服务器的 SSH 私钥(PEM 格式,完整内容) |
EC2_HOST |
EC2 服务器 IP 或域名 |
EC2_USER |
EC2 SSH 用户名(如 ec2-user、ubuntu) |
FORGEJO_TOKEN |
Gitea 个人访问 Token(用于创建 Release、下载 asset) |
FORGEJO_URL |
Gitea 地址:https://git.51yanmei.com |
TELEGRAM_TOKEN |
Telegram Bot Token(部署通知) |
TELEGRAM_CHAT_ID |
Telegram Chat ID(接收通知的对话) |
触发部署方式
# 开发完成,确认测试通过后打 tag
git tag -a v1.1.0 -m "v1.1.0"
git push nas main && git push nas v1.1.0
# → CI 自动:compile → test → release → deploy → Telegram 通知
回滚: Forgejo UI → Actions → Manual Deploy → 输入旧 tag → Run
EC2 服务器目录结构
/opt/jiu/
├── backend/
│ ├── jiu-server # Go 可执行文件
│ └── config/
│ └── version.yaml # 版本信息(由 CI 自动更新)
├── web/ # Flutter Web 构建产物(/app/ 路径)
├── marketing/ # 营销站点静态 HTML
│ ├── assets/
│ ├── index.html
│ ├── docs.html
│ └── download.html
├── images/ # 商品图片上传目录
└── web-old/ # 上一版本 Flutter Web(回滚备用)
Systemd 服务名:jiu
日志:journalctl -u jiu -f
Nginx 路由说明
配置文件:deploy/nginx-jiu.conf(CI 部署时自动更新)
| 路径 | 服务 |
|---|---|
/api/*, /health, /version |
Go 后端 API |
/images/* |
商品图片静态文件 |
/app/ |
Flutter 管理端 SPA |
/product/<uuid> |
商品扫码公开页(Flutter Web 路由) |
/ |
营销首页 |