fix(ci): ui-golden 需要机器级 SDL2 SDK——补 DTU_SDL2_DIR、配置期护栏与 build 缓存自愈
This commit is contained in:
@@ -87,6 +87,7 @@
|
||||
| 日期 | 变更 |
|
||||
|---|---|
|
||||
| 2026-10-27 | run 44(推送到已存在分支会正常建 run)暴露的教训写进指南 §5.3:run: 块是被**点源**执行的,`$ErrorActionPreference` 继承 Stop 时原生 stderr 会终止整步;且测 run: 块只能用 `-Command ". 文件"`(`-File` 包点源会把失败测成 rc=0)。§7 补「几秒就亡」一行,skill §10 补测法 |
|
||||
| 2026-10-27 | run 45 首次真跑门禁(L0 46 根绿、L0.5 3188/3188);唯一红 `ui-golden` 定性为 **runner 缺环境**:SDL2 SDK 不入库。新增指南 §4.5:机器级 `DTU_SDL2_DIR` + CMake 配置期硬校验 + `Find-Sdl2Sdk` + `build_sim.ps1` 毒缓存自愈;§4.1.3 变量表补到 5 个、§5.5 与 §7 各补一处;顺带更正 lvgl-simulator skill 的「SDL2 已内置」说法 |
|
||||
| 2026-10-27 | 指南 §5.3 **整节重写并落地**:workflow 两个 job 的 `uses:` 归零(原生 git 全量检出,六项实测 A/B/C/D/E/F + 两条自查命令见 §5.3);§1.2.1 第三行按 1.25.4 实际行为改正(自定义 `DEFAULT_ACTIONS_URL` 已无效,旧写法会把人引向一个不存在的开关);§7 的 checkout 行改为“看见这症状=有人把 `uses:` 加回来了”。另:`scripts/ci_runner_bootstrap.ps1` 的 MSVC 探测改为 `vswhere` + 工具集钉世代(默认 14.51,与覆盖率基线同版本),`-SetEnv` 开始成对写 `DTU_MS_COVERAGE` |
|
||||
| 2026-10-27 | 新增指南 §4.4「覆盖率工具链(mscoverage)与 VS2026 BuildTools」并加进上面的目录表。当天另修掉 `cppcheck` 两根真红(`ci/remote-ci` 的 `5869c03`)——此前 L0 的 28 次红里混着**三类**:runner 缺覆盖率组件、外网拉 `actions/checkout` 抖动、真代码问题。**别再一律当成环境噪声**,按 §7 逐条定性 |
|
||||
| 2026-10-12 | 🐛 **首次真跑出 run**:`L0.5` **成功**(`10 runner(s), 647/647, fail=0`,与本地逐字一致);`L0` **假失败**——gitlint 因 runner 无 git 身份而 `exit 254`(`Missing git configuration: please set user.name`),旧文案把它说成"提交信息违规",且该步 `exit 1` 连带让 26 个钩子全部没跑。已在 `ci_gitlint_range.ps1` 用 `GIT_CONFIG_*` 注入一次性身份(不写文件)并区分 254/1 退出码。另记:**新建分支的首次 push 不触发 run**,需 `workflow_dispatch` 或再推一个非文档提交。详见指南 §7 |
|
||||
|
||||
+55
-2
@@ -832,13 +832,15 @@ mv .dsh/skills/serial-assistant/scripts/state.bak_ci .dsh/skills/serial-assistan
|
||||
#### 4.1.3 机器级 `DTU_*` 环境变量(runner 的正式覆盖通道,2026-10-02 起)
|
||||
|
||||
workflow 已改为统一消费 `DTU_*` 接口(见 [本地工具路径环境变量方案.md §3.3](../环境与部署/本地工具路径环境变量方案.md)):
|
||||
**显式变量优先 → 自动发现回退**,三个 job 步骤相关的变量:
|
||||
**显式变量优先 → 自动发现回退**,与 job 步骤相关的变量(2026-10-27 实测 `-Status` 列 5 个):
|
||||
|
||||
| 变量 | 作用 | 未设置时的回退 |
|
||||
|---|---|---|
|
||||
| `DTU_PRECOMMIT_PYTHON` | 指向装有 pre-commit 的 python.exe(L0/L0.5 用) | PATH 的 `python` → 工作区 `.venv`(干净克隆里通常没有) |
|
||||
| `DTU_CPPCHECK` | 指向 cppcheck.exe(L0 钩子用) | SYSTEM 的 PATH(用户级 PATH 不可见) |
|
||||
| `DTU_MSVC_CL` | 指向 x64 `cl.exe`(L0.5 用) | `%ProgramFiles%`/`%ProgramFiles(x86)%` 推导的 VS 标准根自动探测 |
|
||||
| `DTU_MS_COVERAGE` | 指向 `Microsoft.CodeCoverage.Console.exe`(`test-coverage` 钩子用) | 顺 `DTU_MSVC_CL` 所在的那套 VS 根自动发现(§4.4) |
|
||||
| `DTU_SDL2_DIR` | 指向一份 SDL2 SDK 根(须含 `include\SDL2\SDL.h`;`ui-golden` 要编模拟器) | `simulator\SDL2\SDL2-*`——**干净检出里根本没有这份 SDK,CI 必红**(§4.5) |
|
||||
|
||||
设置(**必须管理员**;scope 用 `Machine` 才能被 SYSTEM 任务看到):
|
||||
|
||||
@@ -966,6 +968,55 @@ MSVC 114 行),**换编译器世代 = 换分母**;指错版本只会把「E
|
||||
安装,非提权读不到该账户 HKCU,**未证**)。→ 「CI runner 与本机同一台」这句要按**量基线那台可能是另一台
|
||||
机器**来理解;换机或换账户一律先 `check_test_coverage.py --list` 再跑全量。
|
||||
|
||||
### 4.5 UI 像素回归的 SDL2 SDK:CI 工作区**天然没有**(2026-10-27 run 45 实测)
|
||||
|
||||
`ui-golden` 要先把 LVGL 模拟器编出来,而模拟器依赖 **SDL2 SDK**。这份 SDK 是**下载来的第三方件**:
|
||||
`.gitignore` 里明写 `simulator/SDL2/`,`git ls-files` 在该路径下命中 **0 个文件**。于是任何一份干净
|
||||
检出里都没有它,而开发机上有——所以本地一直绿,**这个缺失在本地永远照不出来**。
|
||||
|
||||
run 45 第一次在 CI 跑到 `ui-golden` 时报的是:
|
||||
|
||||
```
|
||||
error C1083: 无法打开包括文件: "SDL2/SDL.h"
|
||||
(Lib/lvgl/src/drivers/sdl/lv_sdl_private.h:20)
|
||||
```
|
||||
|
||||
⚠ **别把它读成「UI 像素回归红了」**:这是红因三分法里的**第二类(runner 缺环境)**,与像素、与
|
||||
被检的提交内容都无关。配置阶段那句 `-- SDL2: <路径>` 也**不能**当证据——`simulator/CMakeLists.txt`
|
||||
过去只是 `set()` 拼路径、不校验存在,缺件时照样打印,直到编译 LVGL 的 SDL 驱动才炸。
|
||||
|
||||
**已落地的修法(四件)**:
|
||||
|
||||
1. `simulator/CMakeLists.txt` 支持机器级 **`DTU_SDL2_DIR`** 覆盖 SDK 位置;**不设该变量时行为与
|
||||
过去完全一致**(实测:不设 → 取 `simulator/CMakeLists.txt` 里写死的仓内默认路径 → `ui-golden Passed`)。
|
||||
2. 同文件加**配置期硬校验**:缺 SDK 时一行 `FATAL_ERROR` 讲清三条出路(本机装 / CI 设变量 /
|
||||
删旧 build 缓存),而不是几百行 C1083 冒充代码错误。实测护栏生效:改前那种工作区里
|
||||
`C1083` 行数从一整屏降到 **0**,只剩护栏自己那一条。
|
||||
3. `scripts/ci_runner_bootstrap.ps1` 新增 `Find-Sdl2Sdk`,顺序:已有 `DTU_SDL2_DIR`(Machine →
|
||||
User → Process,逐个校验含 `include\SDL2\SDL.h`)→ 机器级 `D:\DTU_SDK\SDL2-*` → 本仓
|
||||
`simulator/SDL2/SDL2-*`;**命中第 3 档会 WARN**「runner 工作区里不会有这个路径」。`-SetEnv`
|
||||
写入该变量,`-Status` 一并列出。
|
||||
4. **SDK 放机器级而不是仓内**:本机已把那份 26 MB 的 SDK 整目录拷到 `D:\DTU_SDK\` 下(子目录名
|
||||
就是 SDK 自带的版本号目录名)。`Find-Sdl2Sdk` 按 `SDL2-*` 通配发现、**不写死版本**,所以文档
|
||||
里不钉那个目录名(它形如编号,会撞进 `id-check` 校验 8 的噪声桶,而那条上限只许减不许增)。
|
||||
同理也别把变量指回某人的开发检出——CI 的工作区是 runner 自己的目录,不是你这份仓。
|
||||
|
||||
⚠ **第二个坑(毒缓存):设好变量仍然红,红因已经不是 SDK**。上一次配置在 `FATAL_ERROR` 处中断
|
||||
时,CMake **已经把 `CMakeCache.txt` 写下**、工程文件却没生成;`build_sim.ps1` 的判断是「有缓存就
|
||||
不再配置」,于是下一轮**跳过配置**直接进 MSBuild,报 `MSB1009: 项目文件不存在`——离根因十万八千里。
|
||||
更麻烦的是 `simulator/build/` 属被忽略文件,而检出用的是 `git clean -ffd`(**刻意保留**被忽略文件,
|
||||
见 §5.3),**这份毒缓存会跨 run 存活**。已在 `build_sim.ps1` 第三节补一条同形检查(那里原本就有
|
||||
「生成器不符 → 删 build/ 重来」的先例):有缓存但没有 `ALL_BUILD.vcxproj` → 删除重建。
|
||||
|
||||
实测闭环(在一份**没有**仓内 SDK、且带着 run 45 毒缓存的检出里):
|
||||
|
||||
```
|
||||
ws cache present=True ALL_BUILD present=False <- 毒化状态,正是 CI 现在的处境
|
||||
[RECOVERY] rc=0 UI 像素回归(菜单 8 状态 + 内容页 40 页 黄金参考)....Passed
|
||||
```
|
||||
|
||||
即:只需管理员跑一次 `-SetEnv`(与 §4.4 的三条命令同批),CI 的 `ui-golden` 就会转绿,
|
||||
且**自愈** run 45 已经污染的那份工作区。
|
||||
---
|
||||
|
||||
## 5. 仓库端:workflow 文件
|
||||
@@ -1129,7 +1180,7 @@ Select-String -Path '.gitea/workflows/ci.yml' -Pattern '^\s*-?\s*uses:'
|
||||
|
||||
| job | `runs-on` | 步骤要点 |
|
||||
|---|---|---|
|
||||
| `l0-gates` | `windows` | **原生 git 检出**(全量 refspec,不再用 `actions/checkout`;见 §5.3)→ 环境自检检(**Python 探测走 `scripts/ci_find_python.ps1`**、cppcheck 按 `DTU_CPPCHECK` → PATH → 标准安装目录,缺则 `::error::` + exit 1)→ `pre_commit install --install-hooks` → **提交信息门禁 `scripts/ci_gitlint_range.ps1`**(见 §7 排障表"钩子条数对不上"行)→ **决定跳过哪些钩子**(探测 `.map`,写入 `GITHUB_OUTPUT`;无 `.map` 时 `::warning::` 声明体积门禁未跑)→ `pre-commit run --all-files --show-diff-on-failure`(`env: SKIP`,输出 `Tee` 到 `ci-artifacts/l0-pre-commit.log`)→ 打印 `::notice::L0: passed/failed/skipped` 汇总行 → 归档日志说明 |
|
||||
| `l0-gates` | `windows` | **原生 git 检出**(全量 refspec,不再用 `actions/checkout`;见 §5.3)→ 环境自检检(**Python 探测走 `scripts/ci_find_python.ps1`**、cppcheck 按 `DTU_CPPCHECK` → PATH → 标准安装目录,缺则 `::error::` + exit 1)→ `pre_commit install --install-hooks` → **提交信息门禁 `scripts/ci_gitlint_range.ps1`**(见 §7 排障表"钩子条数对不上"行)→ **决定跳过哪些钩子**(探测 `.map`,写入 `GITHUB_OUTPUT`;无 `.map` 时 `::warning::` 声明体积门禁未跑)→ `pre-commit run --all-files --show-diff-on-failure`(`env: SKIP`,输出 `Tee` 到 `ci-artifacts/l0-pre-commit.log`)→ 打印 `::notice::L0: passed/failed/skipped` 汇总行 → 归档日志说明;**`ui-golden` 需要 SDL2 SDK,而该 SDK 不入库** → 依赖机器级 `DTU_SDL2_DIR`(缺件即 FAIL,护栏与落地见 §4.5) |
|
||||
| `l05-host-unit-tests` | `windows` | **原生 git 检出**(与 `l0-gates` 第 1 步逐字一致,内联带来的同步义务,自查见 §5.3 末)→ **探测 MSVC**MSVC**(按 VS_ROOTS 找 `Hostx64\x64\cl.exe`)→ 遍历 `test/host/**/run_unit_test.py` 逐个跑(输出 `Tee` 到 `ci-artifacts/l05-<模块>.log`;解析各模块 `N/M PASSED` 汇总行 → 聚合 `::notice::L0.5: K runner(s), A/B assertions passed`;失败 `::error::` 并置退出码);**未探测到 MSVC 时打印醒目 WARNING 并降级跳过**(不硬失败,避免"没装 VS 的 runner 全红") |
|
||||
|
||||
> 🔴 **两条 Python 探测链必须同序同步**:本地 `scripts/ci_local.py` 与 CI 侧
|
||||
@@ -1207,6 +1258,7 @@ date +%s # 对比 last_online
|
||||
| `l0-gates` 报 `::error::runner 缺少:Python, cppcheck` | runner 没装或不在 PATH | 装完后**重启 runner 服务**(新进程才吃到新 PATH) |
|
||||
| `Prepare all required actions` 或 `checkout` 卡住/超时(~45 s 后整 job 亡、零钩子输出) | 有人把 `uses:` 加回了 workflow —— 该阶段**先于任何步骤**无条件联网,手工 curl 可达不代表 runner 可达 | 本仓库 2026-10-27 起已无 `uses:`(§5.3 有六项实测与自查命令);自查:`Select-String .gitea/workflows/ci.yml -Pattern '^\s*-?\s*uses:'` 应为空 |
|
||||
| job **3~5 秒就亡**、日志里是 `CategoryInfo` + `FullyQualifiedErrorId : NativeCommandError`,而同一条命令在本地全绿 | `run:` 块被**点源**进会话且 `$ErrorActionPreference` 继承为 Stop → 原生程序的 stderr 行变成**终止性**错误(`2>$null` 挡不住) | 块首显式设 `Continue`,原生调用一律摊平(`2>&1` 配 `ForEach-Object` 那类漏斗);复现方法见 §5.3 的 run 44 实录 |
|
||||
| `ui-golden` 红、日志里是 `C1083: SDL2/SDL.h` 或 `MSB1009: 项目文件不存在`,而本地全绿 | 前者 = 检出里根本没有 SDL2 SDK(`.gitignore` 排除、不入库);后者 = 上一轮配置中断留下的半截 `simulator/build` 缓存跨 run 存活 | 设机器级 `DTU_SDL2_DIR`(§4.5);缓存那条已在 `build_sim.ps1` 自愈,也可手删 `simulator/build` |
|
||||
| `l05` 日志出现 `::warning::runner 未安装 MSVC` | VS 装在非默认路径或未装 | 见 §4.2(默认路径 / 同步改两处根目录) |
|
||||
| `mem-numbers` 显示 `Skipped` | 正常(CI 无 Keil,无 `.map`) | 无需处理;但注意 **CI 未守体积门禁**(见 §0.0),改代码后本地 `@build` + `check_mem_numbers.py --scan` 兜底 |
|
||||
| L0.5 显示 `2 runner(s), X/Y ...` 但 X<Y | 有单测用例未通过 | 看该模块的 `::error::unit test failed` 行与其 `ci-artifacts/l05-<模块>.log` |
|
||||
@@ -1499,6 +1551,7 @@ powershell -ExecutionPolicy Bypass -File scripts\ci_runner_bootstrap.ps1 -DryRun
|
||||
|
||||
| 日期 | 变更 |
|
||||
|---|---|
|
||||
| 2026-10-27 | 🟡 **run 45 真把门禁跑起来了**:L0 46 根钩子 Passed / L0.5 = 40 runner 3188/3188 fail=0(`checkout ok: ae80bb8 / commits=670`,SYSTEM 读到机器级 `DTU_MSVC_CL` = E 盘 14.51)。唯一红 = `ui-golden`,定性为**第二类 runner 缺环境**而非像素回归:SDL2 SDK 被 `.gitignore` 排除、不入库,干净检出天然没有(本地有 → 一直绿)。新增 §4.5:`CMakeLists.txt` 支持机器级 `DTU_SDL2_DIR`(不设=行为不变,实测 Passed)+ 配置期硬校验(护栏把一整屏 C1083 降到 0 行)+ `Find-Sdl2Sdk` 三级发现(机器级 `D:\DTU_SDK` 优先,命中仓内路径会 WARN)+ **毒缓存坑**:配置中断留下 `CMakeCache.txt` 却没有工程文件,而 `build_sim.ps1` 是「有缓存就不再配置」→ 下一轮跳过配置、报离根因极远的 `MSB1009`,且 `simulator/build/` 被 `git clean -ffd` 刻意保留 → **跨 run 存活**;已按该文件既有先例补「有缓存无工程 → 删重」。实测闭环:在一份没有仓内 SDK 且带毒缓存的等价工作区里,仅设变量即 `Passed`(8+40 全过、自愈)。§4.1.3 变量表由 3 个补到 5 个;§5.5 的 `l0-gates` 步骤要点补上 `ui-golden` 的 SDK 依赖;skill 侧补症状行、三分法 B 类例、`run.status` 5/6 为非终态;顺带更正 lvgl-simulator skill 中「SDL2 仓库已内置」的说法 |
|
||||
| 2026-10-27 | 🔴 **run 44 真机首验失败一次 → 两条「本地照不出来」的教训写进 §5.3**:把原生检出差上去推到 `ci/remote-ci`(10:38)后两个 job 分别 3 s / 2 s 亡,日志是 `error: No such remote 'origin'` 被包成 `NativeCommandError` 终止整步。教训①:runner 用 `powershell -command . '<文件>'` **点源**执行 run: 块,会话继承 `$ErrorActionPreference=Stop` 时原生程序的 stderr 一行就是**终止性错误**,`2>` 重定向挡不住——修法:块首显式 `Continue` + 所有 git 调用走摊平漏斗(另把 `git remote get-url` 换成 `git config --get`,缺 key 时不写 stderr)。教训②:**测法必须复现点源**——实测 `exit 1` 语义矩阵:`-File` 直跑=1 / `-File` 包点源=**0 且继续执行** / `-Command` 点源=1;我第一版复现器用了中间那种,把四条失败路径全测成 rc=0(假警报,也照不出教训①)。换点源测法后:全新工作区 150 s `checkout ok: c1e7e8c / commits=669`、四条失败路径 ExitCode 全 1、复用工作区 1.6 s 且 gitignored 文件保留。§5.3 实测表补 G/H 两行、§7 补「几秒就亡」一行、`remote-ci-ops` skill §10 补测法。另记:本仓 push 到**已存在**的远端分支会正常建 run(run 44),而新建分支首推不建(已三次复现) |
|
||||
| 2026-10-27 | ✂️ **CI 侧两处根治 + 更正我上一条的一处推断**:① **workflow 去掉 `uses:`**——两个 job 的第 1 步换成原生 git 全量检出(完整 refspec + 分离 HEAD + `reset --hard` + `clean -ffd`、令牌只走 per-invocation `-c http.extraheader`、`GIT_TERMINAL_PROMPT=0` 防挂死、目标 sha 不在历史里就 `::error::` 硬失败而不是默默构建错树)。动因是 run 36/41/42 三次 **`Prepare all required actions` 阶段 ~45 s 外网超时把整个 job 打死、零钩子输出**,而同一分钟手工 `curl` 返回 200。§5.3 整节重写,含六项实测(A/B/C/D/E/F——关键是 E:**把正文从 `ci.yml` 里抽出来跑**,测的就是文件里那份字节)与两条自查命令;§7 的 checkout 行同步改为“看见此症状=有人把 `uses:` 加回来了”。② **`scripts/ci_runner_bootstrap.ps1` 的 `Find-MsvcCl` 重写**:`vswhere -all -products *` 取实例(**能看见非默认盘**)+ 工具集版本降序 + `-MsvcToolset` 前缀**钉住世代**(默认 `14.51.`,与覆盖率基线同版本;钉不上连 WARN 再回落最新,绝不静默)+ 新增 `-MsvcLatest`;`-SetEnv` 增写 `DTU_MS_COVERAGE`(须与 `DTU_MSVC_CL` 成对改)。③ **更正**:先前写“旧探测会把机器级变量覆回 C 盘 14.29”——本机实情是 C 盘 VS2019 已于 **01:00 卸载**(`…\2019` 只剩空目录、C 盘 x64 `cl.exe` 实测 0 个),旧 `-SetEnv` 在本机是**找不到 → 只 Warn → 不写**,于是变量一直指着失效路径(CI 的 L0.5 走显式通道即硬失败,不做静默回退)。实测新逻辑:候选 3 个(14.44/14.51/14.52,全在 E 盘)→ 默认命中 **14.51.36231**,`-Latest` 给 14.52,`-MsvcToolset 99.` 走告警回落。④ §1.2.1 表第三行按 1.25.4 实际行为改正(自定义 `DEFAULT_ACTIONS_URL` 取值已无效)——旧写法会把下一个排障的人引向一个不存在的开关 |
|
||||
| 2026-10-27 | 🧯 **拆穿「L0 恒红 = 环境噪声」这个想当然 + 覆盖率工具链补齐**:① `cppcheck` 恒红**不是**版本漂移——本机与 runner 同机、同 exe(2.21.0)、同参数复现即红,两根 `uninitializedVariable`(`s_cmd_con` 在空信息体分支把未初始化 `body` 传下去、`s_spont_step` 的 `blen` 作用域过宽)是真代码问题,已在 `ci/remote-ci` 的 `5869c03` 修掉(`@build` 0/0,`Code 231712→231732`)。② 新增 §4.4:`Microsoft.CodeCoverage.Console.exe` **只随 VS 分发**(NuGet 两候选包实测 .exe 数为 0 / 只有老版 `CodeCoverage.exe`),本机补装 VS2026 BuildTools 18.11 于 **E 盘**后仍因非默认盘不被看见,须显式机器级 `DTU_MSVC_CL`(指 14.51 = 与 `scripts/test_coverage_baseline.json` 同版本);三条管理员命令、`-Force` 陷阱、`Restart-Service Schedule` 判据一并写入。③ 排障教训:**页面时长与本地对不上时以 `commit_status` + runner 日志为准**——页面那条「L0 Failing after 6m49s」在库里是 run 26 的 409 s(cppcheck 真红),同一 sha 另有一次 5 s 的 checkout 超时,**两者不是一回事**,别拿一个解释另一个 |
|
||||
|
||||
Reference in New Issue
Block a user