Commit Graph
10 Commits
Author SHA1 Message Date
AskaEth 95e8a5ca42 fix(ci): M67 文件行数守门补上 *.py / *.sh —— 脚本不再漏网
file-size job 原先只扫 *.rs/*.md/*.slint/*.yml/*.yaml/*.toml/*.json,
packaging/ 下的构建辅助脚本(make_artifacts.py、check_screenshot.py、
linux-smoke-docker.sh)完全没有任何行数保护。

- 在 git ls-files 的 pathspec 末尾加 '*.py' '*.sh',语义不变(>400 行即硬失败)
- 保留 LICENSE*/CHANGELOG* 排除;Cargo.lock 等机器生成文件刻意不入列
- 阈值、失败方式(::error + exit 1)均未改动
2026-11-01 16:22:51 +08:00
AskaEth 7e08e0ccc9 fix(docs): M62 r1 —— 修正「缺字体→空图+exit 0」的错误论据,拆出运行时冒烟细节文档
review r1(p2-1items/fix-then-merge)只要求改文档与注释,门禁逻辑一行未动。

- P2-1(唯一阻塞项):原稿称「字体库缺失 → 合法 PNG + 退出码 0」,这是错的。review 实测两条失效都是
  **硬失败**:完全没有字体 → fontique panic(退出码 101,不产生 PNG);非软渲染(默认 femtovg)→
  `take_snapshot is not supported by this FemtoVG backend`(退出码 1)。改正口径:`--screenshot` 的 PNG
  是进程自己编码写出的,只要走到 `take_snapshot` 就是「合法 PNG + 退出码 0」,像素断言是**纵深防御**,
  守的是「进程活着、PNG 合法、但场景几乎没画」这一档;其余情形本机暂无样本,属防御性设计、不宣称已复现。
  落点:packaging/ci-runtime-smoke.md §1 与 packaging/check_screenshot.py 模块 docstring。
- P3-1:ci.yml 的 runtime-smoke job 头补一行 —— 本 job 绑死 Slint `Window::take_snapshot`,迁 iced 后必须
  提供等价离屏截图通道,否则静默退化成「能起进程」。
- P3-2:阈值余量写明量级(342/64=5.3×、19.45/3.0=6.5×、0.00761/0.001=7.6×,改「5~8 倍」);并写明
  闸门下限 ≈「至少画出一条标题栏」(review 实测切片 174/35.10/0.02623 与右下 400×300 切片仍 pass),
  即只证明「场景被真实渲染过」,不证明元素齐全、更不证明视觉正确。
- P3-3:README 398/400 已贴红线 —— 借 review 给的逃生口**提前拆**:细节搬进 packaging/ci-runtime-smoke.md
  (78 行),README §11 收缩为 12 行索引(374 行),并写明「再增长继续往细节文档写,两文件都 ≤400」。
- P3-4:本地复跑示例改 Windows 安全路径 `D:/tmp/ull-smoke`;脚本对 repo_root/out_dir 统一 `cygpath -m`
  归一并回显真实路径(Git Bash 下 `/tmp` 会静默落进 Docker VM,宿主什么都收不到 —— review 实测踩到)。
- P3-5:两个 `run:` 里的 `set -o pipefail` 保留但加注释说明「当前无管道,为将来加管道先有失败传播」;
  `cargo clean -p unlucky-app || true` 加内联注释(N7 兜底,CI 里没有对应行,别误抄进 ci.yml)。

验证:`--selftest` 三组仍全部 fail(判红能力未被改坏);真实截图仍 pass(1180x760 / 342 / 19.45 / 0.00761);
0 字节与非 PNG 路径 exit 1;`yaml.safe_load` 通过(6 job,Linux 槽位无 continue-on-error,artifact 步
`if: always()`);`cargo fmt --all --check` 退出 0;cygpath 修复后重跑 Docker 冒烟,宿主机 D:/tmp/ull-m62-rev2
拿到 PNG,md5 `156c382a…` 与前两次 run 及 review 的 artifact 完全一致。
2026-11-01 16:15:47 +08:00
AskaEth ea5f66cf92 feat(ci): M62 —— Linux runtime-smoke(xvfb 真渲染一帧)+ 像素非空白门禁
「编得过」不等于「跑得起来」:CI 里 Linux/macOS 此前只 build + test,从未创建过真实图形窗口。
本 commit 补第一份 Linux 真实图形环境运行证据,并把它做成不可伪造的门禁。

