Skip to content

ci: cross-compile Windows tests on Linux and shard runs via nextest archives#443

Open
wan9chi wants to merge 5 commits into
mainfrom
claude/vigilant-carson-spmrkg
Open

ci: cross-compile Windows tests on Linux and shard runs via nextest archives#443
wan9chi wants to merge 5 commits into
mainfrom
claude/vigilant-carson-spmrkg

Conversation

@wan9chi

@wan9chi wan9chi commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Windows CI jobs previously compiled the whole workspace on slow windows-latest runners — six times over (5 e2e shards + 1 non-e2e shard). This PR moves all Windows compilation to a fast Linux runner and turns the Windows jobs into run-only shards:

  • New build-windows-tests job (Linux): cross-compiles every test binary for x86_64-pc-windows-msvc with cargo-xwin (clang-cl + lld-link against the xwin-fetched MSVC CRT/Windows SDK) and packs them into a portable cargo nextest archive, uploaded as a ~46 MB artifact.
    • cargo xwin env is eval'd before cargo nextest archive, so the plain cargo invocation nextest makes cross-compiles exactly like cargo xwin would. The repo rustflags from .cargo/config.toml are preserved (cargo-xwin merges them into CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS).
    • The llvm-tools rustup component supplies llvm-ar, from which cargo-xwin symlinks the MSVC-style llvm-lib/llvm-dlltool (and lld-link from rust-lld) — no system LLVM needed on the runner.
    • CXXFLAGS=-D_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH is Microsoft's documented escape hatch for the VS17 STL's minimum-Clang static assert; Detours is the only C++ in the workspace.
    • The unpacked MSVC CRT/Windows SDK (~10 min to fetch) is cached via actions/cache, keyed on the xwin manifest version.
  • Six test-windows shards: download the archive, then cargo-nextest nextest run --archive-file --workspace-remap . --partition count:N/6. No Rust toolchain, dev drive, or compilation on the Windows runners. Ignored (Node-dependent) tests run after setup-node, same as before. The Detours submodule is still checked out because fspy_detours_sys's bindings test runs bindgen at test time.
  • The e2e harness's VT_SHARD_INDEX/VT_SHARD_TOTAL self-sharding is removed — nextest's native partitioning replaces its only user (Windows CI), and it spreads e2e and non-e2e tests evenly instead of dedicating a whole shard to non-e2e.
  • fspy's oxlint test now resolves CARGO_MANIFEST_DIR at run time instead of env!(...): compile-time paths bake in the build machine's checkout, which breaks when the binary is built on Linux and executed on a Windows runner from a nextest archive.

Verified end to end: cross-compiled locally on Linux, validated the archive→--workspace-remap→run flow, and all six Windows shards run the cross-compiled tests green in this PR's CI (runs 27367734096, 27369662921).

Time improvement

Baseline is the old workflow's latest main run (27363778976, warm caches); the new numbers are this PR's warm-cache run (27369662921).

Old (6 Windows build+test jobs) New (1 Linux build + 6 run-only shards)
Windows-coverage wall clock 5m 14s (slowest job: windows-e2e-5, 5m00s) 3m 45s (build 1m12s → slowest shard 2m21s)
Per-Windows-job duration 1m45s – 5m00s 1m21s – 2m21s
windows-latest runner minutes 18m 56s 11m 30s (plus 1m12s on Linux)
Cold-cache worst case 6 × full MSVC build on Windows runners 1 × Linux cross-compile (12m41s measured, of which 9m40s was the now-cached SDK fetch)

Net: ~28% faster wall clock for Windows coverage with warm caches, ~40% fewer (2×-billed) Windows runner minutes, and the cold-cache cliff moves from six parallel Windows builds to a single cached-away Linux job. Windows shard times are also far more uniform since they no longer include toolchain setup, dev-drive creation, or compilation.

https://claude.ai/code/session_012vwVCFFfjepzPQGKWLPycf

claude added 5 commits June 11, 2026 17:43
…rchives

Windows CI jobs previously spent most of their wall-clock compiling the
workspace on slow windows-latest runners, six times over. Instead:

- A new build-windows-tests job cross-compiles all test binaries for
  x86_64-pc-windows-msvc on a Linux runner with cargo-xwin (clang-cl +
  lld-link against the xwin-fetched MSVC CRT/Windows SDK) and packs them
  into a portable `cargo nextest archive`, uploaded as an artifact.
- Six test-windows shards download the archive and only run tests via
  `cargo nextest run --archive-file --workspace-remap`, partitioned with
  nextest's native `--partition count:N/6` — no Rust toolchain, dev
  drive, or compilation on the Windows runners.
- The e2e harness's VT_SHARD_INDEX/VT_SHARD_TOTAL self-sharding is
  removed; nextest partitioning replaces its only user (Windows CI).
- fspy's oxlint test now resolves CARGO_MANIFEST_DIR at run time instead
  of `env!`, since compile-time paths bake in the build machine's
  checkout and break when the binary runs on another machine.

https://claude.ai/code/session_012vwVCFFfjepzPQGKWLPycf
…ners

The namespace runner image has no system LLVM; cc-rs failed to find
llvm-lib when archiving Detours. With the rustup llvm-tools component
installed, cargo-xwin symlinks llvm-lib/llvm-dlltool from the
toolchain's llvm-ar (and lld-link from rust-lld), verified locally with
system LLVM tools hidden.

https://claude.ai/code/session_012vwVCFFfjepzPQGKWLPycf
fspy_detours_sys's bindings test runs bindgen at test time against the
Detours submodule headers, so run-only shards still need the submodule.

https://claude.ai/code/session_012vwVCFFfjepzPQGKWLPycf
Downloading and unpacking the SDK took 9m40s of the build job's 12m41s;
the cross-compile itself took 45s. The unpacked SDK is immutable for a
given manifest version, so cache it keyed on the xwin major version.

https://claude.ai/code/session_012vwVCFFfjepzPQGKWLPycf
Empty commit to re-run CI now that the previous run saved the
cargo-xwin SDK cache.

https://claude.ai/code/session_012vwVCFFfjepzPQGKWLPycf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants