Files
blog/scripts/setup-cnb-remotes.sh
T
zqlit 448b898e40 feat(远端): 恢复自建 Gitea 代码辅仓,OpenList 降为备选备份
用户定案:「自建 gitea 同步一下吧,openlist 也作为备选备份」。
于是把上一轮「撤销全部 git 辅仓」的决定部分回退:在线那一路回到自建 Gitea,
OpenList 上的加密 bundle 从「唯一异地备份」改为「备选异地备份」。

两层不是重复,而是失效模式不同:
  · 自建 Gitea(在线、可增量、可浏览)—— 不受任何第三方平台规则约束
  · 离线 bundle(离线、单一文件、完整历史)—— 平台全挂也能恢复

一、实际同步
- Gitea 位于 23.254.236.47:3001(Gitea 28.0.0),本机直连即可推,
  **不需要广州中转机**(旧结论「沙箱跑不通 git smart HTTP」只针对当时的代理)
- 远端停在 ed38f938(2026-10-04),落后 57 个提交,且是本地 HEAD 的**祖先**
  → 一次 fast-forward 追平,**未强推、未丢历史**
- 同步后 origin 与 gitea 均指向 5f27ad32

二、git 配置
- 恢复 remote `gitea`(凭据编在 URL 里,只落本机 .git/config,不入库)
- `pushall` 回到双推:
    !git push origin main; ec=$?; git remote | grep -qx gitea && git push gitea main; exit $ec
  · 用 `;` 而非 `&&` → 主仓挂了辅仓照样推
  · `exit $ec` → 退出码仍以主仓为准,辅仓成功不掩盖主仓失败
  · gitea 段带存在性前置判断 → 没配辅仓时静默跳过,不白报错

三、发布链路恢复 gitea(前一轮刚去掉,现按新定案加回)
- `deploy/editor-api/bootstrap.sh`
    · 新增 GITEA_URL / GITEA_USER / GITEA_PASS(凭据必须现给,不写死在脚本里)
    · PUSH_REMOTES 默认 → origin,gitea;没给 GITEA_PASS 则降级为 origin
    · 恢复「配 gitea 远端」一节;退役远端名单去掉 gitea(只留 gh / gitee)
      —— 否则新部署会把现行辅仓当成退役远端清掉
    · 结尾补一句「未启用 Gitea 辅仓」的提示
- `docker-compose.editor.yml`、`editor-api/server.mjs` → 默认 origin,gitea
- `editor-api/README.md` → 变量表同步;`editor-api/Dockerfile` → 注释补 http 情形

四、`scripts/setup-cnb-remotes.sh` 改回双远端模式
- 头部沿革、USAGE、凭据段全部重写;GITEA_PASS 走环境变量,不入库
- 退役远端循环只清 gh / gitee;pushall 写同一份定义

五、文档
- `架构总览.md`:§1.2 地址地图加「代码辅仓」行、备份行降为「备选」;
  §2 旅程图改双推;§5.1 推送重写(含别名实际定义与三条取舍);
  §5.2 远端改双行表 + Gitea 接入细节;§5.3 由「不走 git 远端」改为
  「远端与备份的分工」(三层各自的失效模式);§5.6 定位改备选;
  §6 待办 #2/#4/#7/#10 更新
- `CNB构建落地方案.md` §4.0 目标形态与定案块、§4.1 第 4 条
- `README.md` 发布流程图、推送说明、脚本表
- `scripts/backup-run.mjs` 头部注释:不再是「唯一备份」

实测:
  git push gitea main → ed38f938..5f27ad32  main -> main
  git pushall         → origin / gitea 双向同步,退出码 0
  bash -n 校验 bootstrap.sh 与 setup-cnb-remotes.sh 均通过
2026-10-06 21:42:08 +08:00

