From e7b37d7719039e32e00ce760a0a3b0cac8b050e9 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Thu, 25 Jun 2026 23:04:35 +0800 Subject: [PATCH] =?UTF-8?q?test(ci):=20=E5=88=803=20=E2=80=94=20CI=20?= =?UTF-8?q?=E5=8D=95=E7=82=B9=E9=9F=A7=E6=80=A7:runner=20=E7=A6=BB?= =?UTF-8?q?=E7=BA=BF=E5=91=8A=E8=AD=A6(=E7=BC=BA=E5=8F=A3=E2=91=A2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- deploy/runner/runner-deadman.sh | 73 +++++++++++++++++++++++++++++++++ docs/ci-runner.md | 26 +++++++++++- docs/index.html | 2 +- 3 files changed, 99 insertions(+), 2 deletions(-) create mode 100755 deploy/runner/runner-deadman.sh diff --git a/deploy/runner/runner-deadman.sh b/deploy/runner/runner-deadman.sh new file mode 100755 index 0000000..adbc412 --- /dev/null +++ b/deploy/runner/runner-deadman.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# runner-deadman —— CI runner 死信守望。CI 整条吊在一台 mac(mac-pangolin-2)上, +# mac 一关/掉线 CI 全停且无人知道。本脚本放在【另一台常在线主机】上,周期查 gitea +# Actions API 里该 runner 的 status,连续 offline 到阈值 → Telegram 告警;恢复也通知。 +# +# 仿 deploy/bootstrap/monitor/deadman-watch.sh(同一发信/去抖范式),探活对象从 +# 「TCP 端口」换成「gitea runner 在线状态」。 +# +# 配置 /etc/pangolin-runner-deadman.env: +# GITEA_URL=http://127.0.0.1:13000 # gitea 基址(经 relay 或直连) +# GITEA_TOKEN=... # gitea 读写 key(Bitwarden「gitea 读写key」) +# GITEA_REPO=wangjia/pangolin # owner/repo +# RUNNER_NAME=mac-pangolin-2 # 要守望的 runner 名 +# TELEGRAM_BOT_TOKEN=... TELEGRAM_CHAT_ID=... +# FAIL_THRESHOLD=2 # 连续几次 offline 才告警(去抖) +# +# 在该常在线主机上每 3 分钟跑一次(cron,用户态即可): +# */3 * * * * /usr/local/bin/runner-deadman >/dev/null 2>&1 +# (mac 宿主可改用 launchd LaunchAgent,见 docs/ci-runner.md「韧性」节。) +set -uo pipefail + +ENV_FILE=/etc/pangolin-runner-deadman.env +[ -r "$ENV_FILE" ] || { echo "缺少 $ENV_FILE" >&2; exit 1; } +# shellcheck disable=SC1090 +. "$ENV_FILE" +: "${FAIL_THRESHOLD:=2}" +: "${GITEA_REPO:=wangjia/pangolin}" +: "${RUNNER_NAME:=mac-pangolin-2}" +STATE_DIR="${STATE_DIR:-$HOME/.local/state/pangolin-runner-deadman}" +mkdir -p "$STATE_DIR" +statef="${STATE_DIR}/${RUNNER_NAME}.fail" + +send_tg() { + local text="$1" + [ -n "${TELEGRAM_BOT_TOKEN:-}" ] && [ -n "${TELEGRAM_CHAT_ID:-}" ] || { echo "$text"; return; } + curl -fsS --max-time 15 \ + "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + --data-urlencode "chat_id=${TELEGRAM_CHAT_ID}" \ + --data-urlencode "text=${text}" >/dev/null 2>&1 || echo "Telegram 发送失败" >&2 +} + +# 查 runner 状态。响应形如: +# {"runners":[{"id":6,"name":"mac-pangolin-2","status":"online","busy":false,...}],...} +resp=$(curl -fsS --max-time 15 -H "Authorization: token ${GITEA_TOKEN}" \ + "${GITEA_URL%/}/api/v1/repos/${GITEA_REPO}/actions/runners" 2>/dev/null) || { + # API 取不到(监控主机网络抖动 / relay 没起 / gitea 宕):不计入去抖,避免误报。 + echo "runner-deadman: gitea API 不可达,跳过本次(不改状态)" >&2 + exit 0 +} + +# 提取该 runner 的 status(优先 jq,缺 jq 退回 grep)。 +if command -v jq >/dev/null 2>&1; then + status=$(printf '%s' "$resp" | jq -r --arg n "$RUNNER_NAME" \ + '.runners[]? | select(.name==$n) | .status' 2>/dev/null) +else + status=$(printf '%s' "$resp" \ + | grep -oE "\"name\":\"${RUNNER_NAME}\"[^}]*\"status\":\"[a-z]+\"" \ + | grep -oE '"status":"[a-z]+"' | tail -1 | cut -d'"' -f4) +fi + +if [ "$status" = "online" ]; then + if [ -f "$statef" ]; then + send_tg "🟢 [CI runner ${RUNNER_NAME}] 恢复在线" + rm -f "$statef" + fi +else + # status 为 offline / 空(runner 已从 gitea 掉线或不存在)。 + fails=$(( $(cat "$statef" 2>/dev/null || echo 0) + 1 )) + echo "$fails" > "$statef" + if [ "$fails" -eq "$FAIL_THRESHOLD" ]; then + send_tg "🔴 [CI runner ${RUNNER_NAME}] 离线(status=${status:-缺失}),连续 ${fails} 次,CI 已停摆" + fi +fi diff --git a/docs/ci-runner.md b/docs/ci-runner.md index 64f410f..7c9f7dc 100644 --- a/docs/ci-runner.md +++ b/docs/ci-runner.md @@ -57,6 +57,30 @@ launchctl load ~/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= +# 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 @@ -69,4 +93,4 @@ rm -rf ~/.cache/act-pangolin ## 验证 - gitea → 仓库 Settings → Actions → Runners 应只见 **mac-pangolin-2**(online)。 -- 向 `main` 开 PR 触发 9 个 job;首次全绿见 run #298(commit `65bd7c3`)。 +- 向 `main` 开 PR 触发 10 个 job(后增覆盖率闸 + go-integration);首次全绿见 run #298(commit `65bd7c3`)。 diff --git a/docs/index.html b/docs/index.html index 0f3cfcf..b223233 100644 --- a/docs/index.html +++ b/docs/index.html @@ -122,7 +122,7 @@

排障 / Runbook

CI Runner 设置记录 MD
-
gitea Actions self-hosted runner 记录:决定用 1 个(mac-pangolin-2,项目级·mac host·label nas·复用 jiu relay)、已删 orphan 的清理命令、持久化 TODO。CI 首跑 run #298 9/9 全绿。
+
gitea Actions self-hosted runner 记录:决定用 1 个(mac-pangolin-2,项目级·mac host·label nas·复用 jiu relay)、已删 orphan 的清理命令、launchd 持久化 + 单点韧性(runner 离线 Telegram 告警)。CI 首跑 run #298。
docs/ci-runner.md