ci: 归档 ECS 专用工作流;新增 NAS 自动部署流水线

This commit is contained in:
2026-10-10 16:33:29 +08:00
parent 0593ff7e62
commit a41a6644a4
17 changed files with 45 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
name: Fix 唐杰→鲁杰 (线上残留文本一次性改名)
# 背景:大师改名(唐杰→鲁杰)是通过后台 PATCH 改【大师档案的 displayName/honorific】完成的,
# 大师页已显示鲁杰。但当初一次性种进库的【文旅行程文本】(itinerary/masterMoments/highlights)、
# 以及 twin 的 characterPrompt/tagline/masterworks、master.intro 里的"唐杰"字面串,改名不会重写。
# 本工作流做一次【外科手术式】替换:只把这些文本字段里的"唐杰"换成"鲁杰",不动其它任何数据、
# 不重建种子(不会丢头像/作品/点赞)。只匹配含"唐杰"的文档,已经干净则自动零改动(可反复安全重跑)。
#
# ⚠ 需要 mongosh 支持 $replaceAll(MongoDB 4.4+)。生产为本地 Mongo,一般满足。
# 跑完会打印每个集合改了几条;若都为 0,说明线上早已干净。
on:
workflow_dispatch:
inputs:
confirm:
description: '输入 RENAME 确认执行(把线上残留“唐杰”改为“鲁杰”)'
required: true
type: string
jobs:
fix:
runs-on: ubuntu-latest
steps:
- name: Replace 唐杰 → 鲁杰 in tours / twins / masters text fields
if: ${{ inputs.confirm == 'RENAME' }}
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.ECS_HOST }}
username: ${{ secrets.ECS_USER }}
password: ${{ secrets.ECS_PASSWORD }}
command_timeout: 5m
script: |
set -e
cd /var/www/digitalme-api.invoratec.cn
[ -f .env ] || { echo "❌ 生产 .env 缺失,中止"; exit 1; }
MONGO_URI="$(grep '^MONGO_URI=' .env | cut -d= -f2- || echo 'mongodb://localhost:27017')"
MONGO_DB="$(grep '^MONGO_DB=' .env | cut -d= -f2- || echo 'creator_cn')"
echo "──── 目标库:$MONGO_DB ────"
mongosh "$MONGO_URI/$MONGO_DB" --quiet --eval '
const FIND = "唐杰", REP = "鲁杰";
const rp = (f) => ({ $replaceAll: { input: { $ifNull: [f, ""] }, find: FIND, replacement: REP } });
// 出现前计数
const before = {
tours: db.tours.countDocuments({ $or: [ {title:/唐杰/}, {masterMoments:/唐杰/}, {highlights:/唐杰/}, {"itinerary.title":/唐杰/}, {"itinerary.desc":/唐杰/} ] }),
twins: db.twins.countDocuments({ $or: [ {displayName:/唐杰/}, {honorific:/唐杰/}, {characterPrompt:/唐杰/}, {tagline:/唐杰/}, {masterworks:/唐杰/} ] }),
masters: db.masters.countDocuments({ $or: [ {intro:/唐杰/}, {offlineCommit:/唐杰/} ] }),
};
print("命中(改前):tours=" + before.tours + " twins=" + before.twins + " masters=" + before.masters);
const rt = db.tours.updateMany(
{ $or: [ {title:/唐杰/}, {masterMoments:/唐杰/}, {highlights:/唐杰/}, {"itinerary.title":/唐杰/}, {"itinerary.desc":/唐杰/} ] },
[ { $set: {
title: rp("$title"),
masterMoments: { $map: { input: { $ifNull: ["$masterMoments", []] }, as: "m", in: rp("$$m") } },
highlights: { $map: { input: { $ifNull: ["$highlights", []] }, as: "h", in: rp("$$h") } },
itinerary: { $map: { input: { $ifNull: ["$itinerary", []] }, as: "d", in: { $mergeObjects: [ "$$d", { title: rp("$$d.title"), desc: rp("$$d.desc") } ] } } }
} } ]
);
const rw = db.twins.updateMany(
{ $or: [ {displayName:/唐杰/}, {honorific:/唐杰/}, {characterPrompt:/唐杰/}, {tagline:/唐杰/}, {masterworks:/唐杰/} ] },
[ { $set: {
displayName: rp("$displayName"), honorific: rp("$honorific"),
characterPrompt: rp("$characterPrompt"), tagline: rp("$tagline"),
masterworks: { $map: { input: { $ifNull: ["$masterworks", []] }, as: "w", in: rp("$$w") } }
} } ]
);
const rm = db.masters.updateMany(
{ $or: [ {intro:/唐杰/}, {offlineCommit:/唐杰/} ] },
[ { $set: { intro: rp("$intro"), offlineCommit: rp("$offlineCommit") } } ]
);
print("已改:tours=" + rt.modifiedCount + " twins=" + rw.modifiedCount + " masters=" + rm.modifiedCount);
const leftT = db.tours.countDocuments({ $or: [ {title:/唐杰/}, {masterMoments:/唐杰/}, {highlights:/唐杰/}, {"itinerary.title":/唐杰/}, {"itinerary.desc":/唐杰/} ] });
const leftW = db.twins.countDocuments({ $or: [ {displayName:/唐杰/}, {honorific:/唐杰/}, {characterPrompt:/唐杰/}, {tagline:/唐杰/}, {masterworks:/唐杰/} ] });
const leftM = db.masters.countDocuments({ $or: [ {intro:/唐杰/}, {offlineCommit:/唐杰/} ] });
print("残留(改后):tours=" + leftT + " twins=" + leftW + " masters=" + leftM + " (应全为 0)");
' || { echo "❌ mongosh 执行失败(可能 Mongo < 4.4 不支持 \$replaceAll,或连接串不对)"; exit 1; }
echo "✅ 完成。刷新文旅路线详情页,D4 应显示「鲁杰·营造之道」。"
- name: Confirmation missing
if: ${{ inputs.confirm != 'RENAME' }}
run: |
echo "未执行:confirm 必须精确输入 RENAME。"
exit 1