diff --git a/.github/workflows/guards.yml b/.github/workflows/guards.yml index 807bf0d..0fbc9b1 100644 --- a/.github/workflows/guards.yml +++ b/.github/workflows/guards.yml @@ -1,5 +1,9 @@ name: Guards +# ⚠ 本文件所有 `run:` 都在 `bash -e {0}` 下跑(GitHub 未指定 shell 时的默认值),脚本里的 +# `set -uo pipefail` **关不掉 -e**:裸管道 / 裸赋值 `x=$(… | grep …)` 零命中时会把整步静默杀死, +# 一条 `::error::` 都不打(M142 在 release-build.yml 栽过,M156 在这里补账)。探测一律 `if ! x=$(…)` 或 `$(… || true)`。 + # 架构与合规守门(与 fmt/clippy 同级,不允许 continue-on-error): # 1. core-no-ui —— crates/core 零 UI 依赖(D3 铁律),依赖表 + cargo tree 双查 # 2. presenter-no-ui —— crates/presenter 零 UI 依赖(D26 / M85):Slint 版与 iced 版共用的宿主层 @@ -54,7 +58,11 @@ jobs: run: | set -uo pipefail forbidden='slint|egui|eframe|iced|winit|gtk|javafx|tauri|fltk|druid|relm' - tree=$(cargo tree -p unlucky-core --edges normal --prefix none) + # 与下方 presenter / design 的 `if ! tree=$(…)` 对称:cargo tree 自己失败(改名 / 解析失败)时裸赋值会被 -e 静默杀死,只剩 exit code 1 无注解。 + if ! tree=$(cargo tree -p unlucky-core --edges normal --prefix none); then + echo "::error::cargo tree -p unlucky-core 执行失败 —— crate 是否仍叫 unlucky-core?" + exit 1 + fi echo "$tree" if echo "$tree" | grep -vE '^unlucky-core v' | grep -qiE "$forbidden"; then echo "::error::core 的依赖树出现 UI 框架 —— 传递依赖也不允许" @@ -109,7 +117,9 @@ jobs: exit 1 fi echo "$tree" - hits=$(printf '%s\n' "$tree" | grep -vE '^unlucky-presenter v' | grep -iE "$forbidden") + # 「零命中」本来就该是绿的正路,但裸赋值会把 grep 的 exit 1 交给 -e(见文件头): + # M156 之前这里每次零命中都整步红且零注解 —— presenter-no-ui 自 M89 引入起从未绿过。 + hits=$(printf '%s\n' "$tree" | grep -vE '^unlucky-presenter v' | grep -iE "$forbidden" || true) if [ -n "$hits" ]; then echo "::error::presenter 的依赖树出现 UI 框架(传递依赖也不允许),本次命中:" printf '%s\n' "$hits" | sed 's/^/ - /' @@ -318,9 +328,10 @@ jobs: } # 只对「文本里出现过 unsafe_code」的文件跑词法器(标识符不可能被空白拆开, # 所以这个预筛不会漏)。601 个文件 → 个位数个候选,整个 job 约 2 秒。 + # `git grep` 零匹配 exit 1 + pipefail → 裸赋值同样会被 -e 静默杀死(见文件头)。 actual=$(git grep -l 'unsafe_code' -- '*.rs' 2>/dev/null | LC_ALL=C sort | while IFS= read -r f; do if scan "$f"; then printf '%s\n' "$f"; fi - done | LC_ALL=C sort) + done | LC_ALL=C sort || true) echo "期望(恰好这一个):$EXPECTED" echo "实际扫到的集合:" if [ -n "$actual" ]; then printf '%s\n' "$actual" | sed 's/^/ - /'; else echo " (空)"; fi