Files
pangolin/docs/ci-runner.md
T
wangjia e7b37d7719
ci-pangolin / Lint — shellcheck (pull_request) Successful in 9s
ci-pangolin / OpenAPI Sync Check (pull_request) Successful in 23s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 5s
ci-pangolin / Flutter — analyze + test (pull_request) Failing after 37s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Successful in 4s
ci-pangolin / Go — build + test (pull_request) Successful in 19s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Successful in 17s
ci-pangolin / Go — integration (mysql/redis testcontainers) (pull_request) Successful in 4m16s
ci-pangolin / Golden — 视觉回归 (components + auth) (pull_request) Successful in 15s
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 23s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 15s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 7s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 19s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m29s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 13s
test(ci): 刀3 — CI 单点韧性:runner 离线告警(缺口③)
CI 整条吊在一台 mac,关机/掉线即全停且无人知道。新增
deploy/runner/runner-deadman.sh(仿 bootstrap/monitor/deadman-watch.sh):
放另一台常在线主机,每 3 分钟查 gitea Actions API 里 mac-pangolin-2 的 status,
连续 offline 到阈值 → Telegram 告警,恢复也通知;API 取不到时跳过不误报。

响应字段已对照真 gitea API 核验({"runners":[{"name":...,"status":"online"}]}),
shellcheck 干净,实跑验证 online→不告警、缺失→进告警分支。

docs/ci-runner.md 增「韧性」节(告警部署 + cron/launchd)并标注持久化激活仍待
本机手动跑(pkill/launchctl,Claude 跑不了);验证段 job 数 9→10。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 23:04:35 +08:00

