Files
blog/scripts/setup-cnb-remotes.sh
T
zqlit 5f27ad321d chore(备份): 异地备份定案为 OpenList 离线 bundle,撤销全部 git 辅仓
用户定案:「辅助仓就用 openlist,其他不再考虑」。
据此把前一轮为 Gitee 铺的路全部收回,git 远端只剩 CNB 一个。

一、git 配置收口
- `pushall` 别名 `origin + gitee` → `!git push origin main`(只推唯一远端)
- 移除 `gitea` remote(自建 23.254.236.47:3001)—— 远端仓库本身没删,
  需要时可 `git remote add` 恢复;改动前配置存
  `.workbuddy-backup/git-remotes.20261006-211516.txt`
- 确认无 gitee 相关 credential 残留

二、发布链路去 Gitee 化(6 处)
- `deploy/editor-api/bootstrap.sh`
    · 删掉 GITEE_URL / GITEE_SSH_KEY 两个变量与「没给私钥就降级」的分支
    · PUSH_REMOTES 默认 → origin
    · 原「配 gitee 辅仓远端」一节改为「清理退役远端」循环(gh/gitee/gitea),
      让从旧部署续用的工作区自动恢复干净
- `docker-compose.editor.yml`、`editor-api/server.mjs` → 默认值 origin
- `editor-api/README.md` → 变量表同步
- `editor-api/Dockerfile` → 注释里的「CNB / GitHub」改「CNB」
- `blog-admin/src/routes/rss/tools.ts` → deploy-notify 的注释里
  「与 Gitea Actions 的构建通知配套」改为中性描述
  (该轮询链路 2026-10-04 起已被 CNB 国内节点直传取代)

三、`scripts/setup-cnb-remotes.sh` 重写为单远端模式
- 去掉 GITEE_URL / GITEE_TOKEN 参数、校验、凭据写入与自检提示
- 新增「清理退役远端」步骤
- 凭据处理改为「已存在空的 credential.helper 就不再添加」,
  不再用 --replace-all —— 本仓另有一个从 `$HOME/.workbuddy/secrets/cnb-token`
  读令牌的自定义 helper,那是有效的,不能被脚本抹掉

四、备份升级为「唯一辅仓」的配置
- 保留份数 3 → 7(一周窗口;每份 605.5 MB ≈ 4.2 GB,F50 有 256 GB)
    · `scripts/backup-task.cmd` 默认参数 --keep 7
    · `scripts/backup-bundle.mjs` 的 KEEP 默认值同步为 7
      (原先写的是 2,一直被命令行参数掩盖着)
- 远端目录 `/本地/备份` → `/本地/备份/blog-bundle`:
  根目录是用户自己在用的(放着 github-zqlit-*、local-repos-* 等手工备份),
  实测发现直接放根下的 bundle 已被清掉 —— 改子目录隔离,避免混放与误删

五、新增 `scripts/backup-run.mjs`:备份的推荐入口 + 失败告警
- 读 `.workbuddy-backup/openlist-backup.env`(只补空缺,环境变量优先)
- 跑 backup-bundle.mjs 并实时透传输出,同时留一份日志尾部
- 退出码非 0 → 经 `scripts/send_mail.js` 发告警邮件(附日志尾部与常见原因);
  成功默认不发,`--notify-success` 才发
- 退出用 `process.exitCode` 而非 `process.exit()`,避免截断未排干的 stdout
- 发信失败不改判备份退出码 —— 通知不该掩盖真正的故障
- 理由:这是当前**唯一**的异地备份,而「每天自动跑」的任务最典型的失败模式
  恰恰是静默的(F50 被带出门、换了网段、OpenList 没起来、口令改过……),
  没有告警就要等到真要用备份那天才发现
- `scripts/backup-task.cmd` 改调它