- ci.yml 新增 runtime-smoke(ubuntu-latest):装 xvfb + 软渲染/字体依赖,用 xvfb-run 起 GUI 进程,
  走既有 `--software-renderer --screenshot` 通道渲出一帧 PNG,再断言 ①退出码 0 ②PNG 宽高 > 0
  ③非空白(唯一色数 / 亮度σ / 强边缘占比三项过阈值),并把截图作为 artifact `runtime-smoke-screenshot` 上传。
  既有 fmt/clippy/test/build 四个 job 与触发器语义零改动(纯追加)。
- ci.yml 新增 runtime-smoke-macos 探针:只在 workflow_dispatch 触发且 continue-on-error。官方 macOS
  runner 处于 LaunchDaemon 上下文、无 WindowServer 会话,大概率建不了窗口;本机无 macOS 且 worker 禁
  push,这条路径尚无实测证据,故不拿它卡 PR 门禁(首跑结论决定升常驻或按 D26 归入 iced 重写)。
- packaging/check_screenshot.py:零第三方依赖的 PNG 解码(zlib + 反过滤 0~4)与三项指标判定,
  `--selftest` 打印阈值依据(人为纯色帧 1/0.0/0.0 必红,真实帧 342/19.45/0.00761 全过线)。
- packaging/linux-smoke-docker.sh:在 Docker 里复刻同一 job(TUNA apt/rustup 源),便于无 Linux 桌面的本地复跑。
- packaging/README.md §11:覆盖平台、阈值依据数值、本地复跑、已知跳过项、迁 iced 后需重新验证。

本机实测(Debian 12 容器 + xvfb + 软渲染):退出码 0,PNG 1180x760,唯一色 342 / σ 19.45 / 强边缘 0.00761。
CI(Ubuntu 24.04 runner)首跑仍未验证——本 job 证明「能出图」,不证明视觉正确。
2026-11-01 16:15:47 +08:00
AskaEth 4c1a6c54e5 fix(release): M51 r1 —— linux-arm64 改用 ubuntu-22.04-arm(与 x64 同 glibc 2.35 地板)
P2-1:24.04-arm 会给出 2.39 地板,把 Debian 12 / Raspberry Pi OS Bookworm
(2.36)挡在门外,且「arm64 只有 24.04 档」这句前提是错的(同段注释自己就承认
ubuntu-22.04-arm 有效)。改 os 为 ubuntu-22.04-arm,注释改成「与 x64 同地板
(2.35),覆盖 Debian 12 / Ubuntu 22.04 arm64 / RPi OS Bookworm」;
README §3/§4/§7.5/§9 与 release-notes 的 Downloads/Support matrix 全量订正
2.39 → 2.35+,删掉「arm64 地板高于 x64」的对比措辞。槽位名、产物名、六槽位
齐全性检查与打包脚本均未变。

P2-2:rustup target add 步骤改 env TARGET + `rustup target add "$TARGET"`,
并补 shell: bash(此前是全文件唯一没显式 shell 的 run,在 Windows 槽位会落进
pwsh);Linux 图形栈依赖那步也补了 shell: bash,现在所有 run 都显式 bash、
run 块内零 `${{ }}` 直插。

顺带 nit:host_slot() 报错改回原始 arch token(`riscv64` 不再显示成 None),
README §7.5 宣传的那个用例现在诊断可读。

验证:yaml 结构断言(六槽位 / linux-arm64=ubuntu-22.04-arm / 齐全性循环 6 /
run 块 ${{ }} 零泄漏 / run 步骤全带 shell)、全部 run 块 bash -n、grep 2.39
零残留、host_slot 7 组合注入 + freebsd/riscv64 报错含原名、image_arch 真 exe、
windows-arm64 stub 全流程、架构守卫拦截、linux-arm64 归档两次 sha256 一致
(f949d0f5… 与上一轮相同)、windows-x64 原生回归(冒烟 + sha256sum -c)。
2026-11-01 14:16:29 +08:00
AskaEth 15caa1b61f feat(release): M51 —— 发布矩阵补 Linux arm64 与 Windows arm64 两槽位(六槽位)
- release.yml:加 linux-arm64(原生 ubuntu-24.04-arm runner)与 windows-arm64
  (windows-latest 上交叉编译到 aarch64-pc-windows-msvc);产物根改由
  matrix.build_dir 参数化,dumpbin 自检与打包都吃矩阵路径而非硬编码 target/release;
  交叉槽位多两步(rustup target add + ARM64 库体检),release job 的槽位齐全性
  检查从四扩到六。
