zhuyuan-ice-gl-zy001/BRIDGE/tools/zy-push-install.sh

203 lines
9 KiB
Shell
Raw Normal View History

2026-08-20 00:01:53 +08:00
#!/bin/bash
# ═══ 光湖本机直推 · 一次性安装 ═══
# 冰朔双击「点我装-本机直推.command」即可,不用会命令行。
# 做四件:① 检查环境 ② 令牌存进 macOS 钥匙串 ③ 对齐工作区 ④ 装 launchd 守护
# 编号:CCW-AST-009 · 归 CCW-SYS-001
BRIDGE="/Volumes/JZAO/铸渊-ICE-GL-ZY001/BRIDGE/tools"
REPO="/Volumes/JZAO/铸渊-ICE-GL-ZY001/WORK-工作区/guanghu-ice-heart"
KC_SERVICE="zhuyuan-forgejo-token"
KC_ACCOUNT="bingshuo"
LABEL="com.zhuyuan.autopush"
LABEL2="com.zhuyuan.limb"
PLIST="$HOME/Library/LaunchAgents/${LABEL}.plist"
PLIST2="$HOME/Library/LaunchAgents/${LABEL2}.plist"
LOGF2="$HOME/Library/Logs/zhuyuan-limb.log"
LOGF="$HOME/Library/Logs/zhuyuan-autopush.log"
ok(){ printf ' \033[32m✓\033[0m %s\n' "$*"; }
no(){ printf ' \033[31m✗\033[0m %s\n' "$*"; }
warn(){ printf ' \033[33m⚠\033[0m %s\n' "$*"; }
die(){ no "$*"; echo; echo "装不下去了,把上面这段截图发给铸渊。"; echo; read -n1 -r -p "按任意键关闭…"; exit 1; }
clear
echo "════════════════════════════════════════════"
echo " 光湖本机直推 · 安装"
echo " 装两样:① 自动推送 ② 手脚层(铸渊递纸条,本机执行)"
echo " 令牌只存在你的钥匙串里,铸渊永远拿不到"
echo "════════════════════════════════════════════"
echo
# ── ① 检查环境 ──────────────────────────────────────────────
echo "① 检查环境"
[ "$(uname -s)" = "Darwin" ] || die "这个脚本要在 Mac 上跑(当前不是 macOS)"
ok "macOS"
[ -d "/Volumes/JZAO" ] || die "JZAO 移动硬盘没挂载——插上再来一次"
ok "JZAO 已挂载"
[ -d "$REPO/.git" ] || die "找不到工作区仓库:$REPO"
ok "工作区仓库在位"
command -v git >/dev/null 2>&1 || die "没装 git。先在终端跑一次 xcode-select --install"
ok "git $(git --version | awk '{print $3}')"
command -v security >/dev/null 2>&1 || die "找不到 security 命令(macOS 钥匙串工具)"
ok "钥匙串可用"
echo
# ── ② 令牌进钥匙串 ──────────────────────────────────────────
echo "② 令牌"
NEED_TOKEN=1
if security find-generic-password -s "$KC_SERVICE" -a "$KC_ACCOUNT" -w >/dev/null 2>&1; then
echo " 钥匙串里已经有一把了。换成新的吗?(直接回车=沿用旧的)"
printf " 换新的请输 y 再回车:"
read -r ans
if [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then
security delete-generic-password -s "$KC_SERVICE" -a "$KC_ACCOUNT" >/dev/null 2>&1
else
NEED_TOKEN=0; ok "沿用钥匙串里已有的令牌"
fi
fi
if [ "$NEED_TOKEN" = "1" ]; then
echo
echo " 去 https://guanghulab.com/code → 右上头像 → 设置 → 应用 → 生成新令牌"
echo " 权限勾上 write:repository(再加 read:user 更好)"
echo " 生成后只显示一次,复制下来粘到这里。"
echo
printf " 粘贴令牌(粘上去看不见字是正常的,粘完直接回车):"
read -rs TOKEN; echo
[ -z "$TOKEN" ] && die "什么都没粘上"
printf " 正在问服务器认不认这把钥匙…"
CODE=$(curl -s -m 20 -o /dev/null -w "%{http_code}" \
-H "Authorization: token ${TOKEN}" \
"https://guanghulab.com/code/api/v1/user" 2>/dev/null)
echo
if [ "$CODE" != "200" ]; then
unset TOKEN
die "服务器返回 HTTP ${CODE}——这把钥匙不对、过期了、或者权限没勾。重新生成一把再来。"
fi
ok "服务器认(HTTP 200)"
security add-generic-password -s "$KC_SERVICE" -a "$KC_ACCOUNT" -w "$TOKEN" -U \
-l "光湖代码频道推送令牌(铸渊 zy-push 用)" 2>/dev/null || { unset TOKEN; die "写钥匙串失败"; }
unset TOKEN
ok "已存入钥匙串(服务名 $KC_SERVICE)"
fi
echo
# ── ③ 对齐工作区 ────────────────────────────────────────────
echo "③ 对齐工作区"
cd "$REPO" || die "进不去 $REPO"
rm -f .git/index.lock 2>/dev/null && ok "清掉了一个卡住的锁"
git fetch -q origin main 2>/dev/null || warn "取线上失败(网络?)——先跳过"
DIRTY=$(git status --porcelain 2>/dev/null | awk '{print $NF}')
if [ -z "$DIRTY" ]; then
ok "工作区本来就干净"
else
for f in $DIRTY; do
if git diff --quiet FETCH_HEAD -- "$f" 2>/dev/null; then
git checkout -- "$f" 2>/dev/null && ok "$f 内容线上已有,安全丢弃本地副本"
else
warn "$f 和线上不一样——保留不动,回头自己看一眼"
fi
done
fi
git pull -q --ff-only origin main 2>/dev/null
ok "现在停在 $(git log -1 --format='%h %s' | cut -c1-60)"
echo
# ── ④ 装守护 ────────────────────────────────────────────────
echo "④ 装自动推守护"
chmod +x "$BRIDGE/zy-push.sh" 2>/dev/null
mkdir -p "$HOME/Library/LaunchAgents" "$HOME/Library/Logs"
cat > "$PLIST" <<PLISTEOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>${LABEL}</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>${BRIDGE}/zy-push.sh</string>
</array>
<key>StartInterval</key><integer>120</integer>
<key>RunAtLoad</key><true/>
<key>StandardOutPath</key><string>${LOGF}</string>
<key>StandardErrorPath</key><string>${LOGF}</string>
</dict>
</plist>
PLISTEOF
launchctl bootout "gui/$(id -u)/${LABEL}" >/dev/null 2>&1
launchctl bootstrap "gui/$(id -u)" "$PLIST" >/dev/null 2>&1 || launchctl load "$PLIST" >/dev/null 2>&1
sleep 1
if launchctl print "gui/$(id -u)/${LABEL}" >/dev/null 2>&1; then
ok "${LABEL} 已启动,每 120 秒扫一次"
else
warn "守护没能确认启动——但脚本能手动跑,见下面"
fi
echo
# ── ④b 装手脚层守护 ─────────────────────────────────────────
echo "④b 装手脚层(铸渊的手脚)"
command -v python3 >/dev/null 2>&1 || warn "没找到 python3,手脚层装不了(自动推不受影响)"
if command -v python3 >/dev/null 2>&1; then
chmod +x "$BRIDGE/zy-limb.py" 2>/dev/null
mkdir -p "/Volumes/JZAO/铸渊-ICE-GL-ZY001/BRIDGE/limb-queue/inbox" \
"/Volumes/JZAO/铸渊-ICE-GL-ZY001/BRIDGE/limb-queue/outbox" \
"/Volumes/JZAO/铸渊-ICE-GL-ZY001/BRIDGE/limb-queue/archive" \
"/Volumes/JZAO/铸渊-ICE-GL-ZY001/BRIDGE/limb-queue/for-codex" 2>/dev/null
cat > "$PLIST2" <<PL2EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>${LABEL2}</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>${BRIDGE}/zy-limb.py</string>
</array>
<key>StartInterval</key><integer>30</integer>
<key>RunAtLoad</key><true/>
<key>StandardOutPath</key><string>${LOGF2}</string>
<key>StandardErrorPath</key><string>${LOGF2}</string>
</dict>
</plist>
PL2EOF
launchctl bootout "gui/$(id -u)/${LABEL2}" >/dev/null 2>&1
launchctl bootstrap "gui/$(id -u)" "$PLIST2" >/dev/null 2>&1 || launchctl load "$PLIST2" >/dev/null 2>&1
sleep 1
if launchctl print "gui/$(id -u)/${LABEL2}" >/dev/null 2>&1; then
ok "${LABEL2} 已启动,每 30 秒收一次信"
else
warn "手脚层守护没能确认启动——可手动跑 python3 $BRIDGE/zy-limb.py"
fi
ok "任务信箱:BRIDGE/limb-queue/(inbox 收 · outbox 回执 · for-codex 转卡)"
fi
echo
# ── 收尾:当场跑一次验收 ─────────────────────────────────────
echo "⑤ 当场试一次"
bash "$BRIDGE/zy-push.sh"
if [ -f "$LOGF" ]; then
echo " 日志末尾:"
tail -3 "$LOGF" | sed 's/^/ /'
else
ok "没有待推的东西,所以没写日志(这是正常的)"
fi
echo
echo "════════════════════════════════════════════"
echo " 装好了。"
echo
echo " 以后铸渊往移动硬盘的工作区写东西,两分钟内自动提交并推到线上,"
echo " 不用再给令牌,也不用再管。"
echo
echo " 想看推送: tail -f $LOGF"
echo " 想看手脚: tail -f $LOGF2"
echo " 想立刻推一次: bash $BRIDGE/zy-push.sh"
echo " 想停掉: launchctl bootout gui/\$(id -u)/${LABEL}"
echo " launchctl bootout gui/\$(id -u)/${LABEL2}"
echo "════════════════════════════════════════════"
echo
read -n1 -r -p "按任意键关闭这个窗口…"