现象:Windows runner 明明在线、job 也确实派给了 windows-runner-01(它自己的日志: "Runner labels: windows-latest, windows-2025, windows-2022"),但每次运行里 Windows 产物都是 skipped。 原因在 job 级 if 上: (github.event_name != 'workflow_dispatch' && vars.ENABLE_WINDOWS == 'true') Gitea 的 runner 在 job 级 if 里拿不到(或拿不对)vars 上下文,条件恒为假 —— 而这个 条件写反的代价是"静悄悄不编",不看 runner 日志根本看不出来。同一份文件里 `github.event.inputs.linux != 'false'` 这个形式在 runner 日志里能看到正常求值 (evaluating expression '...' evaluated to 'true'),所以三个平台统一成这种形式: Linux / Windows : github.event.inputs.<平台> != 'false' → 默认跑 macOS : github.event.inputs.macos == 'true' → 默认不跑(还没有机器) 同时把 workflow_dispatch 里 windows 的默认值改成 true,并更新文件头:写清三台 runner 各自声明的标签、为什么不能拿 Linux 交叉编 Windows/macOS、以及第 4 条—— 平台开关不要用仓库变量(附上这次的证据)。 runs-on 里的 vars.RUNNER_* 保持不变(标签不匹配时用它们覆盖)。
第一次真实运行的日志(job 14)钉出来的两件事: 1. 上传产物那一步一直是失败的: GHESNotSupportedError: @actions/artifact v2.0.0+, upload-artifact@v4+ and download-artifact@v4+ are not currently supported on GHES v4 里的 @actions/artifact 会拒绝非 github.com 的服务器。Gitea 实现的是 v3 那套 接口(ACTIONS_RUNTIME_URL),所以三个平台都换成 upload-artifact@v3,并加一个 .github/actionlint.yaml 把"v3 太旧"这条 GitHub 规则的误报关掉(原因写在里面)。 产物路径本身没问题:日志里 tauri build 已经产出 deb/AppImage,v4 在报错之前也 认出了那批文件("The least common ancestor is .../release/bundle")。 2. 缓存服务在 job 容器里连不上: Failed to restore: getCacheEntry failed: connect ETIMEDOUT 172.18.0.2:37315 setup-node 的 cache: pnpm 每次要干等 4 分 39 秒才放弃,cargo 缓存那步也白等 26 秒。 先全部去掉(两个 job 每轮省约 10 分钟),文件头第 3 条写明了等缓存修好怎么加回来。 其余在真机上都是绿的:rustup 兜底、pnpm 12.11.2、Node 24.22.0、tsc、vite、 protocol 15 / cam-core 80 / src-tauri 30 个测试、tauri build(deb + AppImage)全过。
触发:push 到 main(只认 desktop/ 与 protocol/ 的改动)、v* tag、PR、手动。 产物:Linux deb + AppImage、Windows NSIS 安装包、macOS 通用 dmg,各自传 artifact。 几个不是随手写的点: - 三个平台都显式 --target / CARGO_BUILD_TARGET。desktop/.cargo/config.toml 里钉着 aarch64-apple-darwin,不覆盖的话 Linux/Windows 的 runner 会去编 macOS 的目标, 然后在依赖深处以 libc 找不到 MAP_FAILED 这类形式失败。 - protocol 的测试写 cargo +stable:protocol/ 没有自己的 rust-toolchain.toml,会被 根目录那个 `esp` 接住,而 CI 上没有那个工具链(espup 要下几百 MB)。 - Windows 与 macOS 两个 job 默认不跑(本仓库目前只有 Linux runner),要用仓库变量 ENABLE_WINDOWS / ENABLE_MACOS 打开;没有 runner 时它们只会一直排队。 - cargo 只缓存 registry、不缓存 target/:容器化的 runner 每次都是干净的,拉几 GB 的 target 缓存常常比重新编译还慢。 - 守门 job 先跑 tsc + vite build + protocol/core 的单元测试,三个构建都 needs 它。 本地(Windows)实测:同一条 pnpm tauri build --target x86_64-pc-windows-msvc --bundles nsis 真的编出了 src-tauri/target/x86_64-pc-windows-msvc/release/bundle/ nsis/cam-desktop_0.1.0_x64-setup.exe(2.97 MiB),也验证了 --target 确实盖住了 .cargo/config.toml;protocol 15 个测试、cam-core 80 个测试、tsc、vite build 都过; 三个 Cargo.lock 与 --locked 一致;workflow 本身过 actionlint(带 shellcheck)。 Linux 与 macOS 的打包只能在你们的 runner 上验,第一次跑完把日志贴回来。