5b65ed9579
按草案逐条落到正本,并把三处已知错误的口径改回: ① 测试语义:删掉"单测跑的是构建产物,不是源码"这条被过度推广的说法。 只有"跑产物"的套件(端到端 / 契约 / 产物自检)才必须排在构建之后; go test 自己编译测试程序、pytest 直读源码、vitest 默认也跑源码。 写错这条的代价是给每个套件加假依赖、拖慢门禁并制造假故障。T8 同步改。 ② CI 与 CD 分离:触发表删掉"推默认分支 → 自动部署测试环境",作业划分表删掉 deploy:test 行, §4.6 标注为"项目自己的 CD、不属于通用 CI",速查表同步。 ③ 门禁入口:统一为 make verify(名字可不同,但 AGENTS/Runbook/CI 必须指同一个), §3.1、§8 清单、§9 速查表一致。 ④ 新增 §4.8「必需检查清单与结果口径」:10 项必需检查的判据表 + 三条结果口径 (失败即停但汇总照做、not_run/skipped 不算过、汇总故障不能报绿), 以及预览/通知作为旁路的规则。 ⑤ 接入文档:修掉"直推也拦得住"这句错口径,并写明接入器不再自动合并、 --merge-pr 会先核对状态;试点记录里那一步标注为"当时的自动合并行为已改"。 ⑥ 03/04/05 里的同源表述一并同步(生成物 jobs 与假成功占位的判据)。 验证:本批 18 处精确替换在脚本里逐处断言"恰好命中 1 次"(DRY-RUN 先过一遍再应用); 替换后全仓 grep 复查,旧口径只在"说明它已被改掉"的上下文里出现。
168 lines
14 KiB
Markdown
168 lines
14 KiB
Markdown
# 待配置事项清单
|
||
|
||
> 每项:**现状(已核实)→ 要做什么 → 为什么 → 怎么验证 → 谁来做**。
|
||
> 优先级:**P0** = 不做则规范形同虚设;**P1** = 影响发布可靠性;**P2** = 一致性/卫生。
|
||
> 现状全部来自本次实测(命令在括注里)。
|
||
>
|
||
> ⚠️ 本清单只讲"还差什么";**"怎么让它以后默认生效"(三渠道 + 新工程 5 步)见 `05-应用机制-让规范在以后所有工程生效.md`** —— 别把两份读串。
|
||
|
||
---
|
||
|
||
## P0
|
||
|
||
### 1. 分支保护 —— **已定:默认不开**(不需要动)
|
||
|
||
- **决定**:按原稿口径,`main` **不受保护**,所有改动直接进 `main`(正本 §1.1 / §1.3)。
|
||
- **现状**:曾给 `Weknora/knowledge-governance` 开过一次(禁直推 + 强制 `build / build (push)`),
|
||
**已关掉**;7 个仓现在 `GET /repos/{r}/branch_protections` 全为 `[]`。
|
||
- **这条知识别丢**:将来真需要"谁都不能直推"时,开保护**前**必须做 `06-接入既有工程.md` §2 的体检 ——
|
||
**盲目勾"必须状态检查通过"会让 PR 永远等一个不会出现的检查**。判据仍然有效,只是默认不用它。
|
||
- **可逆**:开/关都是一次 API 调用或网页点一下,不涉及数据。
|
||
|
||
### 2. `knowledge-adapter-service` 的工作流不在 `main` 上
|
||
|
||
- **现状**:`main` 的 `.gitea/workflows/` **不存在**;`build.yml` 只在 `ci/setup` 分支(`GET .../contents/.gitea/workflows?ref=ci/setup` → 200,`ref=main` → 404)。仓库已有 `runner-weknora-ka-01`。
|
||
- **要做什么**:把 `.gitea/workflows/build.yml` + `.gitea/scripts/{ci_gate.py,ci_report.py}` 合到 `main`;关掉/删掉 `ci/setup` 分支。
|
||
- **为什么**:现在推 `main` **不触发任何校验**——这个仓库的 `main` 处于"裸奔"状态。
|
||
- **怎么验证**:`GET /repos/Weknora/knowledge-adapter-service/contents/.gitea/workflows` 在默认分支返回 `build.yml`;推一个提交,`actions/tasks` 出现新 run。
|
||
- **谁来做**:开发(走正常 PR);合并前用 `attach_repo.sh` 的模板拷贝逻辑。
|
||
|
||
### 3. 生产发布的"人工确认"落地方式二选一(需在实例上实测)
|
||
|
||
- **现状**:Gitea **没有** GitLab 的 `when: manual` + `manual_confirmation`;生产部署目前**完全不经过 CI**(DobotAI 是人工在生产机 clone + build)。
|
||
- **要做什么**:
|
||
- 方案 A:确认 Gitea 1.26.2 的 Actions 是否支持 `environment:` 及其审批;支持就在生产 workflow 上用。
|
||
- 方案 B(不依赖平台):生产 workflow 只 `on.workflow_dispatch`,必填 `sha` + `confirm=deploy-production`,最后一步"切镜像"由本人在生产机执行。
|
||
- **为什么**:规范 §5.2 的三层确认里,第二层(参数)与第三层(人)已可落地;第一层要不要平台能力必须先实测,**不能假设**。
|
||
- **怎么验证**:在**非生产**仓库建一个 `environment: test-protect` 的最小 workflow 试跑;或直接采用方案 B 并留一条演练记录。
|
||
- **谁来做**:本人确认 + 开发实现。
|
||
|
||
### 4. "同一份构建产物"的产物落地方式(本环境当前**不满足**)
|
||
|
||
- **现状**:DobotAI 的做法是**在目标机上各自 build**(测试机 build 一次、生产机再 clone 源码 build 一次)——**两份二进制并不逐字节相同**,违反 §5.1。
|
||
- **要做什么**:
|
||
1. 构建移进 CI(仓库 Runner 上 `docker build`)或至少**只在一台机器 build 一次**;
|
||
2. `docker save` 出 `dist/<repo>-<sha12>.tar` + 写 `release-<sha12>.json`(含 `image_id` / `tar_sha256`);
|
||
3. 产物放到一个**两个环境都取得到**的托管点(见第 5 项);
|
||
4. 测试与生产都 `docker load` 同一份 tar,并各自断言 `image_id` 相同。
|
||
- **为什么**:这是本次规范最核心的新增要求。"测试验收过"必须等于"生产跑的就是那份字节",否则验收结论对生产**无效**。
|
||
- **怎么验证**:测试机与生产机各跑 `docker image inspect --format '{{.Id}}'`,两个值**相同**;且都 == 清单 `image_id`。
|
||
- **谁来做**:开发(改造构建 + 部署脚本);本人验收。
|
||
|
||
---
|
||
|
||
## P1
|
||
|
||
### 5. 构建产物的托管点
|
||
|
||
- **现状**:`ci-bridge` 的 `/api/ci/publish` 是给**静态网页预览**(tar.gz 解包 + URL)用的,不适合放镜像 tar / 大文件;`/srv/aiball/ci/previews/` 下面只有 3 个目录。DobotAI 的 tar 目前不在任何统一位置。
|
||
- **要做什么**:定一个产物目录(建议 `/srv/aiball/ci/artifacts/<ns>/<repo>/<sha12>/`,与 bridge 复用同机同 token,按 sha 分目录 + 保留 N 份),或走对象存储/OSS。
|
||
- **为什么**:§5.1 要求"生产取同一个 tar",就必须有一个**两个环境都能取到、且可按 sha 寻址**的地方。
|
||
- **怎么验证**:从测试机和生产机各 `curl` 一次同一个 `tar_sha256` 地址,都能下到且 `sha256sum` 与清单一致。
|
||
- **谁来做**:本人定位置 + 开发接。
|
||
|
||
### 6. 生产/测试的部署凭据尚不存在
|
||
|
||
- **现状**:只有 3 个 Weknora 仓库配了 `CI_BRIDGE_URL`(variable) / `CI_BRIDGE_TOKEN`(secret),**没有任何部署凭据**(`GET /repos/{r}/actions/secrets`)。DobotAI 的部署靠本人在生产机手动执行。
|
||
- **要做什么**:按命名后缀建变量/密钥(Gitea 无 environment scope,见规范 §7.1):
|
||
- Variables:`DEPLOY_TEST_HOST` `DEPLOY_TEST_PORT` `DEPLOY_TEST_USER` `DEPLOY_PROD_HOST` `DEPLOY_PROD_PORT` `DEPLOY_PROD_USER` `ARTIFACT_BASE_URL`
|
||
- Secrets:`DEPLOY_TEST_SSH_KEY` `DEPLOY_PROD_SSH_KEY` `ARTIFACT_TOKEN`
|
||
- **为什么**:CI 要有能力"传产物"到目标机;同时 Gitea 无 File 类型 secret,私钥内容整体存 secret、由脚本落盘 0600。
|
||
- **怎么验证**:`GET /repos/{r}/actions/variables` 与 `/actions/secrets` 列出全部名字(值不显示);在一个 dry-run workflow 里只在**变量名 + ✓/✗** 层面校验(绝不回显值)。
|
||
- **谁来做**:本人在网页/用 `attach_repo.sh` 的接口写入;凭据环节**必须**由本人操作。
|
||
|
||
### 7. `Weknora/Enterprise-Knowledge-Base` 接入(含分支收敛)
|
||
|
||
- **现状**:7 条分支(`main` + `release/graph-guard-v0.7.1-r1`、`release/server-running-v0.7.1`、`develop/enterprise-kb`、`chore/db-pool-tuning`、`feature/dingtalk-richtext-image`、`feature/dingtalk-image-only`);**无 workflow、无 Runner**;语言 Go+Vue。
|
||
- **要做什么**:分支收敛(该合的合、该删的删)→ 跑规范 §8 的 10 步接入清单。
|
||
- **为什么**:长期分支 + `release/*` 正是规范 §1.1 的反模式;且它没有任何校验。
|
||
- **怎么验证**:`GET /repos/{r}/branches` 只剩 `main` + 短命分支;`actions/tasks` 有新 run。
|
||
- **谁来做**:开发 + 本人确认分支删除范围(删分支不可逆)。
|
||
|
||
### 8. Runner 覆盖盘点
|
||
|
||
- **现状**:Weknora 三仓**各一个**仓库级 Runner(kg/dp/ka);`aiball` 组织级 1 个(`runner-software-01`,覆盖 `protocol-docs` 与 `software-pc`);`Weknora` 组织级 **0 个**。
|
||
- **要做什么**:每个新接入仓库都要有**归属该仓库**的 Runner(否则 run 永远 `queued`)。用 `deploy_repo_runner.sh` 起。
|
||
- **为什么**:规范 §4.2 —— "run 一直 queued" 的头号原因是仓库没有自己的 Runner,而不是工作流写错。
|
||
- **怎么验证**:`GET /repos/{r}/actions/runners` 的 `runners` 非空且 `status=online`。
|
||
- **谁来做**:开发(`bash /srv/aiball/runner/deploy_repo_runner.sh <owner/repo> <name>`)。
|
||
|
||
### 9. `aiball/software-pc` 的 runner 依赖第三方 action
|
||
|
||
- **现状**:`validate.yml` 用 `actions/checkout@v4` + `actions/setup-node@v4`,在 `runner-software-01` 上 run#1 = success(**该 runner 能取 action**);但 Weknora 三仓 runner 上刻意不用。
|
||
- **要做什么**:在 `validate.yml` 顶部加注释说明"本 runner 支持取 action";并补上 `npm ci`(现在用 `npm install`,不可重现)。
|
||
- **为什么**:规范 §4.3 要求"按 Runner 配置区分"且要写明理由,否则下一个人会照抄到不支持 `uses:` 的 runner 上。
|
||
- **怎么验证**:把 `npm install` 改成 `npm ci` 后重跑 run,仍 green。
|
||
- **谁来做**:开发。
|
||
|
||
### 10. 生产迁移与回滚脚本的"幂等门"复核
|
||
|
||
- **现状**:DobotAI 已有 `ops/` 下的 `deploy_dobotai_prod.sh` / `rollback_dobotai_prod.sh` / `prod_verify.sh` / `prod_last_turn.sh`(在生产机 `/opt/dobotai/container/ops/`)。
|
||
- **要做什么**:对照规范 §5.8 / §5.5 逐条核对:产物 sha 校验、迁移列 COUNT 门、agent 配置 hash CAS、`flock` 互斥、0600 备份。
|
||
- **为什么**:规范要求"部分失败后重跑不会双重应用",这是**脚本级**保证,必须在脚本里看到。
|
||
- **怎么验证**:每个门都**故意触发**一次(喂一个已存在的列 / 错的 sha),确认脚本**拒绝执行**而不是静默继续。
|
||
- **谁来做**:开发(只读复核 + 演练);演练在测试机做。
|
||
|
||
---
|
||
|
||
## P2
|
||
|
||
### 11. `aiball/upper-tool`、`zheromiku/protocol-docs` 是空仓
|
||
|
||
- **现状**:两个仓库 `empty=true`。
|
||
- **要做什么**:要么初始化(README + `.gitignore` + 门禁骨架),要么归档。
|
||
- **为什么**:空仓出现在仓库列表里,会让人"以为这里该有东西"。
|
||
- **怎么验证**:`GET /repos/{r}` 的 `empty=false`,或仓库已归档。
|
||
- **谁来做**:本人决定去留。
|
||
|
||
### 12. `docs/提交规范.md` 缺失
|
||
|
||
- **现状**:`~/.githooks/commit-msg` 与 `.gitea/scripts/ci_gate.py` 的提示文案都写着"详见 `docs/提交规范.md`",但仓库里**没有这个文件**。
|
||
- **要做什么**:把规范 §2 的内容落成各仓的 `docs/提交规范.md`(或把提示文案改成指向本规范)。
|
||
- **为什么**:一条指不到地方的指路,比不指路更费时间(原稿 §2.2 的原话)。
|
||
- **怎么验证**:`test -f docs/提交规范.md` 通过;或 grep 提示文案确认已改为可达路径。
|
||
- **谁来做**:开发(顺手改)。
|
||
|
||
### 13. 规范自身的仓库化(已完成,只剩"各仓加指针")
|
||
|
||
- **现状**:正本已入仓 —— `zheromiku/eng-standards-main`,默认分支 `main`,2 条提交,HEAD `419396f3ce0c`;本地 `~/eng-standards/` 的 `git rev-parse HEAD` 与远端 `ls-remote` 一致。
|
||
⚠️ 仓名带了 `-main` 后缀(原计划写的是 `eng-standards`);文档内 4 处引用已按**实际仓名**改正,不留指不到的指针。
|
||
- **要做什么**:~~①建仓~~ ✅ ~~②push~~ ✅;③ 各仓 `AGENTS.md` 加一行指针:`Weknora/{dobotai-platform, knowledge-governance, knowledge-adapter-service, Enterprise-Knowledge-Base}`、`aiball/{software-pc, protocol-docs}`。
|
||
- **为什么**:规范要"不用每次重复说一遍",靠的是可被引用的单一来源(原稿 §11)。先前放在 `/srv/aiball/ci/standards/` 下是分类错误 —— 跨仓规范不该挂在单个项目(AI球)的目录里。
|
||
- **怎么验证**:`git ls-remote --heads origin main` 的 SHA == 本地 `git rev-parse HEAD`;各仓 `AGENTS.md` 里的指针路径可达。
|
||
- **谁来做**:③ 需要**改动 6 个仓库**,属独立动作 —— 等指示,不自行扩围。
|
||
|
||
### 14. `aiball` 固件(ESP32-P4)的流水线尚未定义
|
||
|
||
- **现状**:`/srv/aiball/firmware` 有固件工程,但 Gitea 上**没有对应仓库**;`aiball` 组织下只有 `protocol-docs` / `software-pc` / `upper-tool`。
|
||
- **要做什么**:固件入仓后,按同一套 §5.1 建固件流水线:`idf.py build` 一次 → 记录 `.bin` 的 sha256 → 测试机烧录测试版 → **量产/发布烧同一份 `.bin`**。
|
||
- **为什么**:固件同样适用"同一份产物"铁律;烧录"只写不回读",所以**产物哈希是唯一可信的同一性证据**(AIxProbe 经验)。
|
||
- **怎么验证**:`sha256sum` 两次产物文件一致;烧录日志里的字节数与 `OpenOCD wrote` 一致。
|
||
- **谁来做**:本人定仓库归属 + 开发建流水线。
|
||
|
||
### 15. `ci-bridge` 的公开地址与实际可达性核对
|
||
|
||
- **现状**:`config.json` 的 `public_base=http://192.168.50.134:8899`、`public_base_alt=http://100.92.49.78:8899`;本次实测 `127.0.0.1:8899/healthz` 正常(`reports:19, previews:7, notify:true`)。
|
||
- **要做什么**:核对 `192.168.50.134` 是否仍是本机当前 LAN 地址(网段变化会让所有通知里的链接失效)。
|
||
- **为什么**:报告里给的每个 URL 都必须能 200,否则通知等于没发。
|
||
- **怎么验证**:`curl -m 5 http://192.168.50.134:8899/healthz` 与 `curl -m 5 http://100.92.49.78:8899/healthz` 都返回 `ok:true`。
|
||
- **谁来做**:本人/开发。
|
||
|
||
### 16. 规范守门脚本的 Gitea 版(可选)
|
||
|
||
- **现状**:附件里的 `spec-check.mjs` 是 GitLab 口径(判据含 `glab` 占位符、`.gitlab-ci.yml`、`workflow.rules`),直接拿来自Gitea 环境跑会**假红**。
|
||
- **要做什么**:改写判据:`.gitlab-ci.yml` → `.gitea/workflows/*.yml`;`workflow.rules` → `on:` 三类入口;`glab-placeholder` → `giteactl/gitea_api.py` 等价约束;`resource_group` → `flock`。保留 `--self-test` 的反向自检。
|
||
- **为什么**:规范的"可执行"部分最好变成退出码(原稿 §11.2),但不改写就会假红,而假红和假绿一样要修。
|
||
- **怎么验证**:`--self-test` 造两个夹具(合规全绿、违规每条都红)。
|
||
- **谁来做**:开发(本次未做,见任务边界)。
|
||
|
||
---
|
||
|
||
## 不建议做的事(写下来防止被"顺手加上")
|
||
|
||
- ❌ 不要为了能 push 去改 Gitea 凭据/token scope —— 权限没配好要**问人**,自己换 remote/换账号会把"权限没配好"变成"动作做了一半"。
|
||
- ❌ 不要把测试环境部署塞回 `build.yml`(CI 流水线只管校验与编译);生产 workflow 就是生产 workflow。
|
||
占位作业在填完真实逻辑之前**必须红**,不许"打印 TODO 然后返回成功"。
|
||
- ❌ 不要给生产 workflow 设 `concurrency.cancel-in-progress: true`(会取消正在进行的部署,而取消不是回滚)。
|
||
- ❌ 不要在生产与测试**同时**跑压测(两服共用同一套 RDS,会扰动生产)。
|
||
- ❌ 不要在源码路径里用 `dist` / `data` / `secrets` 这些名字(`.gitignore` 会静默吞掉)。 |