- make_artifacts.py:--slot / --build-dir 参数化 + 六槽位映射;打包前回读可执行文件头
  (PE 机器码 / ELF e_machine / Mach-O cputype)校验架构,跨槽位构建自动跳过
  ull --version 冒烟并打印原因(不在 x64 上假装跑得动 arm64 二进制)。
- packaging/README.md + release-notes.md:两张支持矩阵同步加 Windows 11 ARM64 与
  Linux arm64 行;arm64 glibc 地板如实写 2.39(高于 x64 的 2.35),并说明与 Termux
  实验级的区别(这两个是正式发布槽位)。

本地验证:宿主判定注入(七个组合 + 非法宿主 exit 1)、文件头架构识别(真 x64 exe +
合成 PE/ELF/Mach-O 头)、windows-arm64 stub 全流程、架构守卫真拦、linux-arm64 归档
两次 sha256 一致、windows-x64 原生回归(冒烟 + sha256sum -c)。arm64 真机构建由 CI 补。
2026-11-01 13:48:37 +08:00
AskaEth a6013c7d22 fix(ci/release): M50 —— Windows 槽位 dumpbin 定位链改三级(vswhere → find → PATH)
v0.1.0 首跑(run 41273841717)windows-x64 在「Windows 单文件自检」挂
`找不到 dumpbin,无法校验导入表(静态 CRT 门禁不降级)`。两个独立根因:

- `command -v dumpbin` 在 windows-latest 上不成立:VS 环境未预置进 PATH。
- 兜底 glob 深度错了一级:写的是 `<VS 根>/<年>/VC/Tools/...`,真实布局是
  `<VS 根>/<年>/<版次>/VC/Tools/...`(2022/Enterprise、2022/BuildTools),
  所以即便 PATH 失守、glob 也不可能命中。
- 且只扫了 64 位 `Program Files` 根,Build Tools 落在 `Program Files (x86)` 根。

改成三级定位链,全不命中才 fail(门禁语义一字未动:工具缺失仍 exit 1、
导入表出现 VCRUNTIME/MSVCP/MSVCR/ucrtbase 仍 exit 1,文案不变):

1. vswhere —— VS 官方定位器,安装器自身路径固定,与 VS 版本/版次/布局无关:
   `.../Installer/vswhere.exe -latest -products '*' -find <pattern>`。
   模式先试反斜杠(官方文档形式)、再试正斜杠,输出统一折成正斜杠后再执行。
2. find 兜底 —— 两个 VS 根(64 位 + x86)按路径模式扫,`-maxdepth 11`
   留一级余量,不再依赖固定层数的 glob。
3. PATH —— 最后才试,PATH 最不可控。

另加一行 `dumpbin: <路径>(定位自 <层级>)`,下次真机挂掉能直接看出命中哪一级。
同文件其余步骤不依赖 VS 环境(已逐条核对),无需收敛。

验证(本机无 VS):
- 抽出 run 块 `bash -n` 通过;13 条 stub 用例全绿:无工具→fail 文案不变且不写
  dependents.txt、vswhere 反斜杠/正斜杠两个模式、两处 VS 根 find 兜底、PATH 兜底、
  动态 CRT 仍 fail-closed、vswhere 优先于 PATH、vswhere 输出的反斜杠路径归一化后可执行。
- 未改写的原始 run 块在本机实跑:干净 exit 1 + 原文案,不误命中、不崩。
- yaml 解析 + 23 条结构断言全过(矩阵四槽位、触发条件、门禁 grep/文案/exit 原样);
  文件 276 行 ≤ 400。
- git-bash 行为实证:`.exe` 的 `-x` 为真、非可执行文件为假、`find` 接受含空格的
  `C:/Program Files` 根。
真机验证由 merge 后 retag 重跑流水线完成。
2026-11-01 12:58:40 +08:00
AskaEth 62019a29cd fix(packaging): M47 r1 P2 —— 重跑不再断言 pre-release 标记
reviewer 指出:edit 分支此前每次默认重跑都重传 --prerelease,会把用户按
README 建议手动提升为 stable 的 Release 静默翻回 pre-release,文档承诺"重跑
不翻转标记"不成立。按首选修法让代码匹配文档:

- release.yml:create/edit 两套标记分开算。create 保持老契约(空输入 → 首建
  pre-release);edit 只在 inputs.prerelease 显式给出时断言
  (true → --prerelease,false → --prerelease=false),空值(push 或其 Re-run)
  不传任何标记。非法取值直接 ::error + exit 1。
