Files
Unlucky-Launcher/packaging/linux-check-docker.sh
T
AskaEth fdb9ebb014 build(packaging): M147 新增 linux-check-docker.sh,本机复跑 ci.yml 的两条 ubuntu 门禁
`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=<code>`,便于与 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
2026-11-06 20:07:04 +08:00

117 lines
5.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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" <<EOF
FROM $base_image
# 基础镜像已把 apt 源改到 $apt_mirror(见 linux-smoke-docker.sh)。
# aws-lc-sys(rustls 的汇编后端)构建时要 cmake + ninja,缺了就是在 C 依赖里报错退出,
# 与 Rust 侧代码无关——别被那种红骗去改源码(M144 实测)。
RUN apt-get update \\
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\
cmake ninja-build \\
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
EOF
docker build -t "$image" "$context"
fi
# 缓存卷挂到 `registry` 子目录:直接挂 /usr/local/cargo 会盖掉镜像里的 cargo 本体(M62 踩过)。
MSYS_NO_PATHCONV=1 docker run --rm \
-v "$repo_root:/src" \
-v "$cargo_volume:/usr/local/cargo/registry" \
-v "$target_volume:/target" \
-w /src \
-e CARGO_TARGET_DIR=/target \
-e CARGO_TERM_COLOR=never \
-e ULL_CHECK_STAGES="$stages" \
-e ULL_CHECK_TEST_ARGS="$test_args" \
-e ULL_CHECK_FAIL_FAST="$fail_fast" \
"$image" bash -euo pipefail -c '
rustc --version && cargo --version && cat /etc/debian_version
cmake --version | head -1 && ninja --version
run_clippy() { cargo clippy --workspace --all-targets -- -D warnings; }
# 故意不加引号:ULL_CHECK_TEST_ARGS 是一串参数(默认照抄 ci.yml 的那条命令)。
run_test() { cargo test $ULL_CHECK_TEST_ARGS; }
overall=0
for stage in $ULL_CHECK_STAGES; do
case "$stage" in
clippy) label="cargo clippy --workspace --all-targets -- -D warnings"; run=run_clippy ;;
test) label="cargo test $ULL_CHECK_TEST_ARGS"; run=run_test ;;
*) echo "!! 未知阶段: $stage(可选 clippy / test)" >&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 才算绿)"