merge: 解 origin/dev 三处冲突(M182 / M184+M190 / README §14),两边都留
冲突(都来自别人后来改同一批文件): - crates/app-iced/src/platform/mod.rs:保留 M182 的 HostOs / host·linux·macos 分册表 / plan_corner_for,同时保留 M196 的 `[`win32::console`]` 落点说明;把 M182 措辞里已经不 成立的「唯一 unsafe 落点 / 只此一处」改成「两处落点(transparency + console)」 (unsafe-scope 门禁自 M196 起期望集合就是两处,不改这句文档就是错的)。 注意:`pub mod console;` 属于 `platform/win32/mod.rs`,本次解冲突时一度被误加到 `platform/mod.rs`(`cargo check` 立刻报 E0583 文件不存在),已修回。 - .github/workflows/release-build.yml:M190 的「PE 版本资源读回」步、M184 的 linux-x64 xvfb 冒烟步与首帧上传步**全部逐字保留**;M196 的 PE 子系统门禁作为**兄弟步** 插在导入表门禁之后(两道 PE 门禁互不替代)。按块比对:dev 的 10 个步骤逐字未变, 合并后 11 个步骤。 - packaging/README.md:保留 M184 的 §11 补充与 §12 行、M190 的 §14 签名段;§12 里 check_publish_slots 用 dev 的 11 条版本、另加 M196 的 check_pe_subsystem 行;§15 归位在 §14 之后。 行数:release-build.yml 合并后 413 行会撞 400 行红线(dev 侧本来 393),故把 M196 那一步 压到 6 行 + 1 空行(说明改由步骤名指路 packaging/README.md §15 与脚本 docstring 承载), 最终正好 400 行。 验证见 mission 报告:cargo check/test/fmt 全绿,两个 PE 门禁在同一批产物上都 exit 0 (子系统 GUI=2 / CLI=3,版本资源的 subsystem 读数同为 2 / 3)。
This commit is contained in:
commit
1764301cdf
290 files changed
+25890
-2228
No files matched your search
@@ -6,6 +6,9 @@ name: Release / build(可复用)
|
||||
# `matrix.rustflags` → `inputs.rustflags`。
|
||||
# **M164 改了两步**(只这两步):① `Windows ARM64 工具链体检` → `工具链取证`(不再 exit 1,判定权交回编译器;
|
||||
# 理由见该步上方的长注释);② `cargo build` 步给 arm64 槽位显式备齐 target / `LIB`+`INCLUDE` / arm64 `link.exe`。
|
||||
# **M184 加了一步**:`linux-x64` 的 xvfb 运行时冒烟(真渲一帧 + `[theme]` / `[backend] final` 日志断言 + 像素判定)——
|
||||
# 这一档进了 `PUBLISH_SLOTS`,「发出去的包真能跑」从此由 CI 每轮证明;判据只在 `linux-x64` 槽位上跑(arm64 没有
|
||||
# 对应的运行时证据,不给它加一条没验证过的门禁)。同一轮把 arm64 的失败收尾注解按槽位分支。
|
||||
# 矩阵**仍由调用方** `release.yml` 的 `plan` job 生成并在外层展开(矩阵不能带 `if`,`strategy` 可读 `needs`),
|
||||
# 本文件只跑**单个槽位**,不持有槽位表 —— 改槽位只改 `release.yml` 里那一处。
|
||||
# `env` 必须在被调方重复声明:**被调工作流不继承调用方的 workflow 级 `env`**(CARGO_TERM_COLOR / RUST_BACKTRACE
|
||||
@@ -203,11 +206,31 @@ jobs:
|
||||
fi
|
||||
fi
|
||||
cargo build --release --locked --bin unlucky-launcher-iced --bin ull
|
||||
# 产物清单只给 arm64 打:x64(当前唯一在发的槽位)这一步零变化,不额外给它加失败面。
|
||||
# 产物清单只给 windows-arm64 打:两档已发布的 x64(windows-x64 / linux-x64)这一步零变化,不额外给它们
|
||||
# 加失败面(linux-x64 的证据在它自己那条 xvfb 运行时冒烟步里)。
|
||||
if [ "$SLOT" = "windows-arm64" ]; then
|
||||
ls -l "$BUILD_DIR"/unlucky-launcher-iced* "$BUILD_DIR"/ull* || true
|
||||
fi
|
||||
|
||||
# (M190)版本资源门禁:**读产物字节**,不信构建日志。`build.rs` 里写了 `CompanyName` 不等于
|
||||
# 它进了 PE——资源在链接期被丢掉、或被后处理覆盖,都只有读回来才看得见。判据(字段值、四段式
|
||||
# 版本号、FIXEDFILEINFO 的 dwFileVersion)全在 `packaging/check_pe_version.py`,本机可跑。
|
||||
# 只在 Windows 槽位跑:Linux/macOS 产物没有 PE 头,那边 `build.rs` 整段不执行(见
|
||||
# `packaging/pe_version.rs` 文件头)。**工具缺失也 fail**:找不到 python 就等于门禁失效。
|
||||
- name: PE 版本资源读回(CompanyName / ProductName / 版权 / 版本号真的在产物里)
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.build_dir }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
PY=$(command -v python3 || command -v python)
|
||||
if [ -z "$PY" ]; then echo "::error::找不到 python,PE 版本资源门禁无法运行(门禁不降级)"; exit 1; fi
|
||||
# 版本号与 Cargo.toml **同源**:`[workspace.package] version = "x.y.z"`。
|
||||
version=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)
|
||||
echo "expect-version=$version"
|
||||
"$PY" packaging/check_pe_version.py "$BUILD_DIR/unlucky-launcher-iced.exe" "$BUILD_DIR/ull.exe" --expect-version "$version"
|
||||
|
||||
- name: Windows 单文件自检(导入表不得出现 VC++ 可再发行 DLL)
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
@@ -259,25 +282,55 @@ jobs:
|
||||
echo "::error::静态 CRT 未生效:exe 仍动态依赖 VC++ 可再发行包"; exit 1
|
||||
fi
|
||||
|
||||
# M196:**读产物 PE 头的 `Subsystem`**,不读源码。同一个修复 2026-11-01 曾打在已退役的 Slint 树
|
||||
# (`37d3039` 只改了 `crates/app/src/main.rs`,而 `crates/app` 自 M118 起被 workspace `exclude`、
|
||||
# 不进发布矩阵),于是「代码里写过」与「产物里有没有」彻底脱钩——双击多一个控制台窗口这个 bug
|
||||
# 就是这么活到 2026-11-08 的。本步只认那 4 个字节:GUI 产物必须是 WINDOWS_GUI(2),非 2 即红。
|
||||
# 反方向一并守:CLI 产物 `ull.exe` 必须仍是 CONSOLE(3)——它靠真控制台做 stdout/stderr,
|
||||
# 谁把属性抄到它头上,`ull --version | …` 会静默丢输出。守门本体在 packaging/check_pe_subsystem.py
|
||||
# (零第三方依赖,本地同一份代码可跑;`--self-test` 注入 8 条回归(红 6 / 绿 2)证明它会红)。
|
||||
- name: PE 子系统门禁(GUI 产物必须 WINDOWS_GUI/2,CLI 产物必须 CONSOLE/3)
|
||||
- name: PE 子系统门禁(GUI=WINDOWS_GUI/2,CLI=CONSOLE/3;判据与理由见 packaging/README.md §15)
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
run: |
|
||||
PY=$(command -v python3 || command -v python)
|
||||
"$PY" packaging/check_pe_subsystem.py --gui "${{ inputs.build_dir }}/unlucky-launcher-iced.exe" --cli "${{ inputs.build_dir }}/ull.exe"
|
||||
|
||||
# (M184)linux-x64 的**运行时门禁**:这一档已进 PUBLISH_SLOTS,所以「发出去的包真能开窗渲出一帧」得由 CI 每轮证明,
|
||||
# 不能只靠一次性的本机验收(证据与实测输出见 `packaging/docs/linux-evidence.md`)。
|
||||
# **只在 linux-x64 槽位上跑**:判据是按 x64 软渲染实测标定的;`linux-arm64` 上这条链一次都没验过(没有 arm64 的
|
||||
# xvfb 证据),写成无条件的 `runner.os == 'Linux'` 就等于给一个没验证过的槽位加一条会红的判据——正是 M171 那个
|
||||
# 「豁免行要单独落」的同类事故。宁可这条只在有证据的槽位上真跑。
|
||||
- name: Linux x64 运行时冒烟(xvfb 真渲一帧 + 主题/后端日志断言)
|
||||
if: inputs.slot == 'linux-x64'
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.build_dir }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
PY=$(command -v python3 || command -v python)
|
||||
# 读数(含文件字节偏移)直接进日志:红的时候要看的就是这个数,而不是「脚本说不对」。
|
||||
"$PY" packaging/check_pe_subsystem.py \
|
||||
--gui "$BUILD_DIR/unlucky-launcher-iced.exe" \
|
||||
--cli "$BUILD_DIR/ull.exe"
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends xvfb xauth \
|
||||
libxkbcommon-x11-0 libx11-6 libxcursor1 libxrandr2 libxi6 libfontconfig1 fonts-dejavu-core
|
||||
out="$RUNNER_TEMP/linux-smoke"
|
||||
mkdir -p "$out/data"
|
||||
log="$out/launcher.log"
|
||||
# 退出码单独取:`tee` 之后的 `$?` 是 tee 的,管道里 cargo/launcher 的失败会被吞成 0。
|
||||
set +e
|
||||
xvfb-run -a --server-args="-screen 0 1280x1024x24" \
|
||||
"$BUILD_DIR/unlucky-launcher-iced" --software-renderer \
|
||||
--screenshot "$out/linux-x64-first-frame.png" --data-dir "$out/data" 2>&1 | tee "$log"
|
||||
code=${PIPESTATUS[0]}
|
||||
set -e
|
||||
echo "launcher exit=$code"
|
||||
# 两条日志断言(两行都是**恒开**的,不依赖 ULL_ACCEPTANCE):
|
||||
# `[theme] source=…flavor=…follows_system=…` 证明主题是按预期来源定的(截图通道默认 Light),
|
||||
# `[backend] final=… result=started` 证明渲染后端真的起来了(而不是起来前就崩了)。
|
||||
grep -q '^\[theme\] source=' "$log" || { echo "::error::缺少 [theme] 行(主题来源没打印)"; exit 1; }
|
||||
grep -q '^\[backend\] final=.* result=started' "$log" || { echo "::error::缺少 [backend] final=… result=started(渲染后端没起来)"; exit 1; }
|
||||
python3 packaging/check_screenshot.py "$out/linux-x64-first-frame.png" --json
|
||||
ls -l "$out"
|
||||
exit "$code"
|
||||
|
||||
- name: 上传 Linux x64 首帧图(失败也传,人眼复核用)
|
||||
if: always() && inputs.slot == 'linux-x64'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-x64-first-frame
|
||||
path: ${{ runner.temp }}/linux-smoke/
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: 打包(产物 + SHA256SUMS)
|
||||
shell: bash
|
||||
@@ -330,7 +383,18 @@ jobs:
|
||||
# 「不挡发布」——只剩一句 `Process completed with exit code 1.` 的教训见上面那条体检步骤。
|
||||
# M164 起本槽位的红**只可能来自真实构建链路**(体检已降级为取证、永不 exit 1),所以这条注解同时也是
|
||||
# 「arm64 到底能不能编出来」的答案所在:红了就把上面的编译器/链接器原文当根因,别再回去改体检。
|
||||
# M184:Linux arm64 进来(它现在是 `mode: ci`,tag 推送默认就编),措辞按槽位分支 —— 两个 arm64 都**不在**发布名单里,
|
||||
# 但理由不同:windows-arm64 等「能不能出 PE」的答案,linux-arm64 等「真机跑不跑得起来」的答案。
|
||||
- name: arm64 失败收尾注解(红不挡发布)
|
||||
if: failure() && inputs.slot == 'windows-arm64'
|
||||
if: failure() && (inputs.slot == 'windows-arm64' || inputs.slot == 'linux-arm64')
|
||||
shell: bash
|
||||
run: echo "::error::[arm64] 本槽位已红,失败步骤见本 job 的步骤名(M164 起只会是 cargo build / 链接 / 导入表门禁 / 打包,体检步不再判红);PUBLISH_SLOTS 当前只有 windows-x64 ⇒ 本次 Release 仍照发 x64,arm64 产物不进 Release"
|
||||
env:
|
||||
SLOT: ${{ inputs.slot }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "$SLOT" = "linux-arm64" ]; then
|
||||
reason="本槽位只有构建证据、运行时完全未验(没有 ARM64 真机跑过一帧)"
|
||||
else
|
||||
reason="失败步骤见本 job 的步骤名(M164 起只会是 cargo build / 链接 / 导入表门禁 / 打包,体检步不再判红)"
|
||||
fi
|
||||
echo "::error::[$SLOT] 本槽位已红:$reason。PUBLISH_SLOTS 当前是 windows-x64 + linux-x64 ⇒ 本次 Release 仍照发那两档,$SLOT 的产物不进 Release"
|
||||
Reference in new issue
Block a user