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

4.8 KiB
Raw Blame History

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

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)。

部署步骤(一次性):

# 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-2status,连续 offline 到阈值 → Telegram 告警,恢复也通知;API 取不到时跳过不误报。

部署(在常在线主机,如 jiu 的 mac / NAS):

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 LaunchAgentStartInterval 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)。本机残留待清:

# 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)。