Skip to content

Commit 07ac2ac

Browse files
authored
ci(sync-uuid): SSH 进自建服务器跑 DB 脚本(替代 Neon 直连) (#304)
* ci(sync-uuid): 迁移到 SSH 进自建服务器跑脚本 DB 从 Neon 迁到自建后只绑 127.0.0.1:5432,GH runner 直连不通。最干净的 方案是 SSH 进服务器跑——服务器上有完整 repo clone + 本机能到 PG + 已有 github ssh key 可以 push 回来。 - 用 appleboy/ssh-action@v1.2.0,三件套 secrets:SERVER_HOST / SERVER_USER / SERVER_SSH_KEY - 脚本流程:fetch + reset --hard 到触发 commit → pnpm install + prisma generate → uuid.mjs → backfill-contributors.mjs → 只有 diff 时 commit [skip ci] + push - set -euo pipefail 保证任何一步失败整个 action 失败 - command_timeout 15m 给 backfill 足够余量 配套一次性准备(已完成,不在 CI 里): - 服务器 ~/.ssh/authorized_keys 加 gh-actions-leaderboard 公钥 - ~/involution-hell-project/frontend/.env 的 DATABASE_URL 改指 127.0.0.1 注:scripts/generate-leaderboard.mjs 还在 package.json 的 prebuild 钩子里, Vercel 部署时仍会尝试跑。该问题独立处理:要么挪到本 workflow,要么让 Vercel build 时优雅降级(失败跳过用上次提交的 JSON)。 * ci(sync-uuid): 加 3 道防御检查保住署名记录 审计后发现原 workflow 有 3 处边缘风险可能让 uuid.mjs/backfill 产出错数据: 1. 脏工作树被 git reset --hard 抹掉 → 可能浪费 docId 或抹掉手工改动 2. DATABASE_URL 缺失时 backfill 隐性降级成本轮快照 → JSON 被覆盖呈现错误累计 3. DB 行数异常低(被意外清库)→ 增量累计从 0 起算,GH API 单文件最多 N 页外的老 commits 永远丢 加三道闸: - git status --porcelain 非空 → fail loud 强制人工介入 - DATABASE_URL 空 → fail(GITHUB_TOKEN 只 warn) - doc_contributors < 200 行 → fail(迁移完成时 ~295 行,保守下限) 附长注释说明每项保护对应脚本里哪个不变量。以后有人看 workflow 能立刻知道每段为啥不能删。
1 parent 0b31f38 commit 07ac2ac

1 file changed

Lines changed: 78 additions & 8 deletions

File tree

.github/workflows/sync-uuid.yml

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,17 @@ name: Docs Backfill (on docs changes)
44
# 原因:DB 从 Neon 迁到服务器自建 PG 后只绑 127.0.0.1:5432,不对公网暴露。
55
# 设计权衡见 wiki Frontend-Auth-And-Admin / 后端 docs/database.md。
66
#
7+
# ⚠️ 这个 workflow 维护的是**贡献者署名记录的生命线**——谁写了哪篇文档、
8+
# 文件改名/移动后署名不丢,全靠底层两个脚本:
9+
# - scripts/uuid.mjs 生成/保持 docId frontmatter(永不改写已有值)
10+
# - scripts/backfill-contributors.mjs 按 docId 累加 GitHub commits 到 DB,
11+
# doc_paths 表维护历史路径并集跨改名追踪
12+
# 若本 workflow 跑坏了(生成错 docId / 写坏 JSON / 写错 DB),署名可能丢失。
13+
# 下面每一步前都有防御性检查,出错就 fail loud 不吞错。
14+
#
715
# Secrets 依赖:
816
# SERVER_HOST / SERVER_USER / SERVER_SSH_KEY — SSH 远程登录三件套
9-
# (私钥生成方式 + 公钥已写入服务器 ~/.ssh/authorized_keys,见仓库 wiki)
17+
# (私钥生成方式 + 公钥已写入服务器 ~/.ssh/authorized_keys, wiki)
1018

1119
on:
1220
push:
@@ -51,28 +59,90 @@ jobs:
5159
BRANCH="${GITHUB_REF_NAME:-main}"
5260
cd /home/ubuntu/involution-hell-project/frontend
5361
54-
# 1. 同步仓库到触发本次 workflow 的 commit
62+
# ============================================================
63+
# 0. 脏工作树检查
64+
# ------------------------------------------------------------
65+
# 为什么重要:下一步 git reset --hard 会抹掉所有未提交改动。
66+
# 如果上次 workflow 跑到一半 uuid.mjs 写了 docId 但 backfill 失败没
67+
# commit,这些"生成了的新 docId"在脏树里。reset 后 uuid.mjs 会生成
68+
# 不同的新 UUID——不丢署名(因为从未 commit 到 main),但浪费 id
69+
# 且可能造成 docId 分叉留给下一次排查。
70+
#
71+
# 更严重的场景:如果有人手工在服务器上 hotfix MDX 忘 commit,
72+
# reset 会悄悄抹掉。一律 fail loud 强制人工介入更安全。
73+
# ============================================================
74+
if [[ -n "$(git status --porcelain)" ]]; then
75+
echo "::error::服务器 frontend 工作树不干净,拒绝 reset。先人工处理后再重跑。"
76+
git status --short
77+
exit 1
78+
fi
79+
80+
# 同步仓库到触发本次 workflow 的 commit
5581
git fetch --prune origin
5682
git checkout "$BRANCH"
5783
git reset --hard "origin/$BRANCH"
5884
59-
# 2. 依赖和 Prisma client(frontend .env 里 DATABASE_URL 已指本地 PG)
85+
# ============================================================
86+
# 1. 加载环境变量 + 必要字段校验
87+
# ------------------------------------------------------------
88+
# DATABASE_URL 缺失时 backfill 会隐性降级(shouldSyncDb=false),
89+
# 生成的 JSON 内容是"本轮快照"而非"DB 累计值",覆盖 commit 回仓
90+
# 会把累计呈现变成单次快照——**视觉上像数据丢了**但 DB 没动。
91+
# 直接 fail 不给它走降级路径。
92+
# ============================================================
6093
set -a && . ./.env && set +a
94+
if [[ -z "${DATABASE_URL:-}" ]]; then
95+
echo "::error::DATABASE_URL 未配置,拒绝运行以免 JSON 降级成本轮快照"
96+
exit 1
97+
fi
98+
if [[ -z "${GITHUB_TOKEN:-}" ]]; then
99+
echo "::warning::GITHUB_TOKEN 未配置,GitHub API rate limit 60/h 会打爆"
100+
fi
101+
102+
# ============================================================
103+
# 2. DB 健康检查
104+
# ------------------------------------------------------------
105+
# 如果本地 PG 意外被清库或未迁移完成,doc_contributors 表可能是空的。
106+
# 从空 DB 起增量累计 → 早期已经超出 GitHub API 单文件 commits 最多 N 页
107+
# 范围的老 commits 永远拉不回来 → 署名丢失。
108+
#
109+
# 下限 200 行是保守值:迁移完成后 doc_contributors 约 295 行,
110+
# 低于 200 视为"异常状态",要人工确认后才能继续。
111+
# ============================================================
112+
CONTRIB_COUNT=$(docker exec involution-postgres \
113+
psql -U neondb_owner -d involution_hell -tAc \
114+
"SELECT count(*) FROM doc_contributors;" 2>/dev/null || echo "0")
115+
if [[ "$CONTRIB_COUNT" -lt 200 ]]; then
116+
echo "::error::doc_contributors 只有 $CONTRIB_COUNT 行(预期 >= 200),DB 状态异常,拒绝运行。"
117+
echo "::error::如果是故意重置 DB,临时把本检查注释掉,一次跑完再恢复。"
118+
exit 1
119+
fi
120+
echo "DB 健康检查通过:doc_contributors 有 $CONTRIB_COUNT 行"
121+
122+
# 3. 依赖和 Prisma client
61123
pnpm install --frozen-lockfile
62124
pnpm prisma generate
63125
64-
# 3. 给 docs 补 docId frontmatter(幂等;没新增就啥都不改)
126+
# ============================================================
127+
# 4. 跑脚本
128+
# ------------------------------------------------------------
129+
# uuid.mjs:幂等补 docId;已有 docId 的文件绝对不改。
130+
# backfill-contributors.mjs:按 docId 增量累加,doc_paths 表合并历史路径,
131+
# 翻译版跳过,失败即 exit 1 让本 step fail 不进 commit。
132+
# ============================================================
65133
pnpm exec node scripts/uuid.mjs
66-
67-
# 4. 回填 contributors 并写 generated/doc-contributors.json
68134
pnpm exec tsx scripts/backfill-contributors.mjs
69135
70-
# 5. 自动提交 —— 仅当 MDX / JSON 有实际变动时才推
136+
# ============================================================
137+
# 5. 自动提交
138+
# ------------------------------------------------------------
139+
# 只 commit MDX frontmatter 改动 + 生成的 JSON,不包含任何其他脏文件。
140+
# [skip ci] 防止自提交再次触发本 workflow 死循环。
141+
# ============================================================
71142
if ! git diff --quiet -- 'app/docs/**/*.md' 'app/docs/**/*.mdx' generated/doc-contributors.json; then
72143
git config user.name "github-actions[bot]"
73144
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
74145
git add 'app/docs/**/*.md' 'app/docs/**/*.mdx' generated/doc-contributors.json
75-
# [skip ci] 防止自提交再次触发本 workflow 死循环
76146
git commit -m "chore(docs): sync doc metadata [skip ci]"
77147
git push origin "$BRANCH"
78148
else

0 commit comments

Comments
 (0)