六、文档
- `架构总览.md`
    · §1.2 地址地图:备份行改指 F50/OpenList;通知行补「兼做备份失败告警」
    · §2 旅程图:双推改单推,并说明备份换了介质
    · §5.1 / §5.2 推送与远端:只剩 origin;补「已移除远端」表与恢复命令;
      GitHub 退役记录保留并补上「CI 定义也已删除」
    · §5.3 由「辅仓选型」改为「异地备份的定案」—— 明确不走 git 远端;
      平台对比数据保留备查,并注明 `bin/linux/hugo` 出库不必再做了
    · §5.6 补「唯一备份」定位、专属子目录、失败告警、keep 7、SMTP 配置键,
      实测数据更新为本次复测值
    · §6 待办:#2 定案、#3 不必做、#4 已移除、#8 已更新、#10 定位升级,
      新增 #11(F50 目录使用约定)
- `CNB构建落地方案.md` §4.0:双远端改单远端,脚本示例去掉 Gitee 参数
- `README.md`:推送说明改单推;脚本表补 backup-run.mjs

实测(2026-10-06,本轮复测):
  bundle 7.4s / AES-256-GCM 加密 1.3s / 上传 19.2s(31.6 MB/s)
  / 读回 sha256 一致 → 端到端 60.6s,退出码 0
  告警邮件链路已实测(发出一封「备份成功」验证信)

★ 一处过程记录,供以后避免重复踩坑:
  中途我把「本机沙箱里 `env -u ... cmd > file` 会让输出整个消失」
  误判成 process.exit 截断 stdout,并据此改了日志实现;
  随后用 `env -u FOO echo hi > file`(同样零输出)证伪 ——
  那是沙箱文件重定向的伪影,与脚本无关。相关改动已回滚,
  只留下本身无害的 process.exitCode 写法。
2026-10-06 21:27:28 +08:00

