From fdb9ebb01405c578868c2f8b88e02bbb11dcffcf Mon Sep 17 00:00:00 2001 From: AskaEth Date: Fri, 6 Nov 2026 20:07:04 +0800 Subject: [PATCH] =?UTF-8?q?build(packaging):=20M147=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20linux-check-docker.sh=EF=BC=8C=E6=9C=AC=E6=9C=BA=E5=A4=8D?= =?UTF-8?q?=E8=B7=91=20ci.yml=20=E7=9A=84=E4=B8=A4=E6=9D=A1=20ubuntu=20?= =?UTF-8?q?=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `linux-smoke-docker.sh` 复刻的是 runtime-smoke(能不能真跑起来),本脚本复刻的是**编译期 门禁**(能不能编过 / 测过):`cargo clippy --workspace --all-targets -- -D warnings` 与 `cargo test --workspace --all-targets --no-fail-fast`,命令与 ci.yml 逐字一致。 为什么值得单独一条脚本:M144 的两条 ubuntu 红只在「Linux + --all-targets + -D warnings」 三件事凑齐时才炸,Windows 本机永远复现不了(那些 `#[cfg(target_os = "windows")]` 分支在 Windows 上都有使用者)。本脚本是「本机提前挡住它们」的唯一通道。 实现:在现成的 `ull-linux-smoke:bookworm` 上只加一层 `cmake` + `ninja-build`(`aws-lc-sys` 缺 cmake 编不过,M144 实测),缓存卷挂 `registry` 子目录(直接挂 /usr/local/cargo 会盖掉 镜像里的 cargo 本体,M62 踩过),Git Bash 路径用 `cygpath -m` 归一。 - `ULL_CHECK_STAGES`(默认 `clippy test`):两阶段各自跑完再汇总退出码,一处红不掩盖另一处; `ULL_CHECK_FAIL_FAST=1` 恢复首错即停。 - `ULL_CHECK_TEST_ARGS`(默认照抄 ci.yml):快查用 `-p unlucky-app-iced --lib`。 - 每阶段打印 `<命令> → exit=`,便于与 CI 注解里的码对照。 诚实边界写在脚本头:基础镜像 Debian 12 / runner Ubuntu 24.04,只对齐编译期判定,不覆盖 发行版差异面;也不跑 fmt / build / runtime-smoke。 M147 实测(本机 Docker / ull-linux-check:bookworm / 2026-11-06): - `ULL_CHECK_STAGES=clippy` → exit=0(1m27s,原 14 条错) - `ULL_CHECK_STAGES=test ULL_CHECK_TEST_ARGS='-p unlucky-app-iced --lib'` → 623 passed / exit=0 --- packaging/README.md | 1 + packaging/linux-check-docker.sh | 116 ++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 packaging/linux-check-docker.sh diff --git a/packaging/README.md b/packaging/README.md index 9f56fb5..a0766a9 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -66,6 +66,7 @@ Git Bash 下会静默落进 Docker VM(脚本内部用 `cygpath -m` 归一) | `packaging/check_screenshot.py` | 截图非空白判定(CI 门禁 + 本地手动跑,零第三方依赖) | ≤400 | | `packaging/ci-runtime-smoke.md` | §11 的细节:断言口径/阈值依据/失效模式/复跑 | ≤400 | | `packaging/linux-smoke-docker.sh` | 本地复跑 `runtime-smoke`(Docker + xvfb) | ≤400 | +| `packaging/linux-check-docker.sh` | 本地复跑 `ci.yml` 的两条 ubuntu 门禁(clippy / test,Docker) | ≤400 | | `.github/workflows/release.yml` | tag 触发 → 选槽位(`plan`)→ 调下面两个可复用工作流 | ≤400 | | `.github/workflows/release-build.yml` | `workflow_call`:单槽位构建(体检 / cargo / 打包 / 上传 artifact) | ≤400 | | `.github/workflows/release-publish.yml` | `workflow_call`:发布(`PUBLISH_SLOTS` 裁剪 / SHA256SUMS / Release) | ≤400 | diff --git a/packaging/linux-check-docker.sh b/packaging/linux-check-docker.sh new file mode 100644 index 0000000..8867c1b --- /dev/null +++ b/packaging/linux-check-docker.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# 本地复跑 `.github/workflows/ci.yml` 的两条 **ubuntu 门禁**:`clippy --workspace --all-targets +# -- -D warnings` 与 `test --workspace --all-targets`。 +# +# 为什么要有这条脚本(与 `linux-smoke-docker.sh` 同一动机,但受检对象不同): +# - smoke 脚本复刻的是 `runtime-smoke` job(能不能真跑起来);本脚本复刻的是**编译期门禁** +# (能不能编过 / 测过)。M144 的三条红里有两条(clippy ubuntu、test ubuntu)属于后者, +# 而它们只在「Linux + `--all-targets` + `-D warnings`」三件事凑齐时才炸—— +# 在 Windows 本机永远复现不了(Windows 上那些 `#[cfg(target_os = "windows")]` 分支都有使用者)。 +# 所以这条脚本是「本机提前挡住那两条红」的唯一通道。 +# +# 用法: +# bash packaging/linux-check-docker.sh [仓库根目录] +# ULL_CHECK_STAGES=clippy bash packaging/linux-check-docker.sh # 只跑 clippy +# ULL_CHECK_TEST_ARGS='-p unlucky-app-iced --lib' \ +# ULL_CHECK_STAGES=test bash packaging/linux-check-docker.sh # 只跑一个 crate 的单测 +# +# 前置:基础镜像 `ull-linux-smoke:bookworm`(由 `packaging/linux-smoke-docker.sh` 建)。 +# 本脚本在它之上只加一层 `cmake` + `ninja-build`:`aws-lc-sys`(rustls 的汇编后端) +# 缺 cmake 编不过,M144 实测过。 +# +# 诚实边界(别把它当 runner 的等价物): +# - 基础镜像是 **Debian 12(glibc 2.36)**,官方 runner 是 **Ubuntu 24.04(glibc 2.39)**; +# 两者 rustc 走同一份 `rust-toolchain.toml`(stable),所以**编译期 lint 与单测判定**可对齐, +# 但发行版差异面(系统库版本、字体)不受本脚本保护。 +# - 本脚本只跑 ci.yml 里那两条命令,不跑 fmt / build / runtime-smoke。 +# - 冷编很贵(全 workspace + `--all-targets`,M144 实测 15–25 分钟)。缓存卷 `ull-linux-check-target` +# 第二次起是热的;**别**把宿主机的 target 目录挂进来(路径与指纹都对不上,等于骗自己)。 + +set -euo pipefail + +repo_root=$(cd "${1:-.}" && pwd) +base_image=${ULL_SMOKE_IMAGE:-ull-linux-smoke:bookworm} +image=${ULL_CHECK_IMAGE:-ull-linux-check:bookworm} +cargo_volume=${ULL_CARGO_VOLUME:-ull-cargo-reg} +target_volume=${ULL_CHECK_TARGET_VOLUME:-ull-linux-check-target} +apt_mirror=${ULL_APT_MIRROR:-https://mirrors.tuna.tsinghua.edu.cn} +stages=${ULL_CHECK_STAGES:-clippy test} +test_args=${ULL_CHECK_TEST_ARGS:---workspace --all-targets --no-fail-fast} +fail_fast=${ULL_CHECK_FAIL_FAST:-0} + +# Git Bash 里路径是 MSYS 虚拟路径:直接喂给 `docker -v` 会被当成容器内路径(M62 踩过)。 +if command -v cygpath >/dev/null 2>&1; then + repo_root=$(cygpath -m "$repo_root") +fi +echo "== 仓库: $repo_root" +echo "== 阶段: $stages(test 参数: $test_args)" + +if ! docker image inspect "$base_image" >/dev/null 2>&1; then + echo "!! 缺基础镜像 $base_image —— 先跑一次:" >&2 + echo " bash packaging/linux-smoke-docker.sh . D:/tmp/ull-smoke" >&2 + echo " (它建的镜像里已经带了 ci.yml 那批图形栈编译依赖;本脚本只在其上加 cmake/ninja)" >&2 + exit 2 +fi + +# 一层派生镜像:cmake + ninja-build。只在缺镜像或显式 ULL_CHECK_REBUILD_IMAGE=1 时重建。 +if ! docker image inspect "$image" >/dev/null 2>&1 || [ "${ULL_CHECK_REBUILD_IMAGE:-0}" = "1" ]; then + context=$(mktemp -d) + trap 'rm -rf "$context"' EXIT + cat >"$context/Dockerfile" <&2; exit 2 ;; + esac + echo "== 开始: $label" + set +e + "$run" + code=$? + set -e + # 退出码单独成行:一眼能看出是「编译期 lint」还是「单测」,也能与 CI 注解里的码对照。 + echo "== 结束: $label → exit=$code" + if [ "$code" -ne 0 ]; then + overall=1 + if [ "$ULL_CHECK_FAIL_FAST" = "1" ]; then exit "$code"; fi + fi + done + echo "== 汇总: $ULL_CHECK_STAGES → exit=$overall" + exit "$overall" + ' + +echo "== 两条 ubuntu 门禁已跑完(上表 exit=0 才算绿)"