docs(CI): 修 run 46 暴露的 doc-links 违规,并更正「CI 工作区跨 run 复用」错话
CI / L0 静态门禁 (pre-commit) (push) Successful in 5m8s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 2m15s

run 46(你推的 dc5d6a0):L0.5 = Success,40 runner、3188/3188 断言、fail=0;
L0 = 47 Passed / 1 Failed / 2 Skipped —— A 方案确实生效:`ui-golden` 在 CI 里第一次
真编模拟器、真比像素,菜单 8 状态 + 内容页 40 页全过转绿(SYSTEM 命中机器级
`DTU_SDL2_DIR`)。你补跑的 -SetEnv 顺带把 `DTU_MS_COVERAGE` 也钉上了,两个变量成对。

剩下那 1 根红是我自己造的:新加的症状行里写了 gitignored 的构建产物路径,本机
存在、干净检出不存在,于是 `doc-links`「本地过、CI 挂」——正是本文 §4.1.2 记的那
一坑,我一边写它一边踩了它。修法按工具给的提示走(不把不入库的运行时路径当
引用写)。验证没有用本地:在一份**从未构建过模拟器**的干净克隆里先复现(1 处
问题、同一行),再验证修完(0 问题、RC=0),那才是 CI 的处境。

撤回两句错话:我先前写「毒缓存会跨 run 存活」「`-ffd` 是因为 runner 工作区跨运行
复用被忽略文件」——对 CI 都不成立。实测 run 44 / 45 / 46 的 L0 工作区目录哈希互不
相同,**每个 job 一个全新目录**,各付 137~161 s 全量拉取(612 s 的 run 里约 5.4 分钟
是两次拉取)。自愈检查仍然必要,但真正的暴露面是**同一个 job 内**(`ui-golden` 与
板端导航自检共用同一份构建目录,前者中断会毒到后者)以及本机日常开发。§4.5、
§5.3 的 `-ffd` 依据、§7 行与 `ci.yml` 注释四处同步改成实测口径;变更记录按规矩不动
历史行,只在上方加更正行。

