* fix(ci): upstream Windows SDK validation support Port remaining Windows validation tooling from GitLab independently of the combined MXC runtime port. Preserve locked SDK dependencies and guard temporary launcher cleanup. Co-authored-by: Shailendra Singh <shailendras@nvidia.com> Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> * fix(ci): install native TypeScript dependencies before validation Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> --------- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> Co-authored-by: Shailendra Singh <shailendras@nvidia.com>
11 KiB
Windows MSVC Build Design
This page records the design decisions for the native Windows MSVC build lane. It provides the native build lane and validates the in-process MXC compute driver. It does not make Windows a Docker, Kubernetes, Podman, or VM runtime host.
Goals
- Compile the OpenShell gateway and CLI for
x86_64-pc-windows-msvcandaarch64-pc-windows-msvc. - Keep the Linux and macOS build paths unchanged.
- Preserve gateway configuration parsing for all existing compute driver names.
- Build and test the in-process MXC driver on supported Windows hosts.
- Use the ordinary in-process compute-driver composition path; MXC receives the
canonical sandbox policy through
DriverSandboxSpecand advertises that it reports runtime readiness. - Return clear unsupported errors when a Windows gateway is configured to use Docker, Kubernetes, Podman, or VM.
- Keep dedicated
windows:*validation tasks while allowing the repository-widepre-committask to delegate compiler-bearing Rust checks to the native Windows MSVC environment.
Non-Goals
- Do not support Docker Desktop, WSL, Hyper-V, Podman machine, Podman Desktop, Kubernetes, or VM-backed sandbox execution on Windows.
- Do not ship Windows standalone binaries for Docker, Kubernetes, Podman, or VM drivers.
- Do not implement named-pipe driver IPC, Windows services, MSI packaging, Credential Manager integration, or DPAPI integration in this lane.
Unsupported Driver Strategy
The gateway composition crate installs platform-specific registration stubs on Windows. These registrations preserve config-file selection and reject unsupported drivers with a clear error without depending on their runtime crates.
Each stub follows its corresponding compute-driver-* Cargo feature.
compute-driver-mxc independently links and registers MXC, so a gateway built
with only that feature has only the MXC registration. The default
in-tree-compute-drivers alias enables all five features and preserves the
existing MXC plus unsupported-driver registrations. The focused Windows
contract tasks cover default, protocol-only, MXC-only, Docker-stub-only, and
MXC plus Docker-stub compositions.
The Windows lane does not build, release, package, or smoke-test standalone driver binaries for Docker, Kubernetes, Podman, or VM. Those binaries are Linux or macOS deliverables only.
The Kubernetes Secrets and Vault packages are also excluded as top-level Windows workspace targets because their standalone driver binaries use Unix domain sockets. Their libraries remain in the gateway dependency graph, so the gateway's credential-driver configuration and in-process behavior still compile on Windows.
| Driver | Windows build behavior | Runtime behavior |
|---|---|---|
| Docker | Driver crate excluded; gateway registration stub retained. | Gateway construction returns unsupported. |
| Kubernetes | Driver crate excluded; gateway registration stub retained. | Gateway construction returns unsupported. |
| Podman | Driver crate excluded; gateway registration stub retained. | Gateway construction returns unsupported. |
| VM | Driver crate excluded; gateway registration stub retained. | Gateway construction returns unsupported. |
| MXC | Driver links into the native gateway and runs in Windows validation. | process_container is default-deny; grant-only isolation_session requires explicit configuration. |
This keeps Windows behavior explicit without carrying runtime dependencies or creating misleading Windows driver artifacts.
Mise Lane
The GitHub Actions workflow runs Clippy for the Windows-supported workspace and
e2e crates plus Rust tests for pull-request mirror branches labeled test:windows.
Merge queues do not run this workflow. On
pushes to main, a cache-seed job runs the same lint and test commands before a
dependent job builds the release binaries. Manual dispatches exercise the same
seed-then-build path. The binaries remain CI validation artifacts and are not
uploaded or published.
Each job restores and saves a dedicated Rust cache containing the Cargo registry and dependency build artifacts, including artifacts from failed runs. The seed job and pull-request job use the same Cargo target and sccache namespaces. The release build waits for the seed job, then restores its newly warmed cache rather than compiling concurrently from a cold cache.
Windows validation is exposed through tasks/windows.toml:
| Task | Purpose |
|---|---|
windows:check:x64 |
Check the x64 MSVC gateway/CLI build graph. |
windows:check:arm64 |
Check the ARM64 MSVC gateway/CLI build graph. |
windows:lint:x64 |
Run Clippy over the Windows-supported workspace for x64 MSVC. |
windows:lint:arm64 |
Run Clippy over the Windows-supported workspace for ARM64 MSVC. |
windows:build:x64 |
Build release x64 openshell-gateway.exe and openshell.exe. |
windows:build:arm64 |
Build release ARM64 openshell-gateway.exe and openshell.exe. |
windows:test:x64 |
Run native x64 workspace tests with the nextest CI profile and server test support, while excluding unsupported Windows packages as top-level test targets. |
windows:test:arm64 |
Run the same suite natively on ARM64. |
windows:test:unsupported:x64 |
Run focused gateway-composition tests for unsupported driver contracts. |
windows:test:unsupported:arm64 |
Run the same focused contracts natively on ARM64. |
windows:ci |
Run check, build, test, unsupported-contract tests, and artifact reporting. |
The Windows tasks call tasks/scripts/windows-msvc.ps1. The wrapper discovers
Visual Studio's VsDevCmd.bat with vswhere or by enumerating installed
release directories, validates the requested compiler and ARM64 Spectre
libraries, adds rustup MSVC targets, preserves an inherited RUSTC_WRAPPER
when the command is available, and keeps build artifacts under the normal
Cargo target tree. If the wrapper command is unavailable, it warns and clears
the setting so local builds continue without compiler caching.
On Windows, the generic rust:check, rust:lint, and test:rust tasks call
the same wrapper with the host-native MSVC target. The wrapper preserves the
Unix Cargo commands on Linux and macOS, excludes unsupported Windows runtime
packages, and runs the server test-support suite separately. Windows Clippy
continues to deny all warnings except unused imports, dead code, and unused
async functions caused by cfg-gated Windows stubs. Repository-wide pre-commit
skips only Linux-specific installer, build-environment shell-helper, and
packaging-asset tests; its
cross-platform Python, Markdown, license, and documentation checks still run.
Tracked Cargo lockfiles are checked natively through PowerShell. Deterministic
gateway parity uses Git for Windows Bash with temporary, checkout-scoped Python
launchers. The TypeScript SDK uses Windows protobuf plugin paths and x64 Biome
under emulation on ARM64, while its test binding follows Node's architecture
and the locked Rolldown version. Go tests retain race coverage wherever the
toolchain supports it; POSIX permission-bit checks are not Windows ACL tests.
Test tasks require the Rust target architecture to match the Windows host, so
an ARM64 test result is native coverage rather than x64 emulation coverage.
By default it enables bundled Z3 for reproducible Windows builds. z3-sys
builds Z3 from source and links it into the release binaries, so copying
openshell-gateway.exe and openshell.exe does not create an undeclared
libz3.dll runtime dependency. When Z3_LIBRARY_PATH_OVERRIDE points at a
directory containing libz3.lib, the wrapper uses that system Z3 instead and
requires Z3_SYS_Z3_HEADER to point at the full path to z3.h. Binaries built
against a dynamic system Z3 must be deployed with the matching libz3.dll.
GitHub Actions layers the Cargo target cache with sccache's GitHub Actions
backend. The target cache lets Cargo skip intact dependency builds; sccache
recovers cacheable Rust compiler outputs when source changes invalidate part of
that target tree. CI enables client-side mode and normalizes the checkout root
for stable compiler cache keys. The target-cache action runs its metadata step
with RUSTC_WRAPPER cleared so cache maintenance does not depend on sccache.
Hosted jobs use an isolated RUSTUP_HOME containing the pinned toolchain so
unused toolchains in runner images cannot change the target-cache restore key.
The lane uses mise run --skip-tools windows:* because Windows Rust comes from
rustup and linking comes from Visual Studio Build Tools. Mise orchestrates the
tasks; it does not own the Windows toolchain.
ARM64 validation requires the Visual Studio ARM64 MSVC tools, ARM64
Spectre-mitigated libraries, host-native Clang tools, CMake tools, and an
ARM64-capable Windows SDK. Clang provides libclang.dll for bindgen and
clang-cl.exe for ARM64 crypto dependencies. During x64-to-ARM64 check/build,
the wrapper discovers and adds the Visual Studio-bundled Ninja to PATH for
native dependencies. Bundled Z3 uses native MSVC cl.exe with the Visual
Studio generator, while the crypto crates select clang-cl. Artifact hashing
uses .NET SHA256 directly because module autoloading in the mise-launched
Windows PowerShell process is not guaranteed.
The wrapper defaults Cargo compilation to four jobs. Set
OPENSHELL_WINDOWS_BUILD_JOBS to a positive integer to override that limit.
A host-local mutex serializes wrapper-owned Cargo commands so concurrent
pre-commit tasks do not multiply the compiler process count.
The wrapper does not set CL or _CL_: those variables are also consumed by
clang-cl, where MSVC's /MP option can be interpreted as an input file and
break ARM64 crypto dependency builds.
CI Shape
The x64 GitHub Actions jobs run on windows-2025; native ARM64 jobs run on
windows-11-arm. Pull-request mirrors labeled test:windows execute the matching
architecture-specific tasks:
mise run --skip-tools windows:lint:<x64|arm64>
mise run --skip-tools windows:test:<x64|arm64>
Pushes to main and manual dispatches first seed the shared caches with those
same lint and test commands. Both seed and build jobs use job-level
continue-on-error: true, so Windows job failures do not fail the main/manual
workflow. Opt-in PR jobs still report failures normally. After the seed job
finishes, a separate job executes:
mise run --skip-tools windows:build:<x64|arm64>
The server test-support suite includes the unsupported-driver contract test, so CI does not run the focused test task a second time. The focused task remains available for local diagnosis.
The hosted workflow uses architecture-specific cache namespaces and does not cache Cargo-installed binaries.
The local aggregate windows:ci task can still cross-build ARM64 on an x64
host. Hosted tests use architecture-matched runners, so ARM64 test results are
native rather than emulated coverage.
Validation Contract
A successful Windows build report should include:
- x64 and ARM64
cargo checkstatus. - x64 and ARM64 release build status for
openshell-gateway.exeandopenshell.exe. - x64 test summary.
- Native ARM64 test summary when validation runs on an ARM64 host.
- Focused unsupported-driver contract test status.
- Artifact size and SHA256 for each Windows binary.
Warnings from Linux-only dead code are acceptable in the native Windows lane when they come from code paths intentionally disabled on Windows.