把 Round1 四条已验证学习整合进既有文件(就近插入·保持风格·零孤儿新文件): - saa-graph-orchestration §6:铁律「worker succeeded ≠ 准予发布」(split-brain 防线)——九门 runnableOk=机制可玩 ≠ 准予发布,发布裁决归治理层,生产化前安全门由 W-G1 GP9 接管(来源 Lane B agent-loop-v1 退役登记) - staging-ops §3:配方「隔离实例 + -D 注入真验 feature-flagged 后端改动」——起 :48090 隔离实例、JVM -D 注开关+safety baseUrl/key/model,零改 repo/yaml、live 不动(来源 Lane E G1 GP9 10/10 真验) - ui-walkthrough-cdp §3:小配方「localStorage 注入 token 过 requiresAuth 走查」——免登录直达受保护页只读走查(来源 Lane E G0) - 2026-06-16-生成引擎-并行编排 §3:硬规则#7「ultracode 并行 worktree 防悬空提交」——git ops 必须 git -C <worktree>、禁 commit 主 checkout、主 agent 推送前核验 commit 真在其分支(来源 Lane E 错落成悬空 commit 已 cherry-pick 救回) README 索引无需动(4 处均为既有文件内容补充,非结构性增删改名)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.9 KiB
staging 运维配方(机器分工 / 代码同步 / 重部署 / 构建门 / 冒烟)
staging 全栈在 mini-desktop(100.64.0.7):huijing 单体 :48080 + game-studio :4173 + game-admin :4174 + 隔离 MySQL/Redis 容器;共享基建(Gitea/MySQL/Redis/MinIO/new-api)在 mini-infra(100.64.0.8)。 本配方由 2026-06-09~11 多波实战蒸馏(M1 真跑 / 黄金闭环 / UI 走查 / Wave4 集成门);红线类条目同步收录于
../rules/engineering-conventions.md。真 UI 走查另见ui-walkthrough-cdp.md。
1. 机器分工铁律(四机)
- 创始人本地工作站 → lili-mac(M1 Pro / 32G / ARM;不入 Tailscale 调度,会休眠合盖):跑 Claude Code 主会话、本地全栈 dev、本地浏览器/CDP 快走查、
mvn/npm快构建迭代。两条边界:① ARM≠x86,Mac 产出的 JAR/前端 bundle 架构中立可用,但 Docker 镜像 + smoke 门必须在 mini-desktop x86 出(否则镜像架构错、与 prod 不同构=半假门);② Mac 上 CDP 只算"快走查"加速开发,e2e 验收门仍只认 mini-desktop 结果(服务+浏览器同机 localhost,见game-e2e-cdp-harness.md)。 - 权威验收 / 重型构建 / 测试 / staging app / 浏览器 e2e 门 → mini-desktop(15G;java17 + mvn3.8.7 + docker + node22 + chrome146;与 prod 同构)。
- 常驻无人值守 → 6c6g:常开的 agent 编排/Workflow、cron 定时、后台批跑、git 操作(Mac 会休眠故常驻活只能留此)。禁跑重活:重型前端构建 OOM、chrome 连续 exit 144。元规则:同一失败签名第二次出现 → 换机器,不再换启动姿势。
- 共享基建 → mini-infra(绝不在其上跑项目 app / 重型构建;缺 RocketMQ+Nacos,MVP 未部署)。
2. 代码同步(分类器约束)
scp/rsync源码树会被分类器语义拦截(settings 放行也没用)。正解 = git push 到 Gitea → mini-desktop 匿名 HTTP clone/pull:http://101.200.34.71:3000/zizi-al/games-development-ai.git(:3000 HTTP 匿名读,非 :2222 SSH)。- 单文件传输:
cat local | ssh mini-desktop 'cat >/tmp/x'(分类器不拦单文件)。 - 远程脚本省心写法:
ssh mini-desktop 'bash -ls' <<'REMOTE' ... REMOTE(-l拿 PATH,-s读 stdin,免引号地狱)。 - push 竞态与管道掩码(2026-06-12 实翻):①大资产 push 在途时再发 push 会撞 Gitea ref 锁(
remote rejected (failed to update ref)/failed to push some refs)——同仓 push 串行化,等上一笔落地(git ls-remote核)再发;②git push 2>&1 | tail -1的退出码=tail 恒 0,会吞掉推送失败——push 不接管道,要么裸跑判$?,要么tee+PIPESTATUS[0]。每次 push 后以git ls-remote origin <branch>实证远端头,不信本地输出。
3. 后端重部署标准序(授权窗口内执行)
教训:
~/game-staging/repo曾是 stale 克隆,「构建源 ≠ 运行 jar」翻过车——每次部署按此序,以字节码实证收口。
- 备份运行 jar 到
/tmp; - 清本地独有 untracked(
application-staging.yaml以 origin 版为准——origin 是含 executor/passport 段的超集); git reset --hard origin/dev/2.0.0;mvn clean install -pl huijing-server -am -DskipTests(warm .m2 约 33s);- jar 字节码实证含本次修改:
unzip -p <fat.jar> BOOT-INF/lib/<模块>*.jar核对 .class; start-app.sh重启 → 验 health 200 / 四模板 banner / Flyway up-to-date / admin-api 200(M1 无回归)。
高风险/整机重部署安全变体——隔离验证后再切(2026-06-16 整机改新命名空间
com.wanxiang.huijing实证):步 4 构建出新 jar 后,先用新 jar 在隔离端口(如:48090)+ staging profile 起一个实例,live:48080全程不动;在隔离实例上验全(Flyway 全绿无冲突 / health 200 / 本波新端点逐个 200 code=0 / 免短信登录拿 token)。隔离验全过才切:停老 →start-app.sh起新 → 复验(同上 +smoke-test.sh)。任一步 fail → 停新、用/tmp备份 jar 恢复:48080→ 确认 live 恢复。严禁无隔离验证就切 live;备份 jar 留到复验全过再删。 注:start-app.sh/模块名随命名空间改名已更新(huijing-server),重部署前核对 jar 路径与现命名空间一致。
隔离实例 +
-D注入「真验 feature-flagged 后端改动」(不切 live、零改 repo/yaml)——2026-06-16 Lane E G1 实证(GP9 10/10 真验即用此法):要在 staging 真跑一个默认关闭的 feature-flag 后端改动(验它打开后行为对、关着时现行字节不变),不要改 repo 里的application-staging.yaml、也不要重部署 live。配方:用已部署的 jar(或步 4 新 jar)在隔离端口(如:48090)起一个实例,开关与外部依赖全经 JVM-D注入,例:java -jar <fat.jar> --server.port=48090 --spring.profiles.active=staging \ -Daigc.control-plane.enabled=true \ -Daigc.safety.base-url=http://100.64.0.8:3000 -Daigc.safety.api-key=<key> -Daigc.safety.model=<model>Spring 的
-D/--key=val优先级高于 yaml,故开关与 baseUrl/key/model 临时注入即生效,repo 与 live 实例一行不动。在此隔离实例上跑负例集真验(如 10 条恶意 brief 全被 GP9 拦),验完即停,flag 在主干仍默认关 = 现行字节零变。与上一条「整机重部署安全变体」互补:那条是"新 jar 验全过才切 live",这条是"现行字节不动、只临时验一个 flag 行为"。
教训速记(区分两个隔离用法):同样起
:48090隔离实例——「重部署安全变体」目标是最终要切 live(验全过 → 停老起新);「-D注入真验 flag」目标是永不切 live(只验 flag 行为,验完即停,主干字节不变)。混用会误把"只想验 flag"做成了"切 live"。
4. 构建/测试门(红线)
vue-tsc --noEmit是假门禁,前端验证一律npm run build。- mini-desktop 构建 game-studio 必须
npm run build -- --mode staging(vite preview 直接 serve 工作树 dist,默认 build = 事实上改部署、mock 中间件接管且无 warn)。 - huijing 前端(game-admin)稳定配方:pnpm9(
corepack prepare pnpm@9.15.4 --activate,一举绕开 pnpm10+ 的 lockfile 镜像校验与构建脚本审批两道坎)+ 前端目录.npmrc设 npmmirror →node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build(绕 pnpm-run 预检)。node_modules 腐化(如混入 vite8 / 杂散pnpm-workspace.yaml报 packages 缺失)→ 移开杂散文件 → 清装精确回钉版本。 - huijing-module-system 测试:
SPRING_DATA_REDIS_PORT=26379 mvn test ...(宿主 16379 被 staging redis 占用带密码,嵌入式 RedisServer 失败被吞 → NOAUTH 假红)。 - mini-desktop 长驻 serve/后台进程(2026-06-11 T1-spike 双 lane 实证):ssh 会话内
nohup &/setsid仍可能随会话 teardown 被 SIGHUP 连带杀(症状=稍后访问 ERR_CONNECTION_REFUSED)。稳定配方:首选systemd-run --unit=<name>起 durable 单元;次选独立 launchersetsid bash -c 'exec node serve.cjs'双脱离 + 起服后 5×6s 探活门(curl 200 连续过)确认常驻再继续。另:长任务后台进程严禁与pkill/curl写进同一 heredoc 串行(竞态留孤儿进程占 pid 不占端口)。
5. 冒烟门
- API 就绪门:
deploy/smoke-test.sh(只读 12 项)+--deep(13 项含 generate 入队),含 CORS/鉴权(test1 token)验证。 - gotcha:feed item 的
packageUrl恒 null,真实取包走GET /app-api/runtime/package/{versionId}。 - API 全绿 ≠ UI 通:编排器旁路会掩盖 UI 缺陷,用户可见波次收口前必须做一次真 UI 走查(见
ui-walkthrough-cdp.md)。