自查:两个 job 的检出正文仍逐字一致(7147 字符)、run 块非 ASCII 计数 0、`uses:` 0;
本地暂存钩子 HOOKS_RC=0;干净克隆里 `doc-links` 0 问题、`check_ids` 不可判定 1166 =
上限(未增)。预期这一笔推上去 L0 归零失败——那是自 run 23(10-12)以来第一次
两个 job 全绿。
This commit is contained in:
2026-10-27 17:52:53 +08:00
parent dc5d6a0680
commit 529c58da39
4 changed files with 25 additions and 12 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ whenToUse: CI 没跑、run 被取消或零日志、页面报的失败时长/红
| Actions 页空白、无 run | 看改了啥 + 怎么推的 | 四因:①服务端开关未开 ②workflow 没推到远程 ③**纯文档**(`paths-ignore: docs/**`、`**/*.md`)④**新建分支的首次 push**——`before` 是全零 SHA,变更文件集算不出来被 `paths-ignore` 滤空。④ 的实测:建分支那次 push 无 run,紧接着一次普通 push 立刻出 task;绕法 `workflow_dispatch` 或再推一个非文档提交 |
| **页面报的时长/红数与本地或日志对不上** | §4.3 查 `action_run`/`action_run_job` 的 created/started/stopped | **页面时长不可照抄**。本轮实测页面写 `Failing after 6m49s`,库里 41 次 run **最长 ≈4m33s**,run 41 总时长 95 s(L0 45 s / L0.5 43 s)——**没有任何一条记录对得上 6m49s**(多半掺了排队/重试/页面自身口径)。以库里的 `total=stopped-created`、`run=stopped-started`、`queue=started-created` 三个数为准 |
| run 全 **cancelled**、零日志 | `& '.\scripts\ci_runner_bootstrap.ps1' -Status` | runner 掉线;且 `ci.yml` 的 `concurrency.cancel-in-progress: true` 会把排队 run 被下次 push 取消 → **症状是"任务消失"而不是"任务失败"**(历史上 16–21 连续 12 个 job 零日志即此) |
| `ui-golden` 红、日志是 `C1083: SDL2/SDL.h` 或 `MSB1009: 项目文件不存在`,本地全绿 | `git ls-files` 在 `simulator/SDL2*` 下命中 0(SDK 不入库);或 `simulator/build/CMakeCache.txt` 在但没有 `ALL_BUILD.vcxproj` | 属 **B 类缺环境**:设机器级 `DTU_SDL2_DIR`(指南 §4.5);毒缓存已由 `build_sim.ps1` 自愈,也可手删 `simulator/build` |
| `ui-golden` 红、日志是 `C1083: SDL2/SDL.h` 或 `MSB1009: 项目文件不存在`,本地全绿 | 前者 = 检出里根本没有 SDL2 SDK(`.gitignore` 排除它,`git ls-files` 在该 SDK 目录下命中 0 个文件);后者 = 上一轮配置在硬校验处中断,**CMake 缓存文件已写下、工程文件却没生成**,于是下一轮跳过配置 | 设机器级 `DTU_SDL2_DIR`(指南 §4.5);模拟器构建脚本已能自愈,也可手删那份构建目录。**别把构建产物路径当文档引用写**——它不入库,CI 的干净检出里不存在,`doc-links` 会「本地过、CI 挂」(指南 §4.1.2 同族) |
| runner 显示 **online** 却每 10 秒重启、日志暴涨(实测 ~20 MB/天) | daemon 日志出现 `another gitea-runner process is already using ".runner"` | **双看门狗抢锁**:`Unregister-ScheduledTask` **不会**停掉旧实例起的进程 → 孤儿看门狗养着旧 daemon → 它持 `.runner.lock` → 新任务里的 daemon 起不来,而**服务端仍显示 online**(旧 daemon 在服务)。修:管理员 `-StartNow`(它**先杀看门狗、再杀 daemon**,顺序反了会被 10 秒内复活) |
| L0 失败但**本地同一条命令全绿**,日志 `exit code: 254` + `Missing git configuration: please set user.name` | 看是不是 254 | **不是提交信息问题**:`actions/checkout` 把 HOME 指向每次任务的临时目录,SYSTEM 无全局 git 身份 → gitlint 在读规则**之前**就配置错误退出。已由 `scripts/ci_gitlint_range.ps1` 用 `GIT_CONFIG_*` 注入一次性身份修掉;**254 = 门禁没跑起来(exit 2),1 = 信息真违规(exit 1)**,别把两者混成一句 |
| 钩子条数对不上 | `grep -c 'id:' .pre-commit-config.yaml` | **报告数 = 定义数 − 1**(gitlint 属 `commit-msg` stage,`--all-files` 跑不到且表现为全绿 = 静默空转)。增删钩子后重算这个差值 |
+10 -4
View File
@@ -236,8 +236,11 @@ jobs:
if ($c.Code -ne 0) { $c.Lines | ForEach-Object { Write-Host " $_" }; Write-Host '::error::detached checkout failed'; exit 1 }
$rr = Invoke-DtuGit -G @('reset', '--hard', '-q', $env:DTU_REPO_SHA)
if ($rr.Code -ne 0) { Write-Host '::error::reset --hard failed'; exit 1 }
# -ffd, deliberately not -ffdx: -x would delete IGNORED files, and the runner
# reuses those across runs (pip / pre-commit caches live in the workspace).
# -ffd, deliberately not -ffdx: -x would delete IGNORED files. Within ONE job several
# hooks share this directory (pip / the simulator build tree), and local reruns reuse
# it. NOTE measured 2026-10-27: CI gives every job a FRESH workspace (the L0 dirs of
# run 44/45/46 all differ, each paying a full 137-161 s fetch), so -ffd is a safe
# default, not a speed trick.
$cl = Invoke-DtuGit -G @('clean', '-ffd', '-q')
if ($cl.Code -ne 0) { $cl.Lines | ForEach-Object { Write-Host " $_" }; Write-Host '::error::git clean failed'; exit 1 }
$head = (Invoke-DtuGit -G @('rev-parse', '--short', 'HEAD')).Lines -join ''
@@ -624,8 +627,11 @@ jobs:
if ($c.Code -ne 0) { $c.Lines | ForEach-Object { Write-Host " $_" }; Write-Host '::error::detached checkout failed'; exit 1 }
$rr = Invoke-DtuGit -G @('reset', '--hard', '-q', $env:DTU_REPO_SHA)
if ($rr.Code -ne 0) { Write-Host '::error::reset --hard failed'; exit 1 }
# -ffd, deliberately not -ffdx: -x would delete IGNORED files, and the runner
# reuses those across runs (pip / pre-commit caches live in the workspace).
# -ffd, deliberately not -ffdx: -x would delete IGNORED files. Within ONE job several
# hooks share this directory (pip / the simulator build tree), and local reruns reuse
# it. NOTE measured 2026-10-27: CI gives every job a FRESH workspace (the L0 dirs of
# run 44/45/46 all differ, each paying a full 137-161 s fetch), so -ffd is a safe
# default, not a speed trick.
$cl = Invoke-DtuGit -G @('clean', '-ffd', '-q')
if ($cl.Code -ne 0) { $cl.Lines | ForEach-Object { Write-Host " $_" }; Write-Host '::error::git clean failed'; exit 1 }
$head = (Invoke-DtuGit -G @('rev-parse', '--short', 'HEAD')).Lines -join ''
+1
View File
@@ -85,6 +85,7 @@
## 变更记录
| 日期 | 变更 |
| 2026-10-27 | run 46:`ui-golden` 转绿(`DTU_SDL2_DIR` 生效)。新的 1 根红是我自己写的 `doc-links` 违规(把 gitignored 构建产物当引用),§4.1.2 同族,已修;并更正「CI 工作区跨 run 复用」的错话——实测每 job 全新目录、每次 137~161 s 全量拉取,毒缓存只在同一 job 内与本机流传(指南 §4.5/§5.3/§7 与 `ci.yml` 注释同步) |
|---|---|
| 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 已内置」说法 |
+13 -7
View File
@@ -1002,11 +1002,16 @@ error C1083: 无法打开包括文件: "SDL2/SDL.h"
同理也别把变量指回某人的开发检出——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` → 删除重建。
时,CMake **已经把缓存文件写下**、工程文件却没生成;`build_sim.ps1` 的判断是「有缓存就不再配置」,
于是下一轮**跳过配置**直接进 MSBuild,报 `MSB1009: 项目文件不存在`——离根因十万八千里。
⚠ **更正(我自己写错的句子)**:这里原本写「这份毒缓存会**跨 run 存活**」,**对 CI 是错的**。实测 CI
每个 job 都用一个**全新**工作区——run 44 / 45 / 46 的 L0 目录哈希分别是 `b4a9…`、`e3ad…`、`74ce…`,
同一个 L0 job 三次都不同,且每次都付 **137~161 s 全量拉取**。所以跨 run 不会残留。真正的暴露面在
**同一个 job 内**:`ui-golden` 与板端导航自检都要编模拟器、共用同一份构建目录,前者中断就会毒到
后者;本机日常开发同理(我就是先在本地那份等价工作区里撞到的)。自愈检查因此仍然必要:
`build_sim.ps1` 第三节原本就有「生成器不符 → 删构建目录重来」的先例,照同一形状补一条——有缓存
但没有工程文件 → 删重。
实测闭环(在一份**没有**仓内 SDK、且带着 run 45 毒缓存的检出里):
@@ -1076,7 +1081,7 @@ set-url origin <server_url>/<repository>.git` → 完整 refspec `+refs/heads/*:
| 选择 | 为什么 |
|---|---|
| `clean -ffd`,**不是** `-ffdx` | `-x` 会删**被忽略**的文件,而 runner 工作区跨运行复用它们(pip / pre-commit 缓存)。实测:放一个 gitignored 的 `ci-artifacts/kept.log` + 一个未跟踪垃圾 + 改一个跟踪文件 → 重跑后 `dirty_files=0`、垃圾被清、**被忽略文件原样保留** |
| `clean -ffd`,**不是** `-ffdx` | `-x` 会删**被忽略**的文件:同一个 job 内多个钩子共用这份工作区(pip、模拟器构建目录等),本机重复跑也靠它。⚠ **更正(2026-10-27 实测):CI 并不跨 run 复用工作区**——run 44/45/46 的 L0 目录哈希 `b4a9…`/`e3ad…`/`74ce…` 各不相同,每个 job 都付一次 137~161 s 全量拉取;所以选 `-ffd` 是**保守**(将来若真复用,被忽略的缓存不会被误删),不是靠它省时间。实测:放一个 gitignored 文件 + 一个未跟踪垃圾 + 改一个跟踪文件 → 重跑后 `dirty_files=0`、垃圾被清、**被忽略文件原样保留** |
| `GIT_TERMINAL_PROMPT=0` + `-c credential.helper=` | 否则一次认证挑战会让 git **等人类输入**,而 runner 没有控制台 → 白占满 30 分钟 job 超时、表现得像“CI 挂了”。实测灌一个坏令牌:`fatal: unable to get password from user` → **rc=1 立即失败**,不挂起 |
| 令牌只走 per-invocation `-c http.extraheader` | 不写进 `.git/config`、不回显。匿名也能拉(仓库公开:`/info/refs?service=git-upload-pack` 实测 200)→ CI 不因此新增“令牌必须可用”的依赖 |
| 不抓 tag | 本仓库 tag 数 = 0,且无任何脚本用 `git describe --tags`(2026-10-27 实测);要用时再加 |
@@ -1258,7 +1263,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` |
| `ui-golden` 红、日志里是 `C1083: SDL2/SDL.h` 或 `MSB1009: 项目文件不存在`,而本地全绿 | 前者 = 检出里根本没有 SDL2 SDK(`.gitignore` 排除、不入库);后者 = **同一个 job 内**前一个钩子配置中断留下的半截构建缓存(CI 不跨 run 残留,见 §4.5 的更正) | 设机器级 `DTU_SDL2_DIR`(§4.5);构建脚本已自愈,也可手删那份构建目录 |
| `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` |
@@ -1550,6 +1555,7 @@ powershell -ExecutionPolicy Bypass -File scripts\ci_runner_bootstrap.ps1 -DryRun
## 变更记录
| 日期 | 变更 |
| 2026-10-27 | ✅ **run 46:`ui-golden` 转绿(A 方案生效,`DTU_SDL2_DIR` 由 SYSTEM 命中机器级 `D:\DTU_SDK`),L0 = 47 Passed / 1 Failed / 2 Skipped**。那 1 根红是**我自己**:新加的症状行里把 gitignored 的构建产物路径当文档引用写了,本机存在、干净检出不存在 → `doc-links`「本地过、CI 挂」,**正是本文 §4.1.2 记的那一坑**,我一边写它一边踩了它;已在干净克隆(无构建目录)里先复现再修(复现命令与判据同 §4.1.2)。顺带更正我先前两句关于工作区复用的错话:实测 CI **每个 job 一个全新工作区**(run 44/45/46 的 L0 目录哈希 `b4a9…`/`e3ad…`/`74ce…` 互不相同,每次付 137~161 s 全量拉取),所以「毒缓存跨 run 存活」只对**本机与同一 job 内**成立(`ui-golden` 与板端导航自检共用构建目录,前者中断会毒到后者),对跨 run 不成立——§4.5、§5.3 的 `-ffd` 依据、§7 行与 `ci.yml` 注释四处同步改为实测口径(历史行不动,只在上方加本行) |
|---|---|
| 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),而新建分支首推不建(已三次复现) |