- README §3:重跑语义与实现逐字一致,并把"改标记"的两条等价路径
  (gh workflow run -f prerelease=false / 手动 gh release edit)与 dispatch
  语义写顺;yml 头注释同步一句。
2026-11-01 09:37:55 +08:00
AskaEth ea6016716e chore(packaging): 收 M46 r1 六条 P3(dumpbin 门禁/ref 注入面/重跑幂等/文档口径)
- O1 release.yml 找不到 dumpbin 从 ::warning+exit 0 改为 ::error+exit 1(门禁不降级),
  README §7.4 同步为"两侧都 fail、没有降级分支"
- O2 打包 step 改用 env REF_TYPE/TAG 传参,bash 里不再出现 ${{ }} 直插;
  release job 的 TAG/PRERELEASE 已是 env 写法,全文件复核无同类风险点
- O3 gh release create 改为 view 命中则 upload --clobber + edit,同 tag 重跑幂等;
  README §3 补重跑语义与 pre-release 标记以首次创建为准
- O4 yml 头注释与 README §3 点明 inputs.prerelease 只在 tag ref 上 dispatch 可达
  (UI 只能选分支,需 gh workflow run --ref v<tag>),不与"dispatch 只构建不发布"冲突
- O5 release-notes 模板补 Termux 试验级行,README §9 同口径,标题改为"逐行一致"
- O6 README §6 补 ci.yml 每次 push/PR 的 release build 吃 fat LTO 链接时间;
  订正"fat 是全局单线程 LTO"为 codegen-units=1 导致单线程(§6/§7.1 两处);
  §7.3 写入 reviewer 补测的 tar 可复现证据 a99d6e9e…92f8
2026-11-01 09:30:27 +08:00
AskaEth 76d83148ff feat(packaging): 单文件产物矩阵 + tag 触发的 Release 流水线(M46)
- packaging/make_artifacts.py:本地与 CI 共用的打包脚本 —— 版本取自 cargo metadata
  (tag 交叉校验,不一致即失败)、按宿主判定槽位、Windows 裸 exe / UNIX tar.gz
  (内含 LICENSE/NOTICE/README.md)、SHA256SUMS.txt;打包前跑 `ull --version` 断言版本;
  tar 内 mtime/uid 归零 + gzip header mtime=0 → 同源构建 sha256 可复现
- packaging/README.md:产物矩阵与命名约定、版本唯一真相源、各平台运行时依赖、
  软渲染兜底、release profile 取舍、**本机实测**体积与冒烟证据、合规与支持矩阵
- packaging/release-notes.md:GitHub Release 说明模板({{VERSION}}/{{SUMS}},
  写清 Win10+ / macOS 12+ / Linux x64 支持矩阵)
- .github/workflows/release.yml:tag v* 触发四槽位矩阵 → 产物 + 重算 SHA256SUMS →
  gh release create(pre-release 默认开,workflow_dispatch 只构建);Windows 用
  +crt-static 并以 dumpbin 导入表把"单文件"做成硬门禁;归档内容自检 LICENSE/NOTICE/README
- Cargo.toml:release profile lto thin → fat(实测 GUI 16,366,080 → 14,595,584 B
  = −10.8%,ull 7,572,992 → 6,157,824 B = −18.7%)

验证:cargo build --release 通过;GUI `--software-renderer --screenshot` 出 1180×760 PNG、
`ull --version` = 0.1.0;PE 导入表 33 个 DLL 全为系统库(无 VCRUNTIME/libwinpthread);
cargo deny licenses/bans/sources ok;workflow 用 python yaml 解析自检。
2026-11-01 08:33:17 +08:00
AskaEth bc41dfcf7d Unlucky Launcher v0.0.1-alpha
CI / fmt (rustfmt --check) (push) Canceled after 0s
CI / clippy (ubuntu-latest) (push) Canceled after 0s
CI / clippy (windows-latest) (push) Canceled after 0s
CI / test (ubuntu-latest) (push) Canceled after 0s
CI / test (windows-latest) (push) Canceled after 0s
CI / build release (ubuntu-latest) (push) Canceled after 0s
CI / build release (windows-latest) (push) Canceled after 0s
Guards / core 零 UI 守门 (push) Canceled after 0s
Guards / 文件行数 ≤400 守门 (push) Canceled after 0s
Guards / 依赖许可与来源(cargo-deny) (push) Canceled after 0s
Rust 原生单文件 Minecraft 启动器:CLI 完整可用(install/launch/accounts/java/diagnose/agent),
MCP server 接入外部 Agent 工具,GUI 开发中。
2026-10-31 21:54:10 +08:00