ci(release): M164 arm64 判定权交回编译器 + 发布名单守卫(不翻牌)

根因(拿到的真实证据,不是猜的):v0.2.2(run 42322062879 / job 128248713926)与 v0.2.3
(run 42429017002 / job 128573547829)两份 check-run 注解逐字一致 —— 失败步骤是第 6 步
`Windows ARM64 工具链体检`,第 7 步 `cargo build` 状态 skipped。也就是说 v0.2.1~v0.2.3 五轮
全红都红在一个**编译前的启发式探针**上,真正的编译器/链接器一次都没说话。该探针的结论还与它
自己打印的快照矛盾:`SDK Lib 版本→um 架构: 10.0.22621.0→um:[arm,arm64,x64,x86,]` 明明在,却
同时报 `kernel32=缺失`(同一个 `find -path` 模式在本地合成目录树上命中)。runner 实况是
Windows 11 Arm64 + Visual Studio 2026 镜像,`VC.Tools.ARM64` 与 `Windows11SDK.22621/26100`
都装好了,M142 的 `setup.exe modify` 反倒返回非 0。

改:
- release-build.yml:探针降级为「只取证」——vswhere 组件查询 + 各目录 `.lib` 计数 +
  arm64 `link.exe` 候选,一条 `::error::` 都不写、永不 exit 1;不再自动补装 VS。红绿只由
  cargo/链接/静态 CRT 导入表门禁决定。cargo build 步给 arm64 显式备齐工具链:
  `rustup target add aarch64-pc-windows-msvc`、`vcvarsall.bat arm64` 取 `LIB`/`INCLUDE`、
  vswhere 定位 arm64 `link.exe` 后导出 `CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER`
  (顺序不能反:只给链接器不给 LIB ⇒ LNK1181 kernel32.lib)。
- 新增 packaging/check_publish_slots.py(344 行,零依赖):名单 ⇄ 产物**两个方向**。
  声明了缺 GUI/CLI ⇒ `::error::` + exit 1;有产物没声明 ⇒ `::warning::` 明说未发布(M142 之后
  这个方向是静默的,裁剪步只 echo 一行 drop:)。另有源码级断言(名单每项必须存在且 mode=ci、
  运行期名单必须等于文件里那行)与 8 条 `--self-test` 注入回归。
- release-publish.yml:裁剪前插一步跑那个守卫,原来内联的齐全性循环搬进脚本(一套判据一处实现);
  重算 SHA256SUMS 的步骤只负责重算。
- release-guard.yml:PR 阶段跑守卫自测 + 源码级断言。
- 文档同步:release.yml / release-publish.yml / release-build.yml 头注释、packaging/README §12、
  §1 矩阵、§3 构建与发布、§9 支持矩阵、§7.5 arm64 取证、release-notes.md、README/README.zh-CN
  的产物矩阵与说明。口径统一为「arm64 构建取证中、未发布」,不写成已支持。

没做的(按 tower 裁决「方案乙」):`PUBLISH_SLOTS` 本轮**不加回** arm64。arm64 从未产出过 PE、
本机也证不了,写进名单就等于拿 x64 的发布去赌它(M142 移出名单正是为避免这个事故)。下一 tag 的
CI 真出包后翻一行即可,守卫与 SHA256SUMS 自动跟着扩。

验证:workflow YAML 全部可被 PyYAML 解析;所有 `run:` 块过 `bash -n`;探针步在本机(无 VS/SDK)
实跑 exit 0 并打出实况注解;守卫 `--self-test` 8 条全绿、正反两个方向都在合成 dist 上实测过;
check_release_semantics.py(含 --self-mutation)/ release_marker / make_manifest 自检全绿;
cargo metadata 正常。**arm64 产物从未被构建过、也从未在真机跑过**——本机 `rustc --target
aarch64-pc-windows-msvc` 直接撞上没有 MSVC 链接器(git-bash 的 GNU `link` 被当成 link.exe),
`cargo check --workspace --target aarch64-pc-windows-msvc` 也死在 aws-lc-sys 的 cc-rs 阶段
(GNU host 上没有该 target 的 C 编译器)。真实结论只能等下一 tag 的 CI。
This commit is contained in:
AskaEth committed 2026-11-08 08:33:44 +08:00
1 parent 15a19bb375
commit e858664fca
13 files changed
+577 -120

No files matched your search

