fix(ci): run 块按点源语义加固——原生 stderr 变终止性错误曾致两 job 3 秒亡
run 44(本分支上一次推送)把上一版原生检出打回原形:L0 用了 3 s、L0.5 用了
2 s 双双失败,日志里是 error: No such remote 'origin' 被包成 NativeCommandError
后整步终止。根因在我上一版:runner 执行 run: 块的方式是 powershell -command
点源那个文件,会话继承的 $ErrorActionPreference 是 Stop,于是原生程序往 stderr
写的任意一行都会被 PS 5.1 包成终止性错误。我写的 git remote get-url origin
2>$null 正是这一类,而 2>$null 不算摊平,反而让它先把整步炸掉。
修法两件事一起做:块首显式 $ErrorActionPreference = Continue(不依赖继承);
所有 git 调用走同一个漏斗 Invoke-DtuGit,把 stderr 摊平成字符串再决定是否打印。
探针顺手换成 git config --get remote.origin.url:远端不存在时它只返回非零码、
不往 stderr 写,从源头不再触发这类错误。
更阴的一条教训是我的测法本身。第一版复现器用 -File 包一层点源,结果四条失败
路径全测成 rc=0。用最小矩阵把语义钉死后:exit 1 写在被点源的文件里时,-File
直跑 = 1;-File 包一层点源 = 0 且继续执行后续语句;-Command 点源(runner 的真
实用法)= 1。也就是说只要我一直用 -File 测,检出失败也会一路伪装成绿,这个洞
比上面那个 bug 更坏。现在统一用 runner 的真实语义测:powershell -NoProfile
-Command 点源块体文件,且前置 $ErrorActionPreference = Stop。
换测法后的实测(全部跑在从 ci.yml 抽出的那份字节上,不是另抄的副本):
- 点源 + Stop、全新工作区:ExitCode=0、checkout ok: c1e7e8c / commits=669、
dirty_files=0、150.9 s(修复前同一模式就是 run 44 的 3 秒亡);
- DTU_REPO_SHA 空 / DTU_REPO_URL 空 / sha 不在远端 / 坏令牌:ExitCode 均 1,
坏令牌 0.5 s 返回 unable to get password,不挂起、不烧 job 超时;
- 复用工作区:1.6 s,dirty_files=0,被忽略文件保留,未跟踪垃圾清除;
- 结构面:13 步、两 job 第 1 步逐字一致、uses: 计数 0、run 块非 ASCII 计数 0、
无 BOM 无 CR;check yaml Passed;check_doc_links --all 180 篇、无法判定 0。
文档同笔落地(教训要跟它救的那段代码一起进历史):指南 §5.3 补 run 44 实录与
退出码矩阵、实测表补 G/H 两行、§7 补 job 几秒就亡一行、两份变更记录各加一行;
remote-ci-ops skill §10 补 run: 块的正确测法。另记一个运维事实:推到已存在
的远端分支会正常建 run(run 44 即如此,推送后约 4 分钟入库,我先前把轮询窗口
取得太短误判成没建),以后验 workflow 不再需要手动 dispatch 与服务凭据。
下一轮可能红的两处我先标出来,红了正是我们要的证据:SYSTEM 下的 ui-golden
(历史上败在 32 位 MSBuild 与 VCTargetsPath)与 test-coverage(缺
DTU_MS_COVERAGE,走自动发现)。
This commit is contained in:
@@ -207,6 +207,16 @@ gitlint 专属:消息文件必须写在**仓库内**(跨盘符被 pre-commit
|
||||
$b=[System.IO.File]::ReadAllBytes($p); @($b|?{$_ -gt 127}).Count # 必须 0
|
||||
$e=$null; [System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path $p),[ref]$null,[ref]$e)|Out-Null; @($e).Count # 必须 0
|
||||
|
||||
# run: 块:必须按 runner 的语义测——点源(10-27 用 run 44 换来的两条教训)
|
||||
# runner 执行方式: powershell -command . '<块体>' ← 只有这个是真语义
|
||||
$tmp = '.gitea/_blk_probe.ps1' # 用 python 从 ci.yml 抽出某步 run 正文写到这里,别另抄一份
|
||||
& powershell.exe -NoProfile -Command "`$ErrorActionPreference='Stop'; . (Resolve-Path $tmp)"
|
||||
# 教训一:块被点源进会话,$ErrorActionPreference 继承为 Stop 时,原生程序往 stderr
|
||||
# 写一行就变成**终止性** NativeCommandError,`2>` 重定向挡不住(`2>` 加 `$null` 也不行)。
|
||||
# 所以块首显式 `$ErrorActionPreference='Continue'`,原生调用一律摊平成字符串。
|
||||
# 教训二:`exit 1` 的退出码语义随调用方式变——`-File` 直跑=1;`-File` 包一层点源=**0 且继续执行**;
|
||||
# `-Command` 点源=1。用 `-File` 测会把失败全测成 rc=0(我第一版就栽在这,四条失败路径全绿)。
|
||||
|
||||
# .yml:可解析 + 全部 run: 块纯 ASCII + 无 BOM + LF
|
||||
& '.venv\Scripts\python.exe' -c "import yaml;d=yaml.safe_load(open(r'.gitea/workflows/ci.yml',encoding='utf-8'));print(list(d))"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user