136 lines
5.9 KiB
Bash
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.
#!/usr/bin/env bash
# =====================================================================
# 配置 git 远端 —— 本项目只有 CNB 一个远端
# =====================================================================
# 历史沿革:
# 2026-10-04 从「GitHub + 自建 Gitea 双推」切到「CNB 主 + GitHub 备份」
# 2026-10-06 GitHub 账号被平台标记、仓库被按 AUP 清空 → 移除 gh
# 2026-10-06 一度改为「CNB 主 + Gitee 辅」,但 Gitee 免费版卡在
# 单仓 500MB / 单文件 50MB 两道硬门槛(本仓 bin/linux/hugo 83.1MB),
# 云效 Codeup 虽宽松却同属国内大区 —— 多一层同类平台不如换一类介质
# ★ 定案:**异地备份不走 git 远端**。
# 备份 = 整仓 bundle + AES-256-GCM 加密 → 中兴 F50 上的 OpenList
# (scripts/backup-bundle.mjs,计划任务 Blog-BundleBackup 每天 03:30)
# 故 git 远端只剩 CNB origin,pushall 也只推 origin。
#
# 为什么当初不用「一个 remote 挂多个 pushurl」:
# 实测(2026-10-04)git 对多个 pushurl 是「顺序推、遇错即停」——
# 第一个失败,后面的远端一个都不会推,那就失去备份意义了。
# 所以真要加辅仓,得用「独立 remote + 别名」而不是 pushurl。
# (现行方案连这个都不需要了 —— 备份已经换介质。)
#
# 用法:
# bash scripts/setup-cnb-remotes.sh <CNB_URL>
#
# 例:
# bash scripts/setup-cnb-remotes.sh https://cnb.cool/zqlit/blog
#
# 附带令牌(直接写进 Windows 凭据管理器,以后不再输):
# CNB_TOKEN='你的令牌' bash scripts/setup-cnb-remotes.sh https://cnb.cool/zqlit/blog
#
# 回退:脚本会把改动前的配置备份到 .workbuddy-backup/git-remotes.<时间戳>.txt
# =====================================================================
set -euo pipefail
CNB_URL="${1:-}"
if [ -z "$CNB_URL" ]; then
cat <<'USAGE'
用法:bash scripts/setup-cnb-remotes.sh <CNB_URL>
提示:
· CNB 仓库地址直接用仓库页地址,带不带 .git 都行
· CNB **不支持 SSH**,只能 HTTPS + 访问令牌(用户名固定填 cnb,密码填令牌)
令牌:「个人设置 → 访问令牌」,勾「代码仓库 → 读写」
· 本项目**没有** git 辅仓。异地备份走中兴 F50 上的 OpenList:
scripts/backup-bundle.mjs 打包 + AES-256-GCM 加密 + 上传(含校验与恢复)
.workbuddy-backup/openlist-backup.env 连接与口令配置(被 git 忽略)
Windows 计划任务 Blog-BundleBackup 每天 03:30 自动跑
USAGE
exit 1
fi
case "$CNB_URL" in
https://cnb.cool/*) ;;
*) echo "地址看起来不是 CNB 的:$CNB_URL"; exit 1 ;;
esac
ROOT="$(git rev-parse --show-toplevel)"
cd "$ROOT"
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP=".workbuddy-backup/git-remotes.$STAMP.txt"
mkdir -p .workbuddy-backup
{
echo "# 改动前的 git 远端配置($STAMP)"
echo "# 用途:回退参考。本文件可能含明文凭据,勿提交、勿外传。"
echo
echo "## git remote -v"
git remote -v
echo
echo "## 原始 remote.* 与 credential.* 配置"
git config --local --get-regexp '^(remote|credential)\.' || true
} > "$BACKUP"
echo "原配置已备份:$BACKUP"
# 1) origin = CNB(唯一远端,fetch + push,触发构建)
git remote remove origin 2>/dev/null || true
git remote add origin "$CNB_URL"
# 2) 清理退役远端
# gh(GitHub) / gitee / gitea 都已不在备份体系内 —— 留着只会在
# `git pushall` 或后端按 PUSH_REMOTES 推送时撞上失效远端,白白报错。
for retired in gh gitee gitea; do
if git remote | grep -qx "$retired"; then
git remote remove "$retired"
echo "已移除退役远端:$retired"
fi
done
# 3) pushall
# 现在只有一个远端,但仍保留这个别名 —— 文档与肌肉记忆都在用它,
# 将来若真要再加辅仓,改这一行即可。
git config alias.pushall '!git push origin main'
# 4) 凭据
#
# 本机全局 helper 是 GCM(git-credential-manager.exe)。实测它对 cnb.cool 这类
# 第三方 HTTPS 远端会**每次都弹窗**,而且 GCM_INTERACTIVE=never +
# GIT_TERMINAL_PROMPT=0 都压不住 —— git ls-remote 直接挂死(timeout 25s 未返回)。
# → 本仓按需补一个**空的** credential.helper 条目遮蔽全局 GCM,
# 再显式改用 wincred:同样写 Windows 凭据管理器(加密),但没有 UI 弹窗。
# (另:PortableGit 未打包 git-credential-store,exec-path / mingw64/bin 都没有)
#
# ★ 用「已存在就不再加」而不是 --replace-all:本仓可能另有一个从文件读令牌的
# helper($HOME/.workbuddy/secrets/cnb-token),那是有效的,不能被脚本抹掉。
# 也避免重复运行把空条目越堆越多。
store_cred() { # host username password
printf 'protocol=https\nhost=%s\nusername=%s\npassword=%s\n\n' "$1" "$2" "$3" \
| git credential-wincred store
}
if [ -n "${CNB_TOKEN:-}" ]; then
if ! git config --local --get-all credential.helper 2>/dev/null | grep -qx ''; then
git config --local --add credential.helper ""
fi
git config --local credential.https://cnb.cool.helper wincred
store_cred cnb.cool cnb "$CNB_TOKEN"
echo "CNB 凭据已写入 Windows 凭据管理器(wincred,无弹窗)"
else
echo "未提供 CNB_TOKEN,已跳过凭据写入。需要时重跑:"
echo " CNB_TOKEN='你的令牌' bash scripts/setup-cnb-remotes.sh $CNB_URL"
fi
echo
echo "=== 当前远端 ==="
git remote -v | sed -E 's#://[^@/]*@#://***@#g'
echo
echo "=== 下一步 ==="
echo " git push origin main # 推 CNB(触发构建)"
echo " git pushall # 同上(别名,现在只含这一段)"
echo
echo " 异地备份不在这里 —— 想立刻跑一次整仓加密备份:"
echo " node scripts/backup-bundle.mjs --verify --keep 7"