97 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.
# Pangolin CI Runner 记录
> gitea Actions self-hosted runner 设置记录。CI 工作流见 `.gitea/workflows/ci.yml`(9 个 job)。
## 决定:用 1 个 runner
| 项 | 值 |
|---|---|
| 名称 | **mac-pangolin-2**(gitea id 6) |
| 级别 | **项目级**(绑 `wangjia/pangolin`,只服务本仓库) |
| 机器 | mac 本机(`/Users/wangjia/bin/act_runner` v0.6.1) |
| 执行模式 | **host**(非容器) |
| label | `nas`(即 `runs-on: nas`) |
| 连接 | 经 jiu 的 TCP relay `127.0.0.1:13000` → NAS gitea `192.168.3.200:3000` |
### 为什么是 host 模式 + mac
- ci.yml 的 9 个 job **全是 docker-in-docker**(每个 job 内部 `docker run …` 拉 golang/flutter/redis 等镜像)。container 模式(像 jiu 的 `ubuntu-latest:docker://catthehacker`)在非特权容器里跑不了 DinD,所以必须 **host 模式**
- mac 的 Docker Desktop 能跑 Linux 容器,host 模式下 `docker run <linux-image>` 可用。
- 理想归宿其实是 **NAS(Linux)host runner**(给 NAS 现有 runner 加 `nas:host` label),mac 只是当前落点。
### 为什么要 relay(13000)
mac 上的 Shadowrocket 网络扩展会拦截 act_runner 这个 Go 二进制的流量,直连 NAS gitea 失败。jiu 已有一个常驻 python TCP relay(`~/bin/tcp_relay.py`,`127.0.0.1:13000 → 192.168.3.200:3000`),act_runner 连本地 relay 绕过。pangolin runner **复用**这个 relay。
## 配置文件:`~/.act_runner_pangolin2_config.yaml`
```yaml
log:
level: info
runner:
file: /Users/wangjia/.act_runner_pangolin2 # 注册凭证(.runner),勿入 git
capacity: 1
timeout: 3h
labels:
- "nas:host"
cache:
enabled: true
host:
workdir_parent: /Users/wangjia/.cache/act-pangolin2
```
## 持久化(launchd 开机自启)
仿 jiu 的 `com.jiu.act-runner`。文件在仓库 `deploy/runner/`:
- `act_runner_pangolin_start.sh` —— 启动脚本(等 jiu 的 relay 13000 就绪 → 起 daemon → 退出自重启)。
- `com.pangolin.act-runner.plist` —— launchd(RunAtLoad + KeepAlive)。
**部署步骤**(一次性):
```bash
# 1. 文件就位
cp deploy/runner/act_runner_pangolin_start.sh ~/bin/ && chmod +x ~/bin/act_runner_pangolin_start.sh
cp deploy/runner/com.pangolin.act-runner.plist ~/Library/LaunchAgents/
# 2. 停掉临时 daemon(否则和 launchd 起的抢同一注册)
pkill -f act_runner_pangolin2_config.yaml
# 3. 加载常驻服务(开机自启 + 崩溃自重启)
launchctl load ~/Library/LaunchAgents/com.pangolin.act-runner.plist
```
之后 mac 重启 / 退出登录都会自动拉起。日志 `/tmp/act_runner_pangolin2.log`
卸载:`launchctl unload ~/Library/LaunchAgents/com.pangolin.act-runner.plist`
> 依赖 jiu 的 relay(13000)常驻:jiu 的 `com.jiu.act-runner` 在 → relay 在 → 本 runner 能连 NAS gitea。
> ⚠️ **持久化激活状态**:上面三条一次性命令含 `pkill`/`launchctl`,需在 mac 本机手动执行
> (Claude 跑不了)。未激活前 runner 是临时 daemon,mac 重启即停。激活后用下面的离线告警兜底。
## 韧性:runner 离线告警(单点兜底)
CI 整条吊在这一台 mac 上,mac 关机/掉线 → CI 全停且**无人知道**。脚本
`deploy/runner/runner-deadman.sh`(仿 `bootstrap/monitor/deadman-watch.sh`)放在**另一台
常在线主机**上,每 3 分钟查 gitea Actions API 里 `mac-pangolin-2``status`,连续
offline 到阈值 → Telegram 告警,恢复也通知;API 取不到时跳过不误报。
**部署**(在常在线主机,如 jiu 的 mac / NAS):
```bash
cp deploy/runner/runner-deadman.sh /usr/local/bin/ && chmod +x /usr/local/bin/runner-deadman
# /etc/pangolin-runner-deadman.env(不入 git):
# GITEA_URL=http://127.0.0.1:13000 GITEA_TOKEN=<Bitwarden「gitea 读写key」>
# GITEA_REPO=wangjia/pangolin RUNNER_NAME=mac-pangolin-2
# TELEGRAM_BOT_TOKEN=... TELEGRAM_CHAT_ID=... FAIL_THRESHOLD=2
# cron(每 3 分钟):
echo '*/3 * * * * /usr/local/bin/runner-deadman >/dev/null 2>&1' | crontab -
```
mac 宿主可改 launchd LaunchAgent`StartInterval` 180 + 同一脚本),仿
`com.pangolin.act-runner.plist`。响应字段已对照真 API 核验:
`{"runners":[{"name":"mac-pangolin-2","status":"online",...}]}`
## 已删除:mac-pangolin(第一次注册的,id 5)
第一次注册的 runner(label `nas`,config `~/.act_runner_pangolin_config.yaml`)。job 调试时已从 **gitea 删除注册**(API DELETE,204)。本机残留待清:
```bash
# orphan daemon 进程(拿不到任务、空转报 "unregistered runner",无害但占进程)
pkill -f 'act_runner_pangolin_config.yaml' # 只匹配 orphan,不碰 -2 和 jiu
# orphan 文件
rm -f ~/.act_runner_pangolin ~/.act_runner_pangolin_config.yaml
rm -rf ~/.cache/act-pangolin
```
## 验证
- gitea → 仓库 Settings → Actions → Runners 应只见 **mac-pangolin-2**(online)。
-`main` 开 PR 触发 10 个 job(后增覆盖率闸 + go-integration);首次全绿见 run #298(commit `65bd7c3`)。