170 lines
8.1 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 主仓 + 自建 Gitea 代码同步辅仓
# =====================================================================
# 历史沿革:
# 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 虽宽松却同属国内大区 —— 多一层同类平台不如换一类介质
# 2026-10-06 一度定案「远端只剩 CNB,异地备份改走 OpenList 加密 bundle」
# ★ 2026-10-06 现行:**CNB 主仓 + 自建 Gitea 辅仓**,OpenList 上的加密
# bundle 退为**备选备份**。两层性质不同、互为补充:
# · git 辅仓 保「随时能 clone 回来、能按提交追溯」
# · 离线 bundle 保「平台全挂/账号被封时仍有一份完整历史」
# (整仓 + AES-256-GCM → 中兴 F50 上的 OpenList,
# scripts/backup-bundle.mjs,计划任务 Blog-BundleBackup 每天 03:30)
#
# 为什么不用「一个 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
#
# Gitea 辅仓默认按内置地址配,但**凭据必须现给**(不写进本文件):
# GITEA_PASS='Gitea 密码或访问令牌' \
# bash scripts/setup-cnb-remotes.sh https://cnb.cool/zqlit/blog
# 要换地址/换用户名时再带上 GITEA_URL / GITEA_USER。
#
# 回退:脚本会把改动前的配置备份到 .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,密码填令牌)
令牌:「个人设置 → 访问令牌」,勾「代码仓库 → 读写」
· 自建 Gitea 辅仓走 http://23.254.236.47:3001(账号 zqlit),**另需 GITEA_PASS**:
GITEA_PASS='Gitea 密码或令牌' bash scripts/setup-cnb-remotes.sh <CNB_URL>
· 备选异地备份走中兴 F50 上的 OpenList(与 git 远端无关):
scripts/backup-bundle.mjs 打包 + AES-256-GCM 加密 + 上传(含校验与恢复)
.workbuddy-backup/openlist-backup.env 连接与口令配置(被 git 忽略)
Windows 计划任务 Blog-BundleBackup 每天 03:30 自动跑
USAGE
exit 1
fi
# 自建 Gitea 辅仓(默认地址;GITEA_PASS 必须外部给,不写死在本文件里)
GITEA_URL="${GITEA_URL:-http://23.254.236.47:3001/zqlit/blog.git}"
GITEA_USER="${GITEA_USER:-zqlit}"
GITEA_PASS="${GITEA_PASS:-}"
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) gitea = 自建 Gitea(代码同步辅仓)
# 凭据直接编进远端 URL —— 这是「无凭据助手也能免交互推」的唯一简单写法。
# 明文只落在本机 .git/config(不提交、不推送、不进仓库)。
# (口令里若含 # 或 & 会被 sed 吃掉,那种情况请改用访问令牌。)
if [ -n "$GITEA_PASS" ]; then
GITEA_AUTH="$(printf '%s' "$GITEA_URL" | sed -E "s#^(https?://)#\1${GITEA_USER}:${GITEA_PASS}@#")"
git remote remove gitea 2>/dev/null || true
git remote add gitea "$GITEA_AUTH"
echo "gitea 远端已配置:$GITEA_URL(凭据编入 URL,仅存于本机 .git/config)"
elif git remote | grep -qx gitea; then
echo "gitea 远端已存在,本次未给 GITEA_PASS → 保持原样"
else
echo "未提供 GITEA_PASS → 跳过 gitea 远端配置(只剩 origin 一个远端)"
echo " 需要时:GITEA_PASS='xxx' bash scripts/setup-cnb-remotes.sh $CNB_URL"
fi
# 3) 清理退役远端
# gh(GitHub) / gitee 都已不在远端列表里 —— 留着只会在 `git pushall`
# 或后端按 PUSH_REMOTES 推送时撞上失效远端,白白报错。
# ★ gitea **不在**名单里:它是现行辅仓,别跟着一起清掉。
for retired in gh gitee; do
if git remote | grep -qx "$retired"; then
git remote remove "$retired"
echo "已移除退役远端:$retired"
fi
done
# 4) pushall —— CNB 与 Gitea 都推
# ★ 用 `;` 而不是 `&&`:主仓失败时辅仓照样得推上去,
# 备份的意义正在于「主仓出问题时它那儿还有」。
# 但退出码仍以主仓为准(exit $ec),免得辅仓推成功把主仓的失败盖掉。
# 先探一下 gitea 在不在,免得没配辅仓时每次 pushall 都白报一行错。
git config alias.pushall '!git push origin main; ec=$?; git remote | grep -qx gitea && git push gitea main; exit $ec'
# 5) 凭据
#
# 本机全局 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 pushall # 依次推 origin(CNB) 与 gitea(推荐)"
echo " git push origin main # 只推 CNB(触发构建)"
echo " git push gitea main # 只推 Gitea 辅仓"
echo
echo " 备选异地备份不在这里 —— 想立刻跑一次整仓加密备份:"
echo " node scripts/backup-bundle.mjs --verify --keep 7"