+16 -8
View File
@@ -3,19 +3,25 @@ name: Release
# 发布流水线:tag `v*` → **只构建两个 Windows 槽位**(各自原生 `windows-latest` / `windows-11-arm`)→ 单文件产物 +
# SHA256SUMS → artifact + GitHub Release。**push tag 默认创建稳定版**(M163:不带 `--prerelease`,否则
# `releases/latest` 永远 404、自更新通道取不到清单);同 tag 重跑幂等(覆盖资产与说明、不 create、不碰标记)。
# **构建 ≠ 发布**:只有 `PUBLISH_SLOTS` 里的槽位才进 Release 与 SHA256SUMS ——**M142 起只有 `windows-x64`**(arm64 连试
# 四轮未成,仍留矩阵里取证、红了不挡 x64 发布;它修好后把键加回那一行即可)。四档 Linux/macOS 从未验证,默认连构建都
# 不跑(M139:省配额、不留红叉);整表六槽位取证走 `gh workflow run release.yml -f all_slots=true`(槽位表在 `plan`)。
# **构建 ≠ 发布**:只有 `PUBLISH_SLOTS` 里的槽位才进 Release 与 SHA256SUMS ——**M142 起只有 `windows-x64`**(arm64 仍留
# 矩阵里取证、红了不挡 x64 发布)。**M164 的更正**:arm64 那五轮红其实全红在一个误判的编译前体检步(cargo/link 一次
# 都没跑过,见 `release-build.yml` 顶部),该门禁已拆、判定权交回编译器;但「arm64 能不能出 PE」只能由**下一 tag 的
# CI** 证明,故名单仍只列 x64(tower 裁决:不拿 x64 的发布去赌一个没验证过的槽位)。真出包之后把键加回那一行即可。
# 四档 Linux/macOS 从未验证,默认连构建都不跑(M139:省配额、不留红叉);整表六槽位取证走
# `gh workflow run release.yml -f all_slots=true`(槽位表在 `plan`)。
# 名单 ⇄ 产物两个方向都有守卫(M164):`packaging/check_publish_slots.py`(PR 阶段在 release-guard.yml,发布侧在
# release-publish.yml 的 `--dist` 模式)——声明了缺产物 ⇒ 红;有产物没声明 ⇒ `::warning::` 明说未发布。
# 契约唯一真相源 packaging/README.md,打包本体 packaging/make_artifacts.py(本地与 CI 同一份脚本)。`inputs.prerelease`
# 只在 **tag ref** 上 dispatch 才可达(跑 tag 得 `gh workflow run release.yml --ref v0.2.1`);分支 ref 的 dispatch 与
# push 一样被 release job 的 `if: github.ref_type == 'tag'` 挡在发布之外。
#
# M145 拆分(本文件与 packaging/README.md 都已顶到 400 行红线,下一处改动必越线):本文件只留**触发 + 槽位表 + 编排**,
# 两个 job 的实体各搬一份可复用工作流(`workflow_call`),步骤逐字未改:
# - `.github/workflows/release-build.yml` = 原 `build` job 全流程(Linux 依赖 / arm64 工具链体检 / cargo build /
# 静态 CRT 导入表门禁 / 打包 / 归档自检 / 上传 artifact / arm64 收尾注解),矩阵键换成同名 `inputs.*`。
# - `.github/workflows/release-build.yml` = 原 `build` job 全流程(Linux 依赖 / arm64 工具链取证(M164 起只取证)/
# cargo build / 静态 CRT 导入表门禁 / 打包 / 归档自检 / 上传 artifact / arm64 收尾注解),矩阵键换成同名 `inputs.*`。
# - `.github/workflows/release-publish.yml` = 原 `release` job 全流程(`PUBLISH_SLOTS` 白名单 / 裁剪 / 重算
# SHA256SUMS / 渲染说明 / `gh release` 幂等),`secrets.GITHUB_TOKEN` 改为显式透传的 secret。
# (M164 在裁剪前插了一步「发布名单守卫」,故它是 7 步而不是搬家时的 6 步。)
# `on` / `env` / `permissions` / `concurrency` 与 `plan` 的槽位表**一字未动**。
on:
@@ -72,9 +78,11 @@ jobs:
SLOTS = [
# Windows x64:MSVC + 静态 CRT(+crt-static)→ exe 不依赖 VC++ 可再发行包,双击即用的单文件。
dict(slot="windows-x64", os="windows-latest", build_dir="target/release", rustflags="-C target-feature=+crt-static", mode="ci"),
# Windows arm64:**原生** `windows-11-arm`(4C/16G,公开仓库免费;GitHub 文档的 Standard runners 也列
# `windows-11-vs2026-arm`)。M140 前是在 windows-latest 上交叉,**CI 从未成功过一次**(v0.2.1 首跑红在
# 工具链体检,M141/M142 在此修)。原生还让 `ull --version` 冒烟真跑,dumpbin 走 Hostarm64 分支。
# Windows arm64:**原生** `windows-11-arm`(4C/16G,公开仓库免费)。该标签自 2026-09 起是
# **Windows 11 Arm64 + Visual Studio 2026** 镜像(VS 在 `C:\Program Files\Microsoft Visual Studio\18`),
# 镜像清单里 `VC.Tools.ARM64` 与 `Windows11SDK.22621/26100` 都装好了。M140 前是在 windows-latest 上交叉;
# v0.2.1~v0.2.3 的红全红在 M141/M142 那个**编译前体检**步(cargo 永远 skipped),M164 已把它降级为只取证。
# 原生还让 `ull --version` 冒烟真跑,dumpbin 走 Hostarm64 分支。
dict(slot="windows-arm64", os="windows-11-arm", build_dir="target/release",
rustflags="-C target-feature=+crt-static", mode="ci"),
# ↓ 四档**未验证,不纳入 CI**:从未真构建成功、也没在真机跑过,默认一个都不编;`all_slots=true` 时照编