From 161522d24774aaac5ba3a766c2391c6653f401c5 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 12 Aug 2026 11:04:59 -0700 Subject: [PATCH 01/27] fix(ci): preserve Windows Rust build cache Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 3dda62238..9d0c2bcd8 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -16,6 +16,11 @@ jobs: targets: x86_64-pc-windows-msvc - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + env: + # mise exports RUSTC_WRAPPER=sccache, but this workflow intentionally + # does not install sccache. Keep rust-cache's cargo metadata calls + # independent of that unavailable wrapper so target artifacts save. + RUSTC_WRAPPER: "" with: shared-key: windows-msvc-x64 cache-targets: "true" @@ -41,6 +46,10 @@ jobs: targets: aarch64-pc-windows-msvc - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + env: + # Keep rust-cache's cargo metadata calls independent of the + # unavailable sccache wrapper exported by mise. + RUSTC_WRAPPER: "" with: shared-key: windows-msvc-arm64 cache-targets: "true" From 5e29a8db9c5f8db8cb1ae261f4dbc2061e66b2a1 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 12 Aug 2026 11:05:49 -0700 Subject: [PATCH 02/27] fix(ci): invalidate empty Windows caches Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 9d0c2bcd8..6415eb621 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -22,7 +22,9 @@ jobs: # independent of that unavailable wrapper so target artifacts save. RUSTC_WRAPPER: "" with: - shared-key: windows-msvc-x64 + # v2 invalidates the empty archive produced while cargo metadata + # could not run without sccache. + shared-key: windows-msvc-x64-v2 cache-targets: "true" cache-on-failure: "true" cache-bin: "false" @@ -51,7 +53,7 @@ jobs: # unavailable sccache wrapper exported by mise. RUSTC_WRAPPER: "" with: - shared-key: windows-msvc-arm64 + shared-key: windows-msvc-arm64-v2 cache-targets: "true" cache-on-failure: "true" cache-bin: "false" From c7d5b5c8d8ab2b60f6e3de27d7bd02129659aa11 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 12 Aug 2026 16:18:51 -0700 Subject: [PATCH 03/27] perf(ci): cache Windows builds with sccache Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 13 ++++--- .../build-openshell-mxc-windows/reference.md | 9 +++-- .github/workflows/windows-msvc.yml | 37 +++++++++++-------- architecture/windows-msvc-build.md | 26 +++++++------ tasks/scripts/windows-msvc.ps1 | 11 +++++- 5 files changed, 59 insertions(+), 37 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index d61fc555e..fe8bcfe20 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -134,7 +134,7 @@ from this skill. | `Z3_LIBRARY_PATH_OVERRIDE` | unset | Directory containing an x64 system `libz3.lib`; not valid for ARM64. | | `Z3_SYS_Z3_HEADER` | unset | Full `z3.h` path required with a system Z3 library. | | `Z3_SYS_BUNDLED_DIR_OVERRIDE` | pinned source cached under `CARGO_TARGET_DIR` when explicit, otherwise `%LOCALAPPDATA%\OpenShell\cache\z3` | Use an existing Z3 source tree containing `src/api/z3.h`; otherwise the wrapper fetches the pinned revision through Git and sets this automatically. | -| `RUSTC_WRAPPER` | cleared by wrapper | The wrapper clears inherited values because `--skip-tools` does not provision `sccache`. | +| `RUSTC_WRAPPER` | used when available, otherwise cleared | The wrapper resolves the configured executable before entering `cmd.exe`; local `--skip-tools` runs continue without it when unavailable. | Legacy fork variables such as `OPENSHELL_UPSTREAM`, `OPENSHELL_MXC_FORK_DIR`, and `OPENSHELL_MXC_FORK_BRANCH` are no longer part @@ -187,10 +187,11 @@ order: 6. Focused unsupported-driver contract tests. 7. Artifact reporting. -The GitHub Actions jobs use architecture-specific `Swatinem/rust-cache` -entries for the Cargo registry and dependency target artifacts. Failed runs -also save their usable dependency artifacts. The workflow remains manually -dispatched until cache-hit runtimes justify restoring automatic triggers. +The GitHub Actions jobs use architecture-specific GitHub Actions sccache +namespaces for compiler outputs and `Swatinem/rust-cache` entries for Cargo +registry data. They do not transfer Cargo target directories. Failed runs also +save usable cache data. The workflow remains manually dispatched until +cache-hit runtimes justify restoring automatic triggers. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the @@ -207,7 +208,7 @@ commands above on an ARM64 host. The repository-wide `mise run pre-commit` task is also supported on Windows. Its Rust check, Clippy, and test dependencies enter the same MSVC environment -for the native host target and clear inherited `RUSTC_WRAPPER`. Linux glibc +for the native host target and use an available inherited `RUSTC_WRAPPER`. Linux glibc installer tests and Linux service/RPM packaging-asset tests skip explicitly; the Linux build-environment shell-helper test also skips; cross-platform checks continue to run. The blocking Windows Clippy pass excludes unsupported diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index 4a5f2668a..d7f37b327 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | Manual GitHub Actions x64 job and disabled ARM64 scaffold, each with an architecture-specific Rust dependency cache. | +| `.github/workflows/windows-msvc.yml` | Manual GitHub Actions x64 job and disabled ARM64 scaffold, each with architecture-specific sccache and Cargo registry caches. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands @@ -46,9 +46,10 @@ if ($arch -eq [System.Runtime.InteropServices.Architecture]::Arm64) { The native test tasks reject a target that does not match the host architecture. Do not report x64 compatibility-under-emulation coverage from an ARM64 run. -The wrapper adds missing rustup targets and clears inherited -`RUSTC_WRAPPER`. It does not install Visual Studio, Rust, Docker, Kubernetes, -Podman, WSL, Hyper-V, or VM tooling. +The wrapper adds missing rustup targets and uses an inherited `RUSTC_WRAPPER` +when its executable is available. It clears unavailable wrappers so local +`--skip-tools` runs still work. It does not install Visual Studio, Rust, Docker, +Kubernetes, Podman, WSL, Hyper-V, or VM tooling. On Windows, `mise run pre-commit` routes `rust:check`, `rust:lint`, and `test:rust` through this wrapper for the host-native target. The shared task diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 6415eb621..e60f4a5ce 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -4,58 +4,65 @@ on: jobs: x64: runs-on: windows-2025 + env: + SCCACHE_GHA_ENABLED: "true" + SCCACHE_GHA_VERSION: windows-msvc-x64-v1 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 with: install: false experimental: true + - name: Configure GHA sccache backend + uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - uses: dtolnay/rust-toolchain@master with: toolchain: "1.95.0" targets: x86_64-pc-windows-msvc - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - env: - # mise exports RUSTC_WRAPPER=sccache, but this workflow intentionally - # does not install sccache. Keep rust-cache's cargo metadata calls - # independent of that unavailable wrapper so target artifacts save. - RUSTC_WRAPPER: "" with: - # v2 invalidates the empty archive produced while cargo metadata - # could not run without sccache. - shared-key: windows-msvc-x64-v2 - cache-targets: "true" + # Keep registry downloads, but let sccache measure compiler reuse + # without a restored target directory masking its effect. + shared-key: windows-msvc-x64-sccache-v1 + cache-targets: "false" cache-on-failure: "true" cache-bin: "false" - run: mise run --skip-tools windows:check:x64 - run: mise run --skip-tools windows:build:x64 - run: mise run --skip-tools windows:test:x64 - run: mise run --skip-tools windows:test:unsupported:x64 + - name: sccache stats + if: always() + run: sccache --show-stats arm64: # TODO: provision a windows-arm64 self-hosted runner runs-on: [self-hosted, windows-arm64] if: false # flip to true once the runner is online + env: + SCCACHE_GHA_ENABLED: "true" + SCCACHE_GHA_VERSION: windows-msvc-arm64-v1 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 with: install: false experimental: true + - name: Configure GHA sccache backend + uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - uses: dtolnay/rust-toolchain@master with: toolchain: "1.95.0" targets: aarch64-pc-windows-msvc - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - env: - # Keep rust-cache's cargo metadata calls independent of the - # unavailable sccache wrapper exported by mise. - RUSTC_WRAPPER: "" with: - shared-key: windows-msvc-arm64-v2 - cache-targets: "true" + shared-key: windows-msvc-arm64-sccache-v1 + cache-targets: "false" cache-on-failure: "true" cache-bin: "false" - run: mise run --skip-tools windows:check:arm64 - run: mise run --skip-tools windows:build:arm64 + - name: sccache stats + if: always() + run: sccache --show-stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index df875bc8e..0eeddb11f 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -48,11 +48,13 @@ creating misleading Windows driver artifacts. ## Mise Lane -The GitHub Actions workflow is manually dispatched. Each architecture restores -and saves a dedicated Rust cache containing the Cargo registry and dependency -build artifacts, including artifacts from failed runs. Keep the workflow manual -until cache-hit runtimes demonstrate that it is suitable for pull requests and -merges to `main`. +The GitHub Actions workflow is manually dispatched. Each architecture uses a +dedicated GitHub Actions sccache namespace for compiler outputs and a separate +Rust cache for Cargo registry data, including data from failed runs. The target +directory is not transferred because sccache provides reusable compiler outputs +without a multi-gigabyte target archive. Keep the workflow manual until +cache-hit runtimes demonstrate that it is suitable for pull requests and merges +to `main`. Windows validation is exposed through `tasks/windows.toml`: @@ -71,8 +73,9 @@ Windows validation is exposed through `tasks/windows.toml`: 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, clears inherited `RUSTC_WRAPPER`, and -keeps build artifacts under the normal Cargo target tree. +libraries, adds rustup MSVC targets, uses an inherited `RUSTC_WRAPPER` when its +executable is available, and otherwise clears it before invoking Cargo. Build +artifacts remain under the normal Cargo target tree. 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 @@ -134,10 +137,11 @@ mise run --skip-tools windows:test:x64 mise run --skip-tools windows:test:unsupported:x64 ``` -The cache is partitioned by architecture so incompatible x64 and ARM64 target -artifacts cannot collide. It does not cache Cargo-installed binaries, which -also keeps the disabled self-hosted ARM64 scaffold from modifying persistent -runner tooling. +The sccache and Cargo registry caches are partitioned by architecture so +incompatible x64 and ARM64 artifacts cannot collide. The workflow does not +cache Cargo target directories or Cargo-installed binaries, which also keeps +the disabled self-hosted ARM64 scaffold from modifying persistent runner +tooling. The local aggregate `windows:ci` task cross-builds ARM64 on an x64 host. The GitHub x64 job currently runs only the x64 tasks, and native ARM64 tests remain diff --git a/tasks/scripts/windows-msvc.ps1 b/tasks/scripts/windows-msvc.ps1 index cf1b4c868..bf5722b2c 100644 --- a/tasks/scripts/windows-msvc.ps1 +++ b/tasks/scripts/windows-msvc.ps1 @@ -516,11 +516,20 @@ function Invoke-VsCargo { $targetArch = Get-VsTargetArch $RustTarget $hostArch = Get-HostArch $logPath = Join-Path $LogDir $LogName + $rustcWrapper = "" + if (-not [string]::IsNullOrWhiteSpace($env:RUSTC_WRAPPER)) { + $wrapperCommand = Get-Command $env:RUSTC_WRAPPER -ErrorAction SilentlyContinue + if ($wrapperCommand) { + $rustcWrapper = $wrapperCommand.Source + } else { + Write-Warning "RUSTC_WRAPPER '$env:RUSTC_WRAPPER' was not found; continuing without it." + } + } $environmentSetup = @( "set `"CARGO_TARGET_DIR=$TargetDir`"", "set `"CARGO_BUILD_JOBS=$WindowsBuildJobs`"", "set `"CARGO_INCREMENTAL=0`"", - "set `"RUSTC_WRAPPER=`"" + "set `"RUSTC_WRAPPER=$rustcWrapper`"" ) if ($hostArch -eq "amd64" -and $RustTarget -eq "aarch64-pc-windows-msvc") { # Let cmake-rs select MSVC cl.exe for bundled Z3. AWS-LC selects From 1376f4174d19252def22636515b6abd8d8a36011 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 12 Aug 2026 18:51:21 -0700 Subject: [PATCH 04/27] ci(windows): restore target directory caching Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 13 +++---- .../build-openshell-mxc-windows/reference.md | 9 ++--- .github/workflows/windows-msvc.yml | 37 ++++++++----------- architecture/windows-msvc-build.md | 26 ++++++------- tasks/scripts/windows-msvc.ps1 | 11 +----- 5 files changed, 37 insertions(+), 59 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index fe8bcfe20..d61fc555e 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -134,7 +134,7 @@ from this skill. | `Z3_LIBRARY_PATH_OVERRIDE` | unset | Directory containing an x64 system `libz3.lib`; not valid for ARM64. | | `Z3_SYS_Z3_HEADER` | unset | Full `z3.h` path required with a system Z3 library. | | `Z3_SYS_BUNDLED_DIR_OVERRIDE` | pinned source cached under `CARGO_TARGET_DIR` when explicit, otherwise `%LOCALAPPDATA%\OpenShell\cache\z3` | Use an existing Z3 source tree containing `src/api/z3.h`; otherwise the wrapper fetches the pinned revision through Git and sets this automatically. | -| `RUSTC_WRAPPER` | used when available, otherwise cleared | The wrapper resolves the configured executable before entering `cmd.exe`; local `--skip-tools` runs continue without it when unavailable. | +| `RUSTC_WRAPPER` | cleared by wrapper | The wrapper clears inherited values because `--skip-tools` does not provision `sccache`. | Legacy fork variables such as `OPENSHELL_UPSTREAM`, `OPENSHELL_MXC_FORK_DIR`, and `OPENSHELL_MXC_FORK_BRANCH` are no longer part @@ -187,11 +187,10 @@ order: 6. Focused unsupported-driver contract tests. 7. Artifact reporting. -The GitHub Actions jobs use architecture-specific GitHub Actions sccache -namespaces for compiler outputs and `Swatinem/rust-cache` entries for Cargo -registry data. They do not transfer Cargo target directories. Failed runs also -save usable cache data. The workflow remains manually dispatched until -cache-hit runtimes justify restoring automatic triggers. +The GitHub Actions jobs use architecture-specific `Swatinem/rust-cache` +entries for the Cargo registry and dependency target artifacts. Failed runs +also save their usable dependency artifacts. The workflow remains manually +dispatched until cache-hit runtimes justify restoring automatic triggers. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the @@ -208,7 +207,7 @@ commands above on an ARM64 host. The repository-wide `mise run pre-commit` task is also supported on Windows. Its Rust check, Clippy, and test dependencies enter the same MSVC environment -for the native host target and use an available inherited `RUSTC_WRAPPER`. Linux glibc +for the native host target and clear inherited `RUSTC_WRAPPER`. Linux glibc installer tests and Linux service/RPM packaging-asset tests skip explicitly; the Linux build-environment shell-helper test also skips; cross-platform checks continue to run. The blocking Windows Clippy pass excludes unsupported diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index d7f37b327..4a5f2668a 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | Manual GitHub Actions x64 job and disabled ARM64 scaffold, each with architecture-specific sccache and Cargo registry caches. | +| `.github/workflows/windows-msvc.yml` | Manual GitHub Actions x64 job and disabled ARM64 scaffold, each with an architecture-specific Rust dependency cache. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands @@ -46,10 +46,9 @@ if ($arch -eq [System.Runtime.InteropServices.Architecture]::Arm64) { The native test tasks reject a target that does not match the host architecture. Do not report x64 compatibility-under-emulation coverage from an ARM64 run. -The wrapper adds missing rustup targets and uses an inherited `RUSTC_WRAPPER` -when its executable is available. It clears unavailable wrappers so local -`--skip-tools` runs still work. It does not install Visual Studio, Rust, Docker, -Kubernetes, Podman, WSL, Hyper-V, or VM tooling. +The wrapper adds missing rustup targets and clears inherited +`RUSTC_WRAPPER`. It does not install Visual Studio, Rust, Docker, Kubernetes, +Podman, WSL, Hyper-V, or VM tooling. On Windows, `mise run pre-commit` routes `rust:check`, `rust:lint`, and `test:rust` through this wrapper for the host-native target. The shared task diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index e60f4a5ce..6415eb621 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -4,65 +4,58 @@ on: jobs: x64: runs-on: windows-2025 - env: - SCCACHE_GHA_ENABLED: "true" - SCCACHE_GHA_VERSION: windows-msvc-x64-v1 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 with: install: false experimental: true - - name: Configure GHA sccache backend - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - uses: dtolnay/rust-toolchain@master with: toolchain: "1.95.0" targets: x86_64-pc-windows-msvc - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + env: + # mise exports RUSTC_WRAPPER=sccache, but this workflow intentionally + # does not install sccache. Keep rust-cache's cargo metadata calls + # independent of that unavailable wrapper so target artifacts save. + RUSTC_WRAPPER: "" with: - # Keep registry downloads, but let sccache measure compiler reuse - # without a restored target directory masking its effect. - shared-key: windows-msvc-x64-sccache-v1 - cache-targets: "false" + # v2 invalidates the empty archive produced while cargo metadata + # could not run without sccache. + shared-key: windows-msvc-x64-v2 + cache-targets: "true" cache-on-failure: "true" cache-bin: "false" - run: mise run --skip-tools windows:check:x64 - run: mise run --skip-tools windows:build:x64 - run: mise run --skip-tools windows:test:x64 - run: mise run --skip-tools windows:test:unsupported:x64 - - name: sccache stats - if: always() - run: sccache --show-stats arm64: # TODO: provision a windows-arm64 self-hosted runner runs-on: [self-hosted, windows-arm64] if: false # flip to true once the runner is online - env: - SCCACHE_GHA_ENABLED: "true" - SCCACHE_GHA_VERSION: windows-msvc-arm64-v1 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 with: install: false experimental: true - - name: Configure GHA sccache backend - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - uses: dtolnay/rust-toolchain@master with: toolchain: "1.95.0" targets: aarch64-pc-windows-msvc - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + env: + # Keep rust-cache's cargo metadata calls independent of the + # unavailable sccache wrapper exported by mise. + RUSTC_WRAPPER: "" with: - shared-key: windows-msvc-arm64-sccache-v1 - cache-targets: "false" + shared-key: windows-msvc-arm64-v2 + cache-targets: "true" cache-on-failure: "true" cache-bin: "false" - run: mise run --skip-tools windows:check:arm64 - run: mise run --skip-tools windows:build:arm64 - - name: sccache stats - if: always() - run: sccache --show-stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index 0eeddb11f..df875bc8e 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -48,13 +48,11 @@ creating misleading Windows driver artifacts. ## Mise Lane -The GitHub Actions workflow is manually dispatched. Each architecture uses a -dedicated GitHub Actions sccache namespace for compiler outputs and a separate -Rust cache for Cargo registry data, including data from failed runs. The target -directory is not transferred because sccache provides reusable compiler outputs -without a multi-gigabyte target archive. Keep the workflow manual until -cache-hit runtimes demonstrate that it is suitable for pull requests and merges -to `main`. +The GitHub Actions workflow is manually dispatched. Each architecture restores +and saves a dedicated Rust cache containing the Cargo registry and dependency +build artifacts, including artifacts from failed runs. Keep the workflow manual +until cache-hit runtimes demonstrate that it is suitable for pull requests and +merges to `main`. Windows validation is exposed through `tasks/windows.toml`: @@ -73,9 +71,8 @@ Windows validation is exposed through `tasks/windows.toml`: 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, uses an inherited `RUSTC_WRAPPER` when its -executable is available, and otherwise clears it before invoking Cargo. Build -artifacts remain under the normal Cargo target tree. +libraries, adds rustup MSVC targets, clears inherited `RUSTC_WRAPPER`, and +keeps build artifacts under the normal Cargo target tree. 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 @@ -137,11 +134,10 @@ mise run --skip-tools windows:test:x64 mise run --skip-tools windows:test:unsupported:x64 ``` -The sccache and Cargo registry caches are partitioned by architecture so -incompatible x64 and ARM64 artifacts cannot collide. The workflow does not -cache Cargo target directories or Cargo-installed binaries, which also keeps -the disabled self-hosted ARM64 scaffold from modifying persistent runner -tooling. +The cache is partitioned by architecture so incompatible x64 and ARM64 target +artifacts cannot collide. It does not cache Cargo-installed binaries, which +also keeps the disabled self-hosted ARM64 scaffold from modifying persistent +runner tooling. The local aggregate `windows:ci` task cross-builds ARM64 on an x64 host. The GitHub x64 job currently runs only the x64 tasks, and native ARM64 tests remain diff --git a/tasks/scripts/windows-msvc.ps1 b/tasks/scripts/windows-msvc.ps1 index bf5722b2c..cf1b4c868 100644 --- a/tasks/scripts/windows-msvc.ps1 +++ b/tasks/scripts/windows-msvc.ps1 @@ -516,20 +516,11 @@ function Invoke-VsCargo { $targetArch = Get-VsTargetArch $RustTarget $hostArch = Get-HostArch $logPath = Join-Path $LogDir $LogName - $rustcWrapper = "" - if (-not [string]::IsNullOrWhiteSpace($env:RUSTC_WRAPPER)) { - $wrapperCommand = Get-Command $env:RUSTC_WRAPPER -ErrorAction SilentlyContinue - if ($wrapperCommand) { - $rustcWrapper = $wrapperCommand.Source - } else { - Write-Warning "RUSTC_WRAPPER '$env:RUSTC_WRAPPER' was not found; continuing without it." - } - } $environmentSetup = @( "set `"CARGO_TARGET_DIR=$TargetDir`"", "set `"CARGO_BUILD_JOBS=$WindowsBuildJobs`"", "set `"CARGO_INCREMENTAL=0`"", - "set `"RUSTC_WRAPPER=$rustcWrapper`"" + "set `"RUSTC_WRAPPER=`"" ) if ($hostArch -eq "amd64" -and $RustTarget -eq "aarch64-pc-windows-msvc") { # Let cmake-rs select MSVC cl.exe for bundled Z3. AWS-LC selects From 685845724a0a6983367a29b3f9b5e81a9fd665bc Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 09:53:10 -0700 Subject: [PATCH 05/27] perf(ci): use prebuilt Z3 on Windows Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 29 ++-- .../build-openshell-mxc-windows/reference.md | 9 +- .github/workflows/windows-msvc.yml | 11 +- Cargo.lock | 101 +++++++++++++ architecture/windows-msvc-build.md | 32 ++-- crates/openshell-prover/Cargo.toml | 1 + crates/openshell-server/Cargo.toml | 1 + tasks/scripts/windows-msvc.ps1 | 137 ++---------------- 8 files changed, 151 insertions(+), 170 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index d61fc555e..fe6ea4ea3 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -113,7 +113,7 @@ The lane targets a Windows host with Visual Studio Build Tools and rustup. | Visual C++ ARM64 tools | `vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.ARM64 -property installationPath` | Required for native ARM64 check, build, and tests and for x64-to-ARM64 check/build. Tests always require a native runner. | | Visual C++ ARM64 Spectre-mitigated libraries | `vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre -property installationPath` | Required by `regorus` through `msvc_spectre_libs`; the build fails when the selected MSVC toolset lacks `lib\spectre\arm64`. | | Visual C++ Clang tools | `vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Llvm.Clang -property installationPath` | Provides host-native `libclang.dll` for `bindgen` and `clang-cl.exe` for ARM64 crypto dependencies such as `ring` and `aws-lc-sys`. On ARM64, the wrapper uses `VC\Tools\Llvm\Arm64\bin`. | -| Visual C++ CMake tools | `vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.CMake.Project -property installationPath` | Provides CMake and Ninja. The x64-to-ARM64 path adds Ninja to `PATH` for native dependencies but keeps bundled Z3 on CMake's Visual Studio ARM64 generator with native MSVC `cl.exe`. | +| Visual C++ CMake tools | `vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.CMake.Project -property installationPath` | Provides CMake and Ninja for native dependencies. The x64-to-ARM64 path adds Ninja to `PATH`; Z3 uses an architecture-specific prebuilt release. | | Windows SDK | `where.exe rc.exe` from a Developer PowerShell | Install an SDK containing target libraries and ARM64 tools. | | Rust via rustup | `rustc --version` | Add each target being validated: `x86_64-pc-windows-msvc` and/or `aarch64-pc-windows-msvc`. The wrapper also adds the selected target. | | mise | `mise --version` | Used as a task runner only. | @@ -133,7 +133,8 @@ from this skill. | `CARGO_TARGET_DIR` | `target` under repo root | Override Cargo output location. Use a short absolute path when x64-to-ARM64 builds approach Windows path-length limits. | | `Z3_LIBRARY_PATH_OVERRIDE` | unset | Directory containing an x64 system `libz3.lib`; not valid for ARM64. | | `Z3_SYS_Z3_HEADER` | unset | Full `z3.h` path required with a system Z3 library. | -| `Z3_SYS_BUNDLED_DIR_OVERRIDE` | pinned source cached under `CARGO_TARGET_DIR` when explicit, otherwise `%LOCALAPPDATA%\OpenShell\cache\z3` | Use an existing Z3 source tree containing `src/api/z3.h`; otherwise the wrapper fetches the pinned revision through Git and sets this automatically. | +| `Z3_SYS_Z3_VERSION` | `4.16.0` | Pinned official prebuilt Z3 release selected by the wrapper. | +| `READ_ONLY_GITHUB_TOKEN` | unset | Optional token for the Z3 release lookup; GitHub Actions supplies `github.token`. | | `RUSTC_WRAPPER` | cleared by wrapper | The wrapper clears inherited values because `--skip-tools` does not provision `sccache`. | Legacy fork variables such as `OPENSHELL_UPSTREAM`, @@ -195,9 +196,7 @@ dispatched until cache-hit runtimes justify restoring automatic triggers. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the ARM64 compiler and Spectre-mitigated libraries, lets ARM64 crypto crates select -`clang-cl`, and keeps bundled Z3 on native MSVC `cl.exe` with CMake's Visual -Studio ARM64 generator. Z3 does not use Ninja because `z3-sys 0.10.9` passes -the MSBuild-only `-m` argument. +`clang-cl`, and downloads the official prebuilt ARM64 Z3 static library. On ARM64 hosts, validate the native ARM64 check, build, and test path. The wrapper rejects test targets that do not match the host architecture, so x64 @@ -291,19 +290,13 @@ Useful log files: | `test-x86_64-pc-windows-msvc-unsupported-*.log` | Focused unsupported-driver contract output. | | `test-aarch64-pc-windows-msvc-unsupported-*.log` | Focused native ARM64 contract output. | -The first bundled-Z3 check or test can spend several minutes in CMake/MSBuild -without much console output because Cargo output is redirected to the log. Look -for native `MSBuild.exe` workers before treating the process as stalled. The -wrapper fetches the pinned Z3 source through Git before Cargo starts. It caches -under an explicitly configured `CARGO_TARGET_DIR`, or under the current user's -local application data directory when Cargo uses its default target tree. -Concurrent commands publish the validated source through an atomic directory -rename, so x64 and ARM64 validation can share the cache safely. The wrapper does -not rely on the rate-limited GitHub Contents API used by `z3-sys`. A failed -fetch reports the partial checkout path for diagnosis. The artifact report -computes SHA256 through .NET directly and does not rely on the -`Get-FileHash` module being available inside the mise-launched Windows -PowerShell process. +The first check downloads the pinned official Z3 archive for the target +architecture through `z3-sys`. GitHub Actions authenticates the lookup with its +read-only workflow token; local users can set `READ_ONLY_GITHUB_TOKEN` if an +unauthenticated lookup is rate-limited. Cargo stores the extracted library in +its target tree, so the Windows target cache reuses it. The artifact report +computes SHA256 through .NET directly and does not rely on the `Get-FileHash` +module being available inside the mise-launched Windows PowerShell process. ## Common Fix Patterns diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index 4a5f2668a..2514c2b0d 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -67,11 +67,10 @@ file. For ARM64, verify the Visual Studio instance contains the ARM64 MSVC tools, ARM64 Spectre-mitigated libraries, Clang tools, CMake tools, and a Windows SDK. Clang supplies host-native `libclang.dll` for `bindgen` and `clang-cl.exe` for -ARM64 crypto dependencies such as `ring` and `aws-lc-sys`. Native ARM64 uses -the normal bundled-Z3 CMake path. An x64-to-ARM64 check/build discovers and -adds host-native Ninja to `PATH`, while the crypto crates select `clang-cl`. -Bundled Z3 uses CMake's Visual Studio ARM64 generator with native MSVC `cl.exe` -because `z3-sys 0.10.9` passes the MSBuild-only `-m` argument. Use a short +ARM64 crypto dependencies such as `ring` and `aws-lc-sys`. Native and +x64-to-ARM64 builds use the official prebuilt Z3 4.16.0 static library for the +target architecture. An x64-to-ARM64 check/build discovers and adds host-native +Ninja to `PATH`, while the crypto crates select `clang-cl`. Use a short `CARGO_TARGET_DIR` if Windows path-length limits are reached. ## Unsupported Driver Rules diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 6415eb621..8419ce74a 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -4,6 +4,8 @@ on: jobs: x64: runs-on: windows-2025 + env: + READ_ONLY_GITHUB_TOKEN: ${{ github.token }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 @@ -22,9 +24,8 @@ jobs: # independent of that unavailable wrapper so target artifacts save. RUSTC_WRAPPER: "" with: - # v2 invalidates the empty archive produced while cargo metadata - # could not run without sccache. - shared-key: windows-msvc-x64-v2 + # Keep the prebuilt-Z3 experiment isolated from earlier target caches. + shared-key: windows-msvc-x64-prebuilt-z3-v1 cache-targets: "true" cache-on-failure: "true" cache-bin: "false" @@ -36,6 +37,8 @@ jobs: # TODO: provision a windows-arm64 self-hosted runner runs-on: [self-hosted, windows-arm64] if: false # flip to true once the runner is online + env: + READ_ONLY_GITHUB_TOKEN: ${{ github.token }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 @@ -53,7 +56,7 @@ jobs: # unavailable sccache wrapper exported by mise. RUSTC_WRAPPER: "" with: - shared-key: windows-msvc-arm64-v2 + shared-key: windows-msvc-arm64-prebuilt-z3-v1 cache-targets: "true" cache-on-failure: "true" cache-bin: "false" diff --git a/Cargo.lock b/Cargo.lock index c30f89091..37d520264 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -879,6 +879,15 @@ dependencies = [ "either", ] +[[package]] +name = "bzip2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" +dependencies = [ + "libbz2-rs-sys", +] + [[package]] name = "capctl" version = "0.2.4" @@ -1134,6 +1143,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + [[package]] name = "core-foundation" version = "0.10.1" @@ -1432,6 +1447,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +[[package]] +name = "deflate64" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" + [[package]] name = "delegate" version = "0.13.5" @@ -1574,6 +1595,7 @@ dependencies = [ "const-oid 0.10.2", "crypto-common 0.2.2", "ctutils", + "zeroize", ] [[package]] @@ -1806,6 +1828,7 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -2411,6 +2434,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tower-service", + "webpki-roots", ] [[package]] @@ -3077,6 +3101,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +[[package]] +name = "libbz2-rs-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" + [[package]] name = "libc" version = "0.2.189" @@ -3180,6 +3210,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lzma-rust2" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca93e534d1142d1d0dcca6d25fe302508a5dfb40b302802904577725ea0b695b" +dependencies = [ + "sha2 0.11.0", +] + [[package]] name = "matchers" version = "0.2.0" @@ -4821,6 +4860,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppmd-rust" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -5377,6 +5422,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", ] [[package]] @@ -6869,6 +6915,7 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", + "js-sys", "num-conv", "powerfmt", "serde_core", @@ -7383,6 +7430,12 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typenum" version = "1.20.1" @@ -8446,7 +8499,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c18b0a91a13522d21b3414847667de2b2056a721a3edcb5b6ee6858352d58db4" dependencies = [ "pkg-config", + "reqwest 0.12.28", + "serde_json", "z3-src", + "zip", ] [[package]] @@ -8543,12 +8599,57 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "zip" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" +dependencies = [ + "aes", + "bzip2", + "constant_time_eq", + "crc32fast", + "deflate64", + "flate2", + "getrandom 0.4.2", + "hmac 0.13.0", + "indexmap", + "lzma-rust2", + "memchr", + "pbkdf2", + "ppmd-rust", + "sha1 0.11.0", + "time", + "typed-path", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zlib-rs" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5" + [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + [[package]] name = "zstd" version = "0.13.3" diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index df875bc8e..ae0141359 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -84,20 +84,16 @@ packaging-asset tests; its cross-platform Python, Markdown, license, and documentation checks still run. 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. When +By default it enables the `z3-sys` prebuilt-release feature and pins Z3 4.16.0. +On a clean target directory, `z3-sys` downloads the official static library for +the selected Windows architecture instead of compiling Z3 through +CMake/MSBuild. GitHub Actions supplies its read-only workflow token for the +release lookup, and the Cargo target cache preserves the extracted library for +subsequent runs. 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`. For bundled builds, the wrapper fetches the Z3 source -revision pinned by `z3-sys` through Git and sets -`Z3_SYS_BUNDLED_DIR_OVERRIDE`. When `CARGO_TARGET_DIR` is explicit, the wrapper -uses it for the source cache. Otherwise, it caches under the current user's -local application data directory, outside the checkout. Publishing uses an -atomic directory rename so concurrent x64 and ARM64 commands can share the -cache safely. This keeps downloaded sources outside the checkout by default and -avoids the unauthenticated GitHub API lookup in the `z3-sys` build script, which -can fail with HTTP 403 when a shared runner or developer network exhausts its -API rate limit. An explicitly set `Z3_SYS_BUNDLED_DIR_OVERRIDE` remains -supported and must contain `src/api/z3.h`. +the full path to `z3.h`. Local clean builds use the unauthenticated GitHub API +unless `READ_ONLY_GITHUB_TOKEN` is set. 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 @@ -108,17 +104,15 @@ 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. It lets `cmake-rs` select the Visual Studio ARM64 -generator with native MSVC `cl.exe` for bundled Z3 so the Z3 build does not -inherit the crypto crates' compiler requirement. Z3 stays on the Visual Studio -generator because `z3-sys` emits an MSBuild-only `-m` argument that Ninja -rejects. Artifact hashing uses .NET SHA256 directly because module autoloading -in the mise-launched Windows PowerShell process is not guaranteed. +native dependencies. Z3 uses the official prebuilt ARM64 static library, so it +does not inherit compiler settings from those native dependencies. 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 process count while bundled Z3 compiles. +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. diff --git a/crates/openshell-prover/Cargo.toml b/crates/openshell-prover/Cargo.toml index ee815f3a3..b620280e4 100644 --- a/crates/openshell-prover/Cargo.toml +++ b/crates/openshell-prover/Cargo.toml @@ -12,6 +12,7 @@ repository.workspace = true [features] bundled-z3 = ["z3/bundled"] +prebuilt-z3 = ["z3/gh-release"] [dependencies] z3 = { workspace = true } diff --git a/crates/openshell-server/Cargo.toml b/crates/openshell-server/Cargo.toml index 772590d1b..bbf772e7f 100644 --- a/crates/openshell-server/Cargo.toml +++ b/crates/openshell-server/Cargo.toml @@ -126,6 +126,7 @@ default = ["telemetry"] ## that contains no telemetry endpoint, HTTP client, or emission code. telemetry = ["openshell-core/telemetry"] bundled-z3 = ["openshell-prover/bundled-z3"] +prebuilt-z3 = ["openshell-prover/prebuilt-z3"] test-support = [] [dev-dependencies] diff --git a/tasks/scripts/windows-msvc.ps1 b/tasks/scripts/windows-msvc.ps1 index cf1b4c868..59ec2b412 100644 --- a/tasks/scripts/windows-msvc.ps1 +++ b/tasks/scripts/windows-msvc.ps1 @@ -32,24 +32,11 @@ if (-not (Test-Path $LogDir)) { } $LogDir = (Resolve-Path $LogDir).Path -$TargetDirWasConfigured = -not [string]::IsNullOrWhiteSpace($env:CARGO_TARGET_DIR) $TargetDir = $env:CARGO_TARGET_DIR -if (-not $TargetDirWasConfigured) { +if ([string]::IsNullOrWhiteSpace($TargetDir)) { $TargetDir = Join-Path $RepoRoot "target" } -$BundledZ3CacheRoot = $TargetDir -if (-not $TargetDirWasConfigured) { - $userCacheRoot = [Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData) - if ([string]::IsNullOrWhiteSpace($userCacheRoot)) { - $userCacheRoot = $env:LOCALAPPDATA - } - if ([string]::IsNullOrWhiteSpace($userCacheRoot)) { - $userCacheRoot = [IO.Path]::GetTempPath() - } - $BundledZ3CacheRoot = Join-Path $userCacheRoot "OpenShell\cache\z3" -} - $BuildJobsValue = $env:OPENSHELL_WINDOWS_BUILD_JOBS if ([string]::IsNullOrWhiteSpace($BuildJobsValue)) { $BuildJobsValue = $env:CARGO_BUILD_JOBS @@ -66,14 +53,11 @@ $WindowsCargoMutex = [System.Threading.Mutex]::new($false, "Local\OpenShellWindo $UnsupportedDriverPackageExcludes = "--exclude openshell-driver-docker --exclude openshell-driver-kubernetes --exclude openshell-driver-kubernetes-secrets --exclude openshell-driver-podman --exclude openshell-driver-vault --exclude openshell-driver-vm --exclude openshell-sandbox --exclude openshell-supervisor-network --exclude openshell-supervisor-process --exclude openshell-vfio" $WindowsClippyPackageExcludes = $UnsupportedDriverPackageExcludes $WindowsClippyLintArgs = "-D warnings -A dead-code -A unused-imports -A clippy::unused-async" -$BundledZ3WorkspaceFeatures = "--features openshell-prover/bundled-z3" -$BundledZ3ServerFeatures = "--features openshell-server/bundled-z3,openshell-prover/bundled-z3" -$BundledZ3Repository = "https://github.com/Z3Prover/z3.git" -$BundledZ3SysVersion = "0.11.0" -# This is the matching Z3 4.16.0 source revision. Update both pins together. -$BundledZ3Revision = "ddb49568d3520e99799e364fb22f35fc67d887b1" -$Z3WorkspaceFeatures = $BundledZ3WorkspaceFeatures -$Z3ServerFeatures = $BundledZ3ServerFeatures +$PrebuiltZ3WorkspaceFeatures = "--features openshell-prover/prebuilt-z3" +$PrebuiltZ3ServerFeatures = "--features openshell-server/prebuilt-z3,openshell-prover/prebuilt-z3" +$PrebuiltZ3Version = "4.16.0" +$Z3WorkspaceFeatures = $PrebuiltZ3WorkspaceFeatures +$Z3ServerFeatures = $PrebuiltZ3ServerFeatures function Get-VsInstallRoots { $programFiles = @( @@ -367,109 +351,14 @@ function Resolve-Z3HeaderPath([string] $HeaderPath) { return (Resolve-Path $HeaderPath).Path } -function Assert-BundledZ3Source([string] $SourcePath, [string] $ExpectedRevision) { - if (-not (Test-Path $SourcePath -PathType Container)) { - throw "Bundled Z3 source directory does not exist: $SourcePath" - } - - $header = Join-Path $SourcePath "src\api\z3.h" - if (-not (Test-Path $header -PathType Leaf)) { - throw "Bundled Z3 source directory does not contain src\api\z3.h: $SourcePath" - } - - if (-not [string]::IsNullOrWhiteSpace($ExpectedRevision)) { - $actualRevision = (& git -C $SourcePath rev-parse HEAD 2>$null) - if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($actualRevision)) { - throw "Could not verify the bundled Z3 source revision at: $SourcePath" - } - if ($actualRevision.Trim() -ne $ExpectedRevision) { - throw "Bundled Z3 source revision mismatch at ${SourcePath}: expected $ExpectedRevision, found $($actualRevision.Trim())" - } - } - - return (Resolve-Path $SourcePath).Path -} - -function Resolve-BundledZ3Source { - if (-not [string]::IsNullOrWhiteSpace($env:Z3_SYS_BUNDLED_DIR_OVERRIDE)) { - return Assert-BundledZ3Source $env:Z3_SYS_BUNDLED_DIR_OVERRIDE "" - } - - $cargoLock = Get-Content (Join-Path $RepoRoot "Cargo.lock") -Raw - $packagePattern = '(?ms)^\[\[package\]\]\s+name = "z3-sys"\s+version = "([^"]+)"' - $packageMatches = [regex]::Matches($cargoLock, $packagePattern) - if ($packageMatches.Count -ne 1 -or $packageMatches[0].Groups[1].Value -ne $BundledZ3SysVersion) { - throw "Bundled Z3 source pin expects z3-sys $BundledZ3SysVersion. Update the version and revision pins for the z3-sys version in Cargo.lock." - } - - $revisionPrefix = $BundledZ3Revision.Substring(0, 12) - $sourcePath = Join-Path $BundledZ3CacheRoot "z3-source-$revisionPrefix" - if (Test-Path $sourcePath) { - return Assert-BundledZ3Source $sourcePath $BundledZ3Revision - } - - if (-not (Get-Command git.exe -ErrorAction SilentlyContinue)) { - throw "Bundled Z3 source preparation requires git.exe on PATH." - } - if (-not (Test-Path $BundledZ3CacheRoot -PathType Container)) { - New-Item -ItemType Directory -Force -Path $BundledZ3CacheRoot | Out-Null - } - - $stagingPath = "$sourcePath.partial-$([guid]::NewGuid().ToString('N'))" - Write-Host "==> Fetching bundled Z3 source" - Write-Host " repository: $BundledZ3Repository" - Write-Host " revision: $BundledZ3Revision" - Write-Host " cache: $sourcePath" - - & git init --quiet $stagingPath - if ($LASTEXITCODE -ne 0) { - throw "git init failed while preparing bundled Z3 source at: $stagingPath" - } - & git -C $stagingPath remote add origin $BundledZ3Repository - if ($LASTEXITCODE -ne 0) { - throw "git remote add failed while preparing bundled Z3 source at: $stagingPath" - } - & git -C $stagingPath fetch --quiet --depth 1 origin $BundledZ3Revision - if ($LASTEXITCODE -ne 0) { - throw "git fetch failed for bundled Z3 revision $BundledZ3Revision. Partial source remains at: $stagingPath" - } - & git -C $stagingPath checkout --quiet --detach FETCH_HEAD - if ($LASTEXITCODE -ne 0) { - throw "git checkout failed for bundled Z3 revision $BundledZ3Revision. Partial source remains at: $stagingPath" - } - - Assert-BundledZ3Source $stagingPath $BundledZ3Revision | Out-Null - try { - # Directory.Move is an atomic rename on the same volume and, unlike - # Move-Item, fails when the destination already exists. A concurrent - # x64/ARM64 invocation can therefore win publication without the loser - # nesting its staging directory inside the shared cache. - [IO.Directory]::Move($stagingPath, $sourcePath) - } catch { - if (-not (Test-Path $sourcePath -PathType Container)) { - throw - } - Write-Host "==> Reusing bundled Z3 source published by another process" - } finally { - if (Test-Path $stagingPath -PathType Container) { - try { - Remove-Item -LiteralPath $stagingPath -Recurse -Force - } catch { - Write-Warning "Could not remove redundant bundled Z3 staging directory: $stagingPath" - } - } - } - return Assert-BundledZ3Source $sourcePath $BundledZ3Revision -} - function Configure-Z3 { if ([string]::IsNullOrWhiteSpace($env:Z3_LIBRARY_PATH_OVERRIDE)) { - Write-Host "==> Z3: bundled" - $env:Z3_SYS_BUNDLED_DIR_OVERRIDE = Resolve-BundledZ3Source - Write-Host " Z3_SYS_BUNDLED_DIR_OVERRIDE=$env:Z3_SYS_BUNDLED_DIR_OVERRIDE" + Write-Host "==> Z3: prebuilt release" + $env:Z3_SYS_Z3_VERSION = $PrebuiltZ3Version + Write-Host " Z3_SYS_Z3_VERSION=$env:Z3_SYS_Z3_VERSION" return [pscustomobject]@{ - WorkspaceFeatures = $BundledZ3WorkspaceFeatures - ServerFeatures = $BundledZ3ServerFeatures + WorkspaceFeatures = $PrebuiltZ3WorkspaceFeatures + ServerFeatures = $PrebuiltZ3ServerFeatures } } @@ -523,8 +412,8 @@ function Invoke-VsCargo { "set `"RUSTC_WRAPPER=`"" ) if ($hostArch -eq "amd64" -and $RustTarget -eq "aarch64-pc-windows-msvc") { - # Let cmake-rs select MSVC cl.exe for bundled Z3. AWS-LC selects - # clang-cl inside its own ARM64 build script. + # Native ARM64 dependencies select their own compilers. Clear inherited + # overrides so AWS-LC can select clang-cl inside its build script. $environmentSetup += @( "set `"CC=`"", "set `"CXX=`"", From e6cad83e6070fb6da7b5a8dee16eef205c0668d9 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 12:52:22 -0700 Subject: [PATCH 06/27] perf(ci): layer sccache on Windows target cache Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 14 +++++----- .../build-openshell-mxc-windows/reference.md | 5 ++-- .github/workflows/windows-msvc.yml | 27 +++++++++++++++---- architecture/windows-msvc-build.md | 13 +++++++-- tasks/scripts/windows-msvc.ps1 | 11 +++++++- 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index fe6ea4ea3..b217c9f6f 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -135,7 +135,7 @@ from this skill. | `Z3_SYS_Z3_HEADER` | unset | Full `z3.h` path required with a system Z3 library. | | `Z3_SYS_Z3_VERSION` | `4.16.0` | Pinned official prebuilt Z3 release selected by the wrapper. | | `READ_ONLY_GITHUB_TOKEN` | unset | Optional token for the Z3 release lookup; GitHub Actions supplies `github.token`. | -| `RUSTC_WRAPPER` | cleared by wrapper | The wrapper clears inherited values because `--skip-tools` does not provision `sccache`. | +| `RUSTC_WRAPPER` | inherited | The wrapper resolves an available command to an absolute path. If it is unavailable, the wrapper warns and continues without compiler caching. | Legacy fork variables such as `OPENSHELL_UPSTREAM`, `OPENSHELL_MXC_FORK_DIR`, and `OPENSHELL_MXC_FORK_BRANCH` are no longer part @@ -188,10 +188,11 @@ order: 6. Focused unsupported-driver contract tests. 7. Artifact reporting. -The GitHub Actions jobs use architecture-specific `Swatinem/rust-cache` -entries for the Cargo registry and dependency target artifacts. Failed runs -also save their usable dependency artifacts. The workflow remains manually -dispatched until cache-hit runtimes justify restoring automatic triggers. +The GitHub Actions jobs layer architecture-specific `Swatinem/rust-cache` +entries for Cargo registry and dependency target artifacts with sccache's GHA +backend for cacheable Rust compiler outputs. Failed runs also save their usable +dependency artifacts. The workflow remains manually dispatched until cache-hit +runtimes justify restoring automatic triggers. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the @@ -206,7 +207,8 @@ commands above on an ARM64 host. The repository-wide `mise run pre-commit` task is also supported on Windows. Its Rust check, Clippy, and test dependencies enter the same MSVC environment -for the native host target and clear inherited `RUSTC_WRAPPER`. Linux glibc +for the native host target and use an inherited compiler wrapper when it is +available. Linux glibc installer tests and Linux service/RPM packaging-asset tests skip explicitly; the Linux build-environment shell-helper test also skips; cross-platform checks continue to run. The blocking Windows Clippy pass excludes unsupported diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index 2514c2b0d..18678321b 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -46,8 +46,9 @@ if ($arch -eq [System.Runtime.InteropServices.Architecture]::Arm64) { The native test tasks reject a target that does not match the host architecture. Do not report x64 compatibility-under-emulation coverage from an ARM64 run. -The wrapper adds missing rustup targets and clears inherited -`RUSTC_WRAPPER`. It does not install Visual Studio, Rust, Docker, Kubernetes, +The wrapper adds missing rustup targets and preserves an inherited +`RUSTC_WRAPPER` when the command is available. Otherwise, it warns and clears +the setting. It does not install Visual Studio, Rust, Docker, Kubernetes, Podman, WSL, Hyper-V, or VM tooling. On Windows, `mise run pre-commit` routes `rust:check`, `rust:lint`, and diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 8419ce74a..9f788fbbe 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -6,12 +6,18 @@ jobs: runs-on: windows-2025 env: READ_ONLY_GITHUB_TOKEN: ${{ github.token }} + SCCACHE_GHA_ENABLED: "true" + SCCACHE_GHA_VERSION: windows-msvc-x64-prebuilt-z3-v2 + SCCACHE_CLIENT_SIDE: "1" + SCCACHE_BASEDIRS: ${{ github.workspace }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 with: install: false experimental: true + - name: Configure GHA sccache backend + uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - uses: dtolnay/rust-toolchain@master with: toolchain: "1.95.0" @@ -19,9 +25,8 @@ jobs: - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 env: - # mise exports RUSTC_WRAPPER=sccache, but this workflow intentionally - # does not install sccache. Keep rust-cache's cargo metadata calls - # independent of that unavailable wrapper so target artifacts save. + # Keep rust-cache's cargo metadata calls independent of the compiler + # wrapper; build steps still inherit sccache from the job. RUSTC_WRAPPER: "" with: # Keep the prebuilt-Z3 experiment isolated from earlier target caches. @@ -33,18 +38,27 @@ jobs: - run: mise run --skip-tools windows:build:x64 - run: mise run --skip-tools windows:test:x64 - run: mise run --skip-tools windows:test:unsupported:x64 + - name: sccache stats + if: always() + run: sccache --show-stats arm64: # TODO: provision a windows-arm64 self-hosted runner runs-on: [self-hosted, windows-arm64] if: false # flip to true once the runner is online env: READ_ONLY_GITHUB_TOKEN: ${{ github.token }} + SCCACHE_GHA_ENABLED: "true" + SCCACHE_GHA_VERSION: windows-msvc-arm64-prebuilt-z3-v2 + SCCACHE_CLIENT_SIDE: "1" + SCCACHE_BASEDIRS: ${{ github.workspace }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 with: install: false experimental: true + - name: Configure GHA sccache backend + uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - uses: dtolnay/rust-toolchain@master with: toolchain: "1.95.0" @@ -52,8 +66,8 @@ jobs: - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 env: - # Keep rust-cache's cargo metadata calls independent of the - # unavailable sccache wrapper exported by mise. + # Keep rust-cache's cargo metadata calls independent of the compiler + # wrapper; build steps still inherit sccache from the job. RUSTC_WRAPPER: "" with: shared-key: windows-msvc-arm64-prebuilt-z3-v1 @@ -62,3 +76,6 @@ jobs: cache-bin: "false" - run: mise run --skip-tools windows:check:arm64 - run: mise run --skip-tools windows:build:arm64 + - name: sccache stats + if: always() + run: sccache --show-stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index ae0141359..9c5821b91 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -71,8 +71,10 @@ Windows validation is exposed through `tasks/windows.toml`: 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, clears inherited `RUSTC_WRAPPER`, and -keeps build artifacts under the normal Cargo target tree. +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 @@ -95,6 +97,13 @@ wrapper uses that system Z3 instead and requires `Z3_SYS_Z3_HEADER` to point at the full path to `z3.h`. Local clean builds use the unauthenticated GitHub API unless `READ_ONLY_GITHUB_TOKEN` is set. +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. + 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. diff --git a/tasks/scripts/windows-msvc.ps1 b/tasks/scripts/windows-msvc.ps1 index 59ec2b412..a71ef929a 100644 --- a/tasks/scripts/windows-msvc.ps1 +++ b/tasks/scripts/windows-msvc.ps1 @@ -405,11 +405,20 @@ function Invoke-VsCargo { $targetArch = Get-VsTargetArch $RustTarget $hostArch = Get-HostArch $logPath = Join-Path $LogDir $LogName + $rustcWrapper = "" + if (-not [string]::IsNullOrWhiteSpace($env:RUSTC_WRAPPER)) { + $wrapperCommand = Get-Command $env:RUSTC_WRAPPER -ErrorAction SilentlyContinue + if ($wrapperCommand) { + $rustcWrapper = $wrapperCommand.Source + } else { + Write-Warning "RUSTC_WRAPPER '$env:RUSTC_WRAPPER' was not found; continuing without it." + } + } $environmentSetup = @( "set `"CARGO_TARGET_DIR=$TargetDir`"", "set `"CARGO_BUILD_JOBS=$WindowsBuildJobs`"", "set `"CARGO_INCREMENTAL=0`"", - "set `"RUSTC_WRAPPER=`"" + "set `"RUSTC_WRAPPER=$rustcWrapper`"" ) if ($hostArch -eq "amd64" -and $RustTarget -eq "aarch64-pc-windows-msvc") { # Native ARM64 dependencies select their own compilers. Clear inherited From c1cdade2a12ed68972fc93e8df1eaf3a1ad0e13b Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 13:28:43 -0700 Subject: [PATCH 07/27] ci(windows): split PR checks from main validation Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 14 +++-- .../build-openshell-mxc-windows/reference.md | 2 +- .github/workflows/windows-msvc.yml | 55 +++++++++++++++++-- architecture/windows-msvc-build.md | 30 +++++++--- 4 files changed, 79 insertions(+), 22 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index b217c9f6f..a51666521 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -28,7 +28,7 @@ The Windows build lane is implemented by these tracked files: | `tasks/windows.toml` | Mise task entry points for `windows:*` commands. | | `tasks/rust.toml`, `tasks/test.toml`, and `tasks/markdown.toml` | Windows routing for compiler-bearing checks, explicit Unix-only test skips, and Markdown dependency setup. | | `tasks/scripts/windows-msvc.ps1` | PowerShell wrapper that enters the Visual Studio developer environment and invokes Cargo. | -| `.github/workflows/windows-msvc.yml` | Manually dispatched GitHub Actions jobs with architecture-specific Rust caches for x64 and future ARM64 Windows validation. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue checks and full main/manual GitHub Actions jobs with architecture-specific Rust caches for x64 and future ARM64 Windows validation. | | `architecture/windows-msvc-build.md` | Design notes and validation contract. | | `.agents/skills/build-openshell-mxc-windows/` | This skill and companion reference material. | @@ -191,8 +191,10 @@ order: The GitHub Actions jobs layer architecture-specific `Swatinem/rust-cache` entries for Cargo registry and dependency target artifacts with sccache's GHA backend for cacheable Rust compiler outputs. Failed runs also save their usable -dependency artifacts. The workflow remains manually dispatched until cache-hit -runtimes justify restoring automatic triggers. +dependency artifacts. Pull-request mirrors and merge queues run the x64 check; +pushes to `main` and manual dispatches run x64 check, release build, and full +workspace tests. Main uses the same cache namespaces and keeps both layers warm +for pull requests. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the @@ -260,9 +262,9 @@ The focused contract tasks for either native architecture run: windows_builtin_compute_drivers_report_unsupported ``` -These tests are also included in the full x64 workspace test run; the focused -task intentionally re-runs them so unsupported Windows behavior is visible in -the CI report. +These tests are also included in the full x64 workspace test run. The focused +task is available for local diagnosis; GitHub Actions does not re-run it after +the full suite. ## Test Accounting Guidance diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index 18678321b..3fcbe12d5 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | Manual GitHub Actions x64 job and disabled ARM64 scaffold, each with an architecture-specific Rust dependency cache. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 checks, full main/manual validation, and a disabled ARM64 scaffold with architecture-specific Rust caches. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 9f788fbbe..8fc9b0732 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -1,8 +1,43 @@ name: Windows MSVC (build-only) + on: + merge_group: + types: [checks_requested] + push: + branches: + - main + - "pull-request/[0-9]+" workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_INCREMENTAL: "0" + jobs: + pr_metadata: + name: Resolve PR metadata + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + outputs: + should_run: ${{ github.ref == 'refs/heads/main' || steps.gate.outputs.should_run == 'true' }} + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - id: gate + if: github.ref != 'refs/heads/main' + uses: ./.github/actions/pr-gate + x64: + needs: pr_metadata + if: needs.pr_metadata.outputs.should_run == 'true' runs-on: windows-2025 env: READ_ONLY_GITHUB_TOKEN: ${{ github.token }} @@ -34,15 +69,20 @@ jobs: cache-targets: "true" cache-on-failure: "true" cache-bin: "false" - - run: mise run --skip-tools windows:check:x64 - - run: mise run --skip-tools windows:build:x64 - - run: mise run --skip-tools windows:test:x64 - - run: mise run --skip-tools windows:test:unsupported:x64 + - name: Check + run: mise run --skip-tools windows:check:x64 + - name: Build release binaries + if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' + run: mise run --skip-tools windows:build:x64 + - name: Test + if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' + run: mise run --skip-tools windows:test:x64 - name: sccache stats if: always() run: sccache --show-stats arm64: # TODO: provision a windows-arm64 self-hosted runner + needs: pr_metadata runs-on: [self-hosted, windows-arm64] if: false # flip to true once the runner is online env: @@ -74,8 +114,11 @@ jobs: cache-targets: "true" cache-on-failure: "true" cache-bin: "false" - - run: mise run --skip-tools windows:check:arm64 - - run: mise run --skip-tools windows:build:arm64 + - name: Check + run: mise run --skip-tools windows:check:arm64 + - name: Build release binaries + if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' + run: mise run --skip-tools windows:build:arm64 - name: sccache stats if: always() run: sccache --show-stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index 9c5821b91..6dc101487 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -48,11 +48,13 @@ creating misleading Windows driver artifacts. ## Mise Lane -The GitHub Actions workflow is manually dispatched. Each architecture restores -and saves a dedicated Rust cache containing the Cargo registry and dependency -build artifacts, including artifacts from failed runs. Keep the workflow manual -until cache-hit runtimes demonstrate that it is suitable for pull requests and -merges to `main`. +The GitHub Actions workflow checks x64 Windows compilation for pull-request +mirror branches and merge queues. Pushes to `main` and manual dispatches also +build the release binaries and run the full x64 workspace test suite. Each +architecture restores and saves a dedicated Rust cache containing the Cargo +registry and dependency build artifacts, including artifacts from failed runs. +The full run on `main` uses the same cache namespaces as pull requests, keeping +both the Cargo target cache and sccache warm for subsequent checks. Windows validation is exposed through `tasks/windows.toml`: @@ -128,23 +130,33 @@ break ARM64 crypto dependency builds. ## CI Shape -The x64 GitHub Actions job runs on `windows-2025` and executes: +The x64 GitHub Actions job runs on `windows-2025`. Pull-request mirrors and +merge queues execute: + +```powershell +mise run --skip-tools windows:check:x64 +``` + +Pushes to `main` and manual dispatches execute: ```powershell mise run --skip-tools windows:check:x64 mise run --skip-tools windows:build:x64 mise run --skip-tools windows:test:x64 -mise run --skip-tools windows:test:unsupported:x64 ``` +The full workspace test 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 cache is partitioned by architecture so incompatible x64 and ARM64 target artifacts cannot collide. It does not cache Cargo-installed binaries, which also keeps the disabled self-hosted ARM64 scaffold from modifying persistent runner tooling. The local aggregate `windows:ci` task cross-builds ARM64 on an x64 host. The -GitHub x64 job currently runs only the x64 tasks, and native ARM64 tests remain -exclusive to an ARM64 runner. +GitHub x64 job runs only the x64 tasks, and native ARM64 tests remain exclusive +to an ARM64 runner. The ARM64 job is scaffolded but disabled until a Windows ARM64 runner is available. Once enabled, it should run check, release build, native workspace From 76a69e72bbc6d3d999651b9a671f9ad34a507329 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 16:23:12 -0700 Subject: [PATCH 08/27] ci(windows): separate checks builds and cache seeding Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 11 +- .../build-openshell-mxc-windows/reference.md | 2 +- .github/workflows/windows-msvc.yml | 101 ++++++++++++++++-- architecture/windows-msvc-build.md | 30 +++--- 4 files changed, 117 insertions(+), 27 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index a51666521..faf0d0e86 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -28,7 +28,7 @@ The Windows build lane is implemented by these tracked files: | `tasks/windows.toml` | Mise task entry points for `windows:*` commands. | | `tasks/rust.toml`, `tasks/test.toml`, and `tasks/markdown.toml` | Windows routing for compiler-bearing checks, explicit Unix-only test skips, and Markdown dependency setup. | | `tasks/scripts/windows-msvc.ps1` | PowerShell wrapper that enters the Visual Studio developer environment and invokes Cargo. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue checks and full main/manual GitHub Actions jobs with architecture-specific Rust caches for x64 and future ARM64 Windows validation. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue lint and test, main cache seeding, and dependent binary-build jobs with architecture-specific Rust caches for x64 and future ARM64 Windows validation. | | `architecture/windows-msvc-build.md` | Design notes and validation contract. | | `.agents/skills/build-openshell-mxc-windows/` | This skill and companion reference material. | @@ -191,10 +191,11 @@ order: The GitHub Actions jobs layer architecture-specific `Swatinem/rust-cache` entries for Cargo registry and dependency target artifacts with sccache's GHA backend for cacheable Rust compiler outputs. Failed runs also save their usable -dependency artifacts. Pull-request mirrors and merge queues run the x64 check; -pushes to `main` and manual dispatches run x64 check, release build, and full -workspace tests. Main uses the same cache namespaces and keeps both layers warm -for pull requests. +dependency artifacts. Pull-request mirrors and merge queues run Windows Clippy +and Rust tests. Pushes to `main` and manual dispatches run the same lint and +test commands in a cache-seed job, followed by a dependent release-binary build +job. The seed and PR jobs use the same cache namespaces. The binaries are not +uploaded or published. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index 3fcbe12d5..d3ebd13a4 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 checks, full main/manual validation, and a disabled ARM64 scaffold with architecture-specific Rust caches. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 lint and test, main/manual cache seeding followed by binary builds, and a disabled ARM64 scaffold with architecture-specific Rust caches. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 8fc9b0732..b9fbc8222 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -35,9 +35,13 @@ jobs: if: github.ref != 'refs/heads/main' uses: ./.github/actions/pr-gate - x64: + pr-check-x64: + name: PR lint and test (x64) needs: pr_metadata - if: needs.pr_metadata.outputs.should_run == 'true' + if: >- + needs.pr_metadata.outputs.should_run == 'true' && + github.ref != 'refs/heads/main' && + github.event_name != 'workflow_dispatch' runs-on: windows-2025 env: READ_ONLY_GITHUB_TOKEN: ${{ github.token }} @@ -69,17 +73,98 @@ jobs: cache-targets: "true" cache-on-failure: "true" cache-bin: "false" - - name: Check - run: mise run --skip-tools windows:check:x64 + - name: Lint + run: mise run --skip-tools rust:lint + - name: Test + run: mise run --skip-tools test:rust + - name: sccache stats + if: always() + run: sccache --show-stats + + cache-seed-x64: + name: Seed cache (x64) + needs: pr_metadata + if: >- + needs.pr_metadata.outputs.should_run == 'true' && + (github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch') + runs-on: windows-2025 + env: + READ_ONLY_GITHUB_TOKEN: ${{ github.token }} + SCCACHE_GHA_ENABLED: "true" + SCCACHE_GHA_VERSION: windows-msvc-x64-prebuilt-z3-v2 + SCCACHE_CLIENT_SIDE: "1" + SCCACHE_BASEDIRS: ${{ github.workspace }} + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 + with: + install: false + experimental: true + - name: Configure GHA sccache backend + uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: "1.95.0" + targets: x86_64-pc-windows-msvc + - name: Cache Rust target and registry + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + env: + RUSTC_WRAPPER: "" + with: + shared-key: windows-msvc-x64-prebuilt-z3-v1 + cache-targets: "true" + cache-on-failure: "true" + cache-bin: "false" + - name: Lint + run: mise run --skip-tools rust:lint + - name: Test + run: mise run --skip-tools test:rust + - name: sccache stats + if: always() + run: sccache --show-stats + + build-x64: + name: Build binaries (x64) + needs: [pr_metadata, cache-seed-x64] + if: >- + always() && + needs.pr_metadata.outputs.should_run == 'true' && + needs.cache-seed-x64.result == 'success' && + (github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch') + runs-on: windows-2025 + env: + READ_ONLY_GITHUB_TOKEN: ${{ github.token }} + SCCACHE_GHA_ENABLED: "true" + SCCACHE_GHA_VERSION: windows-msvc-x64-prebuilt-z3-v2 + SCCACHE_CLIENT_SIDE: "1" + SCCACHE_BASEDIRS: ${{ github.workspace }} + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 + with: + install: false + experimental: true + - name: Configure GHA sccache backend + uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: "1.95.0" + targets: x86_64-pc-windows-msvc + - name: Cache Rust target and registry + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + env: + RUSTC_WRAPPER: "" + with: + shared-key: windows-msvc-x64-prebuilt-z3-v1 + cache-targets: "true" + cache-on-failure: "true" + cache-bin: "false" - name: Build release binaries - if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' run: mise run --skip-tools windows:build:x64 - - name: Test - if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' - run: mise run --skip-tools windows:test:x64 - name: sccache stats if: always() run: sccache --show-stats + arm64: # TODO: provision a windows-arm64 self-hosted runner needs: pr_metadata diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index 6dc101487..322975ddd 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -48,13 +48,17 @@ creating misleading Windows driver artifacts. ## Mise Lane -The GitHub Actions workflow checks x64 Windows compilation for pull-request -mirror branches and merge queues. Pushes to `main` and manual dispatches also -build the release binaries and run the full x64 workspace test suite. Each -architecture restores and saves a dedicated Rust cache containing the Cargo +The GitHub Actions workflow runs x64 Windows Clippy and Rust tests for +pull-request mirror branches and merge queues. 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 full run on `main` uses the same cache namespaces as pull requests, keeping -both the Cargo target cache and sccache warm for subsequent checks. +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`: @@ -130,23 +134,23 @@ break ARM64 crypto dependency builds. ## CI Shape -The x64 GitHub Actions job runs on `windows-2025`. Pull-request mirrors and +The x64 GitHub Actions jobs run on `windows-2025`. Pull-request mirrors and merge queues execute: ```powershell -mise run --skip-tools windows:check:x64 +mise run --skip-tools rust:lint +mise run --skip-tools test:rust ``` -Pushes to `main` and manual dispatches execute: +Pushes to `main` and manual dispatches first seed the shared caches with those +same lint and test commands. After the seed succeeds, a separate job executes: ```powershell -mise run --skip-tools windows:check:x64 mise run --skip-tools windows:build:x64 -mise run --skip-tools windows:test:x64 ``` -The full workspace test includes the unsupported-driver contract test, so CI -does not run the focused test task a second time. The focused task remains +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 cache is partitioned by architecture so incompatible x64 and ARM64 target From 916abc6cab0a18d47460d00848448dbb4530a932 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 16:26:57 -0700 Subject: [PATCH 09/27] fix(ci): simplify Windows build dependency Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index b9fbc8222..821530989 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -125,12 +125,8 @@ jobs: build-x64: name: Build binaries (x64) - needs: [pr_metadata, cache-seed-x64] - if: >- - always() && - needs.pr_metadata.outputs.should_run == 'true' && - needs.cache-seed-x64.result == 'success' && - (github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch') + needs: cache-seed-x64 + if: needs.cache-seed-x64.result == 'success' runs-on: windows-2025 env: READ_ONLY_GITHUB_TOKEN: ${{ github.token }} From 2046301615ca4c2bfdc4263c704acea7ca2c7d8a Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 16:28:36 -0700 Subject: [PATCH 10/27] fix(ci): rely on Windows job dependency status Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 821530989..73b445e37 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -126,7 +126,6 @@ jobs: build-x64: name: Build binaries (x64) needs: cache-seed-x64 - if: needs.cache-seed-x64.result == 'success' runs-on: windows-2025 env: READ_ONLY_GITHUB_TOKEN: ${{ github.token }} From 9bb4b4847817aa0f4d7d97a1c1460d850fd71203 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 16:33:37 -0700 Subject: [PATCH 11/27] fix(ci): use valid opt-in Windows ARM runner Signed-off-by: Piotr Mlocek --- .agents/skills/build-openshell-mxc-windows/SKILL.md | 2 +- .agents/skills/build-openshell-mxc-windows/reference.md | 2 +- .github/workflows/windows-msvc.yml | 6 +++--- architecture/windows-msvc-build.md | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index faf0d0e86..c59fad68c 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -28,7 +28,7 @@ The Windows build lane is implemented by these tracked files: | `tasks/windows.toml` | Mise task entry points for `windows:*` commands. | | `tasks/rust.toml`, `tasks/test.toml`, and `tasks/markdown.toml` | Windows routing for compiler-bearing checks, explicit Unix-only test skips, and Markdown dependency setup. | | `tasks/scripts/windows-msvc.ps1` | PowerShell wrapper that enters the Visual Studio developer environment and invokes Cargo. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue lint and test, main cache seeding, and dependent binary-build jobs with architecture-specific Rust caches for x64 and future ARM64 Windows validation. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue lint and test, main cache seeding, dependent binary-build jobs, and opt-in hosted ARM64 validation with architecture-specific Rust caches. | | `architecture/windows-msvc-build.md` | Design notes and validation contract. | | `.agents/skills/build-openshell-mxc-windows/` | This skill and companion reference material. | diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index d3ebd13a4..c6763c9a5 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 lint and test, main/manual cache seeding followed by binary builds, and a disabled ARM64 scaffold with architecture-specific Rust caches. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 lint and test, main/manual cache seeding followed by binary builds, and opt-in hosted ARM64 validation with architecture-specific Rust caches. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 73b445e37..d0bcab260 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -161,10 +161,10 @@ jobs: run: sccache --show-stats arm64: - # TODO: provision a windows-arm64 self-hosted runner + # Keep native ARM64 validation opt-in until its runtime and cost are measured. needs: pr_metadata - runs-on: [self-hosted, windows-arm64] - if: false # flip to true once the runner is online + runs-on: windows-11-arm + if: vars.ENABLE_WINDOWS_ARM64 == 'true' env: READ_ONLY_GITHUB_TOKEN: ${{ github.token }} SCCACHE_GHA_ENABLED: "true" diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index 322975ddd..de01fae1a 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -162,10 +162,10 @@ The local aggregate `windows:ci` task cross-builds ARM64 on an x64 host. The GitHub x64 job runs only the x64 tasks, and native ARM64 tests remain exclusive to an ARM64 runner. -The ARM64 job is scaffolded but disabled until a Windows ARM64 runner is -available. Once enabled, it should run check, release build, native workspace -tests, and the focused unsupported-driver contracts for -`aarch64-pc-windows-msvc`. +The ARM64 job uses the hosted `windows-11-arm` runner but remains disabled +unless the repository variable `ENABLE_WINDOWS_ARM64` is set to `true`. Before +enabling it, measure the native runner and extend it to follow the same +lint/test seed and dependent-build split as x64. ## Validation Contract From 0404e95a104e64a51ef5831ae0d4366640df73aa Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 16:35:21 -0700 Subject: [PATCH 12/27] ci(windows): keep ARM64 validation local Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 2 +- .../build-openshell-mxc-windows/reference.md | 2 +- .github/workflows/windows-msvc.yml | 43 ------------------- architecture/windows-msvc-build.md | 13 +++--- 4 files changed, 7 insertions(+), 53 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index c59fad68c..a58d5ac05 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -28,7 +28,7 @@ The Windows build lane is implemented by these tracked files: | `tasks/windows.toml` | Mise task entry points for `windows:*` commands. | | `tasks/rust.toml`, `tasks/test.toml`, and `tasks/markdown.toml` | Windows routing for compiler-bearing checks, explicit Unix-only test skips, and Markdown dependency setup. | | `tasks/scripts/windows-msvc.ps1` | PowerShell wrapper that enters the Visual Studio developer environment and invokes Cargo. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue lint and test, main cache seeding, dependent binary-build jobs, and opt-in hosted ARM64 validation with architecture-specific Rust caches. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 lint and test, main cache seeding, and dependent x64 binary-build jobs. ARM64 remains a local task until it gets a native workflow. | | `architecture/windows-msvc-build.md` | Design notes and validation contract. | | `.agents/skills/build-openshell-mxc-windows/` | This skill and companion reference material. | diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index c6763c9a5..70fd6f95b 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 lint and test, main/manual cache seeding followed by binary builds, and opt-in hosted ARM64 validation with architecture-specific Rust caches. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 lint and test plus main/manual cache seeding followed by x64 binary builds. ARM64 remains local-only until it gets a native workflow. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index d0bcab260..e84d4dacf 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -159,46 +159,3 @@ jobs: - name: sccache stats if: always() run: sccache --show-stats - - arm64: - # Keep native ARM64 validation opt-in until its runtime and cost are measured. - needs: pr_metadata - runs-on: windows-11-arm - if: vars.ENABLE_WINDOWS_ARM64 == 'true' - env: - READ_ONLY_GITHUB_TOKEN: ${{ github.token }} - SCCACHE_GHA_ENABLED: "true" - SCCACHE_GHA_VERSION: windows-msvc-arm64-prebuilt-z3-v2 - SCCACHE_CLIENT_SIDE: "1" - SCCACHE_BASEDIRS: ${{ github.workspace }} - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 - with: - install: false - experimental: true - - name: Configure GHA sccache backend - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: "1.95.0" - targets: aarch64-pc-windows-msvc - - name: Cache Rust target and registry - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - env: - # Keep rust-cache's cargo metadata calls independent of the compiler - # wrapper; build steps still inherit sccache from the job. - RUSTC_WRAPPER: "" - with: - shared-key: windows-msvc-arm64-prebuilt-z3-v1 - cache-targets: "true" - cache-on-failure: "true" - cache-bin: "false" - - name: Check - run: mise run --skip-tools windows:check:arm64 - - name: Build release binaries - if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' - run: mise run --skip-tools windows:build:arm64 - - name: sccache stats - if: always() - run: sccache --show-stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index de01fae1a..40436e877 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -153,19 +153,16 @@ 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 cache is partitioned by architecture so incompatible x64 and ARM64 target -artifacts cannot collide. It does not cache Cargo-installed binaries, which -also keeps the disabled self-hosted ARM64 scaffold from modifying persistent -runner tooling. +The hosted workflow uses an x64-specific cache namespace and does not cache +Cargo-installed binaries. The local aggregate `windows:ci` task cross-builds ARM64 on an x64 host. The GitHub x64 job runs only the x64 tasks, and native ARM64 tests remain exclusive to an ARM64 runner. -The ARM64 job uses the hosted `windows-11-arm` runner but remains disabled -unless the repository variable `ENABLE_WINDOWS_ARM64` is set to `true`. Before -enabling it, measure the native runner and extend it to follow the same -lint/test seed and dependent-build split as x64. +GitHub Actions currently runs only x64. ARM64 remains available through the +local `windows:*:arm64` tasks and requires a separate native workflow when the +project is ready to enable hosted ARM64 validation. ## Validation Contract From 30800440658e407558cf4adf3ae2efd025ab453f Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 16:41:25 -0700 Subject: [PATCH 13/27] fix(ci): retain compatible Windows mise action Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index e84d4dacf..64e889b1e 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -51,7 +51,8 @@ jobs: SCCACHE_BASEDIRS: ${{ github.workspace }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: jdx/mise-action@7e36c90d9ab29c415a2384db3006f3ec8a8cc654 # v4.2.4 + # v4.2.4 causes GitHub Actions startup_failure on windows-2025. + - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: install: false experimental: true @@ -96,6 +97,7 @@ jobs: SCCACHE_BASEDIRS: ${{ github.workspace }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + # v4.2.4 causes GitHub Actions startup_failure on windows-2025. - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: install: false From 36d75e5a7168319e244ab12b9b4ae5b472c1f2ad Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 16:45:08 -0700 Subject: [PATCH 14/27] fix(ci): install Clippy for Windows validation Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index 64e889b1e..f0b874f30 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -62,6 +62,7 @@ jobs: with: toolchain: "1.95.0" targets: x86_64-pc-windows-msvc + components: clippy - name: Cache Rust target and registry uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 env: @@ -108,6 +109,7 @@ jobs: with: toolchain: "1.95.0" targets: x86_64-pc-windows-msvc + components: clippy - name: Cache Rust target and registry uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 env: From 6c484c78a71a6ff803da4f1d2f98157ade03fc5b Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:01:23 -0700 Subject: [PATCH 15/27] ci(windows): focus platform lint coverage Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 10 ++++---- .../build-openshell-mxc-windows/reference.md | 2 +- .github/workflows/windows-msvc.yml | 24 +++++++++++++++---- architecture/windows-msvc-build.md | 13 +++++----- deny.toml | 1 + 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index a58d5ac05..44fd3d93f 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -191,11 +191,11 @@ order: The GitHub Actions jobs layer architecture-specific `Swatinem/rust-cache` entries for Cargo registry and dependency target artifacts with sccache's GHA backend for cacheable Rust compiler outputs. Failed runs also save their usable -dependency artifacts. Pull-request mirrors and merge queues run Windows Clippy -and Rust tests. Pushes to `main` and manual dispatches run the same lint and -test commands in a cache-seed job, followed by a dependent release-binary build -job. The seed and PR jobs use the same cache namespaces. The binaries are not -uploaded or published. +dependency artifacts. Pull-request mirrors and merge queues run Clippy for the +Windows-sensitive sandbox, core, and CLI crates plus Rust tests. Pushes to +`main` and manual dispatches run the same lint and test commands in a cache-seed +job, followed by a dependent release-binary build job. The seed and PR jobs use +the same cache namespaces. The binaries are not uploaded or published. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index 70fd6f95b..a6a65966e 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue x64 lint and test plus main/manual cache seeding followed by x64 binary builds. ARM64 remains local-only until it gets a native workflow. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue lint for Windows-sensitive crates and x64 tests plus identical main/manual cache seeding followed by x64 binary builds. ARM64 remains local-only until it gets a native workflow. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index f0b874f30..b4843a9f6 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -75,8 +75,16 @@ jobs: cache-targets: "true" cache-on-failure: "true" cache-bin: "false" - - name: Lint - run: mise run --skip-tools rust:lint + - name: Lint Windows-sensitive crates + # Formatting is target-independent and already checked by the Linux jobs. + # Keep this guard focused on Windows cfgs, matching the macOS lane. + run: >- + cargo clippy + -p openshell-sandbox + -p openshell-core + -p openshell-cli + --all-targets + -- -D warnings - name: Test run: mise run --skip-tools test:rust - name: sccache stats @@ -119,8 +127,16 @@ jobs: cache-targets: "true" cache-on-failure: "true" cache-bin: "false" - - name: Lint - run: mise run --skip-tools rust:lint + - name: Lint Windows-sensitive crates + # Keep the seed workload identical to the pull-request workload so its + # target and compiler caches are reusable by subsequent pull requests. + run: >- + cargo clippy + -p openshell-sandbox + -p openshell-core + -p openshell-cli + --all-targets + -- -D warnings - name: Test run: mise run --skip-tools test:rust - name: sccache stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index 40436e877..674a06f46 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -48,11 +48,12 @@ creating misleading Windows driver artifacts. ## Mise Lane -The GitHub Actions workflow runs x64 Windows Clippy and Rust tests for -pull-request mirror branches and merge queues. 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. +The GitHub Actions workflow runs Clippy for the Windows-sensitive sandbox, +core, and CLI crates plus Rust tests for pull-request mirror branches and merge +queues. 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. @@ -138,7 +139,7 @@ The x64 GitHub Actions jobs run on `windows-2025`. Pull-request mirrors and merge queues execute: ```powershell -mise run --skip-tools rust:lint +cargo clippy -p openshell-sandbox -p openshell-core -p openshell-cli --all-targets -- -D warnings mise run --skip-tools test:rust ``` diff --git a/deny.toml b/deny.toml index c4dab1233..3f0cf87ba 100644 --- a/deny.toml +++ b/deny.toml @@ -41,6 +41,7 @@ allow = [ "BSD-2-Clause", "BSD-3-Clause", "BSL-1.0", + "bzip2-1.0.6", "ISC", "Zlib", "0BSD", From f2ad9d84fbda0cba5a29b55c91f5074c17237a92 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:05:28 -0700 Subject: [PATCH 16/27] docs(licenses): explain bzip2 allowance Signed-off-by: Piotr Mlocek --- deny.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deny.toml b/deny.toml index 3f0cf87ba..0a8de7976 100644 --- a/deny.toml +++ b/deny.toml @@ -41,6 +41,8 @@ allow = [ "BSD-2-Clause", "BSD-3-Clause", "BSL-1.0", + # Permissive, non-copyleft license pulled in by the prebuilt Z3 archive + # path (z3-sys -> zip -> bzip2); compatible with this Apache-2.0 project. "bzip2-1.0.6", "ISC", "Zlib", From 2d413c177443787e7bcd44d15a23ae9a42f6afb5 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:07:54 -0700 Subject: [PATCH 17/27] ci(windows): simplify workflow name Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index b4843a9f6..f77dd2044 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -1,4 +1,4 @@ -name: Windows MSVC (build-only) +name: Windows MSVC on: merge_group: From d30e21f3d0f320a7842ca51c160c9151b8504841 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:14:58 -0700 Subject: [PATCH 18/27] fix(windows): allow async platform stub Signed-off-by: Piotr Mlocek --- crates/openshell-bootstrap/src/build_windows.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/openshell-bootstrap/src/build_windows.rs b/crates/openshell-bootstrap/src/build_windows.rs index 93af1345d..0be12cd82 100644 --- a/crates/openshell-bootstrap/src/build_windows.rs +++ b/crates/openshell-bootstrap/src/build_windows.rs @@ -9,7 +9,7 @@ use std::path::Path; use miette::Result; // Keep this stub's signature aligned with the supported-platform implementation. -#[allow(clippy::implicit_hasher)] +#[allow(clippy::implicit_hasher, clippy::unused_async)] pub async fn build_local_image( _dockerfile_path: &Path, _tag: &str, From d53bc6d0829fab8952545c7674851751798a7f2e Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:22:44 -0700 Subject: [PATCH 19/27] fix(network): make file fingerprints portable Signed-off-by: Piotr Mlocek --- .../src/identity.rs | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/crates/openshell-supervisor-network/src/identity.rs b/crates/openshell-supervisor-network/src/identity.rs index 5e89c3503..0861f0096 100644 --- a/crates/openshell-supervisor-network/src/identity.rs +++ b/crates/openshell-supervisor-network/src/identity.rs @@ -18,55 +18,51 @@ use std::path::{Path, PathBuf}; use std::sync::Mutex; use tracing::debug; -#[derive(Clone)] +#[derive(Clone, PartialEq)] struct FileFingerprint { len: u64, + #[cfg(unix)] mtime_sec: i64, + #[cfg(unix)] mtime_nsec: i64, + #[cfg(unix)] ctime_sec: i64, + #[cfg(unix)] ctime_nsec: i64, #[cfg(unix)] dev: u64, #[cfg(unix)] ino: u64, + #[cfg(not(unix))] + modified: Option, + #[cfg(not(unix))] + created: Option, } impl FileFingerprint { fn from_metadata(metadata: &Metadata) -> Self { Self { len: metadata.len(), + #[cfg(unix)] mtime_sec: metadata.mtime(), + #[cfg(unix)] mtime_nsec: metadata.mtime_nsec(), + #[cfg(unix)] ctime_sec: metadata.ctime(), + #[cfg(unix)] ctime_nsec: metadata.ctime_nsec(), #[cfg(unix)] dev: metadata.dev(), #[cfg(unix)] ino: metadata.ino(), + #[cfg(not(unix))] + modified: metadata.modified().ok(), + #[cfg(not(unix))] + created: metadata.created().ok(), } } } -impl PartialEq for FileFingerprint { - fn eq(&self, other: &Self) -> bool { - self.len == other.len - && self.mtime_sec == other.mtime_sec - && self.mtime_nsec == other.mtime_nsec - && self.ctime_sec == other.ctime_sec - && self.ctime_nsec == other.ctime_nsec - && { - #[cfg(unix)] - { - self.dev == other.dev && self.ino == other.ino - } - #[cfg(not(unix))] - { - true - } - } - } -} - #[derive(Clone)] struct CachedBinary { hash: String, From f46a2db5e41fd8feb083416521a49a4c298e5020 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:28:45 -0700 Subject: [PATCH 20/27] ci(windows): lint supported deliverables Signed-off-by: Piotr Mlocek --- .../build-openshell-mxc-windows/SKILL.md | 8 ++-- .../build-openshell-mxc-windows/reference.md | 2 +- .github/workflows/windows-msvc.yml | 10 +++-- architecture/windows-msvc-build.md | 14 +++---- .../openshell-bootstrap/src/build_windows.rs | 2 +- .../src/identity.rs | 38 ++++++++++--------- 6 files changed, 41 insertions(+), 33 deletions(-) diff --git a/.agents/skills/build-openshell-mxc-windows/SKILL.md b/.agents/skills/build-openshell-mxc-windows/SKILL.md index 44fd3d93f..257e9903a 100644 --- a/.agents/skills/build-openshell-mxc-windows/SKILL.md +++ b/.agents/skills/build-openshell-mxc-windows/SKILL.md @@ -192,10 +192,10 @@ The GitHub Actions jobs layer architecture-specific `Swatinem/rust-cache` entries for Cargo registry and dependency target artifacts with sccache's GHA backend for cacheable Rust compiler outputs. Failed runs also save their usable dependency artifacts. Pull-request mirrors and merge queues run Clippy for the -Windows-sensitive sandbox, core, and CLI crates plus Rust tests. Pushes to -`main` and manual dispatches run the same lint and test commands in a cache-seed -job, followed by a dependent release-binary build job. The seed and PR jobs use -the same cache namespaces. The binaries are not uploaded or published. +Windows gateway, core, and CLI crates plus Rust tests. Pushes to `main` and +manual dispatches run the same lint and test commands in a cache-seed job, +followed by a dependent release-binary build job. The seed and PR jobs use the +same cache namespaces. The binaries are not uploaded or published. The ARM64 check/build steps in this x64-host contract are cross-builds. The wrapper discovers and adds host-native LLVM and Ninja to `PATH`, requires the diff --git a/.agents/skills/build-openshell-mxc-windows/reference.md b/.agents/skills/build-openshell-mxc-windows/reference.md index a6a65966e..b362ae580 100644 --- a/.agents/skills/build-openshell-mxc-windows/reference.md +++ b/.agents/skills/build-openshell-mxc-windows/reference.md @@ -9,7 +9,7 @@ maintaining the existing build-only Windows MSVC lane. |---|---| | `tasks/windows.toml` | Mise task definitions for `windows:*`. | | `tasks/scripts/windows-msvc.ps1` | Visual Studio environment discovery, rustup target setup, Cargo invocation, logs, artifact report. | -| `.github/workflows/windows-msvc.yml` | PR/merge-queue lint for Windows-sensitive crates and x64 tests plus identical main/manual cache seeding followed by x64 binary builds. ARM64 remains local-only until it gets a native workflow. | +| `.github/workflows/windows-msvc.yml` | PR/merge-queue lint for the Windows gateway, core, and CLI crates plus x64 tests; main/manual runs seed the same caches before x64 binary builds. ARM64 remains local-only until it gets a native workflow. | | `architecture/windows-msvc-build.md` | Human-readable design contract. | ## Commands diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index f77dd2044..ca7cb4896 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -77,13 +77,15 @@ jobs: cache-bin: "false" - name: Lint Windows-sensitive crates # Formatting is target-independent and already checked by the Linux jobs. - # Keep this guard focused on Windows cfgs, matching the macOS lane. + # Keep this guard focused on the gateway and CLI deliverables plus core. run: >- cargo clippy - -p openshell-sandbox + -p openshell-server -p openshell-core -p openshell-cli --all-targets + --no-deps + --features openshell-prover/prebuilt-z3 -- -D warnings - name: Test run: mise run --skip-tools test:rust @@ -132,10 +134,12 @@ jobs: # target and compiler caches are reusable by subsequent pull requests. run: >- cargo clippy - -p openshell-sandbox + -p openshell-server -p openshell-core -p openshell-cli --all-targets + --no-deps + --features openshell-prover/prebuilt-z3 -- -D warnings - name: Test run: mise run --skip-tools test:rust diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index 674a06f46..0dac15964 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -48,12 +48,12 @@ creating misleading Windows driver artifacts. ## Mise Lane -The GitHub Actions workflow runs Clippy for the Windows-sensitive sandbox, -core, and CLI crates plus Rust tests for pull-request mirror branches and merge -queues. 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. +The GitHub Actions workflow runs Clippy for the Windows gateway, core, and CLI +crates plus Rust tests for pull-request mirror branches and merge queues. 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. @@ -139,7 +139,7 @@ The x64 GitHub Actions jobs run on `windows-2025`. Pull-request mirrors and merge queues execute: ```powershell -cargo clippy -p openshell-sandbox -p openshell-core -p openshell-cli --all-targets -- -D warnings +cargo clippy -p openshell-server -p openshell-core -p openshell-cli --all-targets --no-deps --features openshell-prover/prebuilt-z3 -- -D warnings mise run --skip-tools test:rust ``` diff --git a/crates/openshell-bootstrap/src/build_windows.rs b/crates/openshell-bootstrap/src/build_windows.rs index 0be12cd82..93af1345d 100644 --- a/crates/openshell-bootstrap/src/build_windows.rs +++ b/crates/openshell-bootstrap/src/build_windows.rs @@ -9,7 +9,7 @@ use std::path::Path; use miette::Result; // Keep this stub's signature aligned with the supported-platform implementation. -#[allow(clippy::implicit_hasher, clippy::unused_async)] +#[allow(clippy::implicit_hasher)] pub async fn build_local_image( _dockerfile_path: &Path, _tag: &str, diff --git a/crates/openshell-supervisor-network/src/identity.rs b/crates/openshell-supervisor-network/src/identity.rs index 0861f0096..5e89c3503 100644 --- a/crates/openshell-supervisor-network/src/identity.rs +++ b/crates/openshell-supervisor-network/src/identity.rs @@ -18,51 +18,55 @@ use std::path::{Path, PathBuf}; use std::sync::Mutex; use tracing::debug; -#[derive(Clone, PartialEq)] +#[derive(Clone)] struct FileFingerprint { len: u64, - #[cfg(unix)] mtime_sec: i64, - #[cfg(unix)] mtime_nsec: i64, - #[cfg(unix)] ctime_sec: i64, - #[cfg(unix)] ctime_nsec: i64, #[cfg(unix)] dev: u64, #[cfg(unix)] ino: u64, - #[cfg(not(unix))] - modified: Option, - #[cfg(not(unix))] - created: Option, } impl FileFingerprint { fn from_metadata(metadata: &Metadata) -> Self { Self { len: metadata.len(), - #[cfg(unix)] mtime_sec: metadata.mtime(), - #[cfg(unix)] mtime_nsec: metadata.mtime_nsec(), - #[cfg(unix)] ctime_sec: metadata.ctime(), - #[cfg(unix)] ctime_nsec: metadata.ctime_nsec(), #[cfg(unix)] dev: metadata.dev(), #[cfg(unix)] ino: metadata.ino(), - #[cfg(not(unix))] - modified: metadata.modified().ok(), - #[cfg(not(unix))] - created: metadata.created().ok(), } } } +impl PartialEq for FileFingerprint { + fn eq(&self, other: &Self) -> bool { + self.len == other.len + && self.mtime_sec == other.mtime_sec + && self.mtime_nsec == other.mtime_nsec + && self.ctime_sec == other.ctime_sec + && self.ctime_nsec == other.ctime_nsec + && { + #[cfg(unix)] + { + self.dev == other.dev && self.ino == other.ino + } + #[cfg(not(unix))] + { + true + } + } + } +} + #[derive(Clone)] struct CachedBinary { hash: String, From f1ca920a42986c132089e1a4afa9e4d8dbcb1d95 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:40:08 -0700 Subject: [PATCH 21/27] ci(windows): allow platform-gated lint Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 4 ++-- architecture/windows-msvc-build.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index ca7cb4896..cd5c96186 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -86,7 +86,7 @@ jobs: --all-targets --no-deps --features openshell-prover/prebuilt-z3 - -- -D warnings + -- -D warnings -A dead-code -A unused-imports -A clippy::unused-async - name: Test run: mise run --skip-tools test:rust - name: sccache stats @@ -140,7 +140,7 @@ jobs: --all-targets --no-deps --features openshell-prover/prebuilt-z3 - -- -D warnings + -- -D warnings -A dead-code -A unused-imports -A clippy::unused-async - name: Test run: mise run --skip-tools test:rust - name: sccache stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index 0dac15964..a63d3b965 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -139,7 +139,7 @@ The x64 GitHub Actions jobs run on `windows-2025`. Pull-request mirrors and merge queues execute: ```powershell -cargo clippy -p openshell-server -p openshell-core -p openshell-cli --all-targets --no-deps --features openshell-prover/prebuilt-z3 -- -D warnings +cargo clippy -p openshell-server -p openshell-core -p openshell-cli --all-targets --no-deps --features openshell-prover/prebuilt-z3 -- -D warnings -A dead-code -A unused-imports -A clippy::unused-async mise run --skip-tools test:rust ``` From 02b62b48aa05b8a5192ae9ad1c3f4e5defe55558 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 13 Aug 2026 17:53:22 -0700 Subject: [PATCH 22/27] test(otel): enable in-memory exporter Signed-off-by: Piotr Mlocek --- crates/openshell-otel/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/openshell-otel/Cargo.toml b/crates/openshell-otel/Cargo.toml index b53a71681..815598982 100644 --- a/crates/openshell-otel/Cargo.toml +++ b/crates/openshell-otel/Cargo.toml @@ -23,6 +23,7 @@ tonic = { workspace = true } tower-http = { workspace = true } [dev-dependencies] +opentelemetry_sdk = { workspace = true, features = ["testing"] } tokio = { workspace = true } [lints] From c144e377bc4184a6e6b6879087a05f184b96695f Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Fri, 14 Aug 2026 09:45:34 -0700 Subject: [PATCH 23/27] fix(windows): resolve platform lint warnings Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 4 +-- architecture/windows-msvc-build.md | 2 +- crates/openshell-core/src/config.rs | 12 ++++--- crates/openshell-server/src/auth/k8s_sa.rs | 35 +++++++++++++++++-- .../src/compute/driver_config.rs | 6 ++++ crates/openshell-server/src/compute/mod.rs | 16 ++++++--- crates/openshell-server/src/credentials.rs | 22 +++++++----- crates/openshell-server/src/lib.rs | 8 +++++ .../openshell-server/src/persistence/tests.rs | 4 ++- 9 files changed, 86 insertions(+), 23 deletions(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index cd5c96186..ca7cb4896 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -86,7 +86,7 @@ jobs: --all-targets --no-deps --features openshell-prover/prebuilt-z3 - -- -D warnings -A dead-code -A unused-imports -A clippy::unused-async + -- -D warnings - name: Test run: mise run --skip-tools test:rust - name: sccache stats @@ -140,7 +140,7 @@ jobs: --all-targets --no-deps --features openshell-prover/prebuilt-z3 - -- -D warnings -A dead-code -A unused-imports -A clippy::unused-async + -- -D warnings - name: Test run: mise run --skip-tools test:rust - name: sccache stats diff --git a/architecture/windows-msvc-build.md b/architecture/windows-msvc-build.md index a63d3b965..0dac15964 100644 --- a/architecture/windows-msvc-build.md +++ b/architecture/windows-msvc-build.md @@ -139,7 +139,7 @@ The x64 GitHub Actions jobs run on `windows-2025`. Pull-request mirrors and merge queues execute: ```powershell -cargo clippy -p openshell-server -p openshell-core -p openshell-cli --all-targets --no-deps --features openshell-prover/prebuilt-z3 -- -D warnings -A dead-code -A unused-imports -A clippy::unused-async +cargo clippy -p openshell-server -p openshell-core -p openshell-cli --all-targets --no-deps --features openshell-prover/prebuilt-z3 -- -D warnings mise run --skip-tools test:rust ``` diff --git a/crates/openshell-core/src/config.rs b/crates/openshell-core/src/config.rs index fcbdeb73b..cc1832242 100644 --- a/crates/openshell-core/src/config.rs +++ b/crates/openshell-core/src/config.rs @@ -1086,13 +1086,15 @@ mod tests { use super::{ ComputeDriverKind, Config, DEFAULT_SERVICE_ROUTING_DOMAIN, GatewayInterceptorBindingPolicy, GatewayInterceptorConfig, GatewayInterceptorFailurePolicy, GatewayJwtConfig, - GatewayProviderProfileSourceConfig, PolicyValidationFailureMode, - detect_docker_socket_from_candidates, detect_driver, detect_podman_socket_from_candidates, - docker_host_unix_socket_path, docker_socket_responds, normalize_compute_driver_name, - podman_socket_candidates_from_env, podman_socket_responds, + GatewayProviderProfileSourceConfig, PolicyValidationFailureMode, detect_driver, + docker_host_unix_socket_path, normalize_compute_driver_name, + podman_socket_candidates_from_env, }; #[cfg(unix)] - use super::{is_reachable_unix_socket, is_unix_socket}; + use super::{ + detect_docker_socket_from_candidates, detect_podman_socket_from_candidates, + docker_socket_responds, is_reachable_unix_socket, is_unix_socket, podman_socket_responds, + }; #[cfg(unix)] use std::io::{Read as _, Write as _}; use std::net::SocketAddr; diff --git a/crates/openshell-server/src/auth/k8s_sa.rs b/crates/openshell-server/src/auth/k8s_sa.rs index 32cb2e119..626593e4d 100644 --- a/crates/openshell-server/src/auth/k8s_sa.rs +++ b/crates/openshell-server/src/auth/k8s_sa.rs @@ -18,18 +18,27 @@ use super::authenticator::Authenticator; use super::principal::{Principal, SandboxIdentitySource, SandboxPrincipal}; use async_trait::async_trait; +#[cfg(any(not(target_os = "windows"), test))] use k8s_openapi::api::{ authentication::v1::{TokenReview, TokenReviewSpec, TokenReviewStatus, UserInfo}, core::v1::Pod, }; +#[cfg(any(not(target_os = "windows"), test))] use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta; +#[cfg(any(not(target_os = "windows"), test))] use kube::Error as KubeError; +#[cfg(not(target_os = "windows"))] use kube::api::{Api, ApiResource, PostParams}; -use kube::core::{DynamicObject, gvk::GroupVersionKind}; +#[cfg(any(not(target_os = "windows"), test))] +use kube::core::DynamicObject; +#[cfg(any(not(target_os = "windows"), test))] +use kube::core::gvk::GroupVersionKind; use openshell_driver_kubernetes::OperatorNamespaceAllowlist; use std::sync::Arc; use tonic::Status; -use tracing::{debug, info, warn}; +#[cfg(not(target_os = "windows"))] +use tracing::info; +use tracing::{debug, warn}; /// gRPC method path that this authenticator accepts. All other paths fall /// through (return `Ok(None)`) so a gateway-minted JWT is required there. @@ -40,15 +49,25 @@ pub const ISSUE_SANDBOX_TOKEN_PATH: &str = "/openshell.v1.OpenShell/IssueSandbox /// annotation only after validating the pod's `TokenReview` binding, live UID, /// and owning Sandbox CR. The K8s `Role` granted to the gateway must not /// include `patch pods` (see plan ยง11.8). +#[cfg(any(not(target_os = "windows"), test))] pub const SANDBOX_ID_ANNOTATION: &str = "openshell.io/sandbox-id"; +#[cfg(any(not(target_os = "windows"), test))] const SANDBOX_API_GROUP: &str = "agents.x-k8s.io"; +#[cfg(any(not(target_os = "windows"), test))] const SANDBOX_API_VERSION_V1BETA1: &str = "v1beta1"; +#[cfg(not(target_os = "windows"))] const SANDBOX_API_VERSION_V1ALPHA1: &str = "v1alpha1"; +#[cfg(any(not(target_os = "windows"), test))] const SANDBOX_API_VERSION_FULL_V1BETA1: &str = "agents.x-k8s.io/v1beta1"; +#[cfg(any(not(target_os = "windows"), test))] const SANDBOX_API_VERSION_FULL_V1ALPHA1: &str = "agents.x-k8s.io/v1alpha1"; +#[cfg(any(not(target_os = "windows"), test))] const SANDBOX_KIND: &str = "Sandbox"; +#[cfg(any(not(target_os = "windows"), test))] const SANDBOX_ID_LABEL: &str = "openshell.ai/sandbox-id"; +#[cfg(any(not(target_os = "windows"), test))] const POD_NAME_EXTRA: &str = "authentication.kubernetes.io/pod-name"; +#[cfg(any(not(target_os = "windows"), test))] const POD_UID_EXTRA: &str = "authentication.kubernetes.io/pod-uid"; /// Resolved identity extracted from a validated SA token + pod lookup. @@ -160,6 +179,7 @@ impl NamespaceValidator { } #[derive(Debug)] +#[cfg(any(not(target_os = "windows"), test))] struct TokenReviewIdentity { namespace: String, pod_name: String, @@ -167,6 +187,7 @@ struct TokenReviewIdentity { } #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg(any(not(target_os = "windows"), test))] struct SandboxOwnerReference { api_version: String, name: String, @@ -175,6 +196,7 @@ struct SandboxOwnerReference { /// Resolver backed by the apiserver's `TokenReview` API and `kube::Client` /// for the per-pod annotation lookup. +#[cfg(not(target_os = "windows"))] pub struct LiveK8sResolver { client: kube::Client, token_reviews_api: Api, @@ -183,6 +205,7 @@ pub struct LiveK8sResolver { expected_service_account: String, } +#[cfg(not(target_os = "windows"))] impl LiveK8sResolver { pub fn new( client: kube::Client, @@ -236,6 +259,7 @@ impl LiveK8sResolver { } #[async_trait] +#[cfg(not(target_os = "windows"))] impl K8sIdentityResolver for LiveK8sResolver { async fn resolve(&self, token: &str) -> Result, Status> { let review = TokenReview { @@ -342,6 +366,7 @@ impl K8sIdentityResolver for LiveK8sResolver { } #[allow(clippy::result_large_err)] +#[cfg(any(not(target_os = "windows"), test))] fn token_review_identity( status: &TokenReviewStatus, expected_audience: &str, @@ -425,6 +450,7 @@ fn parse_sa_username(username: &str) -> Option<(String, String)> { } #[allow(clippy::result_large_err)] +#[cfg(any(not(target_os = "windows"), test))] fn user_extra_one(user: &UserInfo, key: &str) -> Result { let Some(values) = user.extra.as_ref().and_then(|extra| extra.get(key)) else { return Err(Status::permission_denied("SA token is not pod-bound")); @@ -438,6 +464,7 @@ fn user_extra_one(user: &UserInfo, key: &str) -> Result { } #[allow(clippy::result_large_err)] +#[cfg(any(not(target_os = "windows"), test))] fn pod_sandbox_id(pod: &Pod) -> Result { let sandbox_id = pod .metadata @@ -455,6 +482,7 @@ fn pod_sandbox_id(pod: &Pod) -> Result { } #[allow(clippy::result_large_err)] +#[cfg(any(not(target_os = "windows"), test))] fn sandbox_owner_reference(pod: &Pod) -> Result { let owner_refs = pod.metadata.owner_references.as_deref().unwrap_or_default(); let mut sandbox_refs = owner_refs @@ -502,6 +530,7 @@ fn sandbox_owner_reference(pod: &Pod) -> Result { }) } +#[cfg(any(not(target_os = "windows"), test))] fn is_supported_sandbox_owner_reference( owner: &k8s_openapi::apimachinery::pkg::apis::meta::v1::OwnerReference, ) -> bool { @@ -512,6 +541,7 @@ fn is_supported_sandbox_owner_reference( ) } +#[cfg(any(not(target_os = "windows"), test))] fn should_try_next_sandbox_api_version(err: &KubeError) -> bool { // Kubernetes returns a structured 404 for some missing API resources and a // raw "404 page not found" body for others. Both mean the probed @@ -521,6 +551,7 @@ fn should_try_next_sandbox_api_version(err: &KubeError) -> bool { } #[allow(clippy::result_large_err)] +#[cfg(any(not(target_os = "windows"), test))] fn validate_sandbox_owner_reference( owner: &SandboxOwnerReference, sandbox_id: &str, diff --git a/crates/openshell-server/src/compute/driver_config.rs b/crates/openshell-server/src/compute/driver_config.rs index 9f4cac9a0..41845b8ff 100644 --- a/crates/openshell-server/src/compute/driver_config.rs +++ b/crates/openshell-server/src/compute/driver_config.rs @@ -37,8 +37,11 @@ impl From<&LocalTlsPaths> for GuestTlsPaths { #[derive(Clone, Copy)] pub struct DriverStartupContext<'a> { pub file: Option<&'a config_file::ConfigFile>, + #[cfg(not(target_os = "windows"))] pub guest_tls: Option<&'a GuestTlsPaths>, + #[cfg(not(target_os = "windows"))] pub gateway_port: u16, + #[cfg(not(target_os = "windows"))] pub gateway_tls_enabled: bool, pub endpoint_overrides: &'a BTreeMap, } @@ -125,8 +128,11 @@ mod tests { ) -> DriverStartupContext<'a> { DriverStartupContext { file, + #[cfg(not(target_os = "windows"))] guest_tls: None, + #[cfg(not(target_os = "windows"))] gateway_port: openshell_core::config::DEFAULT_SERVER_PORT, + #[cfg(not(target_os = "windows"))] gateway_tls_enabled: false, endpoint_overrides, } diff --git a/crates/openshell-server/src/compute/mod.rs b/crates/openshell-server/src/compute/mod.rs index e09b63de0..b5385d8b7 100644 --- a/crates/openshell-server/src/compute/mod.rs +++ b/crates/openshell-server/src/compute/mod.rs @@ -431,6 +431,7 @@ pub struct AcquiredRemoteDriverEndpoint { } impl AcquiredRemoteDriverEndpoint { + #[cfg(unix)] pub(crate) fn managed_builtin( driver_kind: ComputeDriverKind, channel: Channel, @@ -443,6 +444,7 @@ impl AcquiredRemoteDriverEndpoint { } } + #[cfg(unix)] pub(crate) fn unmanaged(name: impl Into, channel: Channel) -> Self { Self { name: name.into(), @@ -592,6 +594,7 @@ pub struct ComputeRuntime { driver_info: ComputeDriverInfoSnapshot, shutdown_cleanup: Option>, startup_starter: Option>, + #[cfg(unix)] driver_process: Option>, default_image: String, store: Arc, @@ -634,6 +637,8 @@ impl ComputeRuntime { tracing_log_bus: TracingLogBus, supervisor_sessions: Arc, ) -> Result { + #[cfg(not(unix))] + let _ = driver_process; let capabilities = driver .get_capabilities(Request::new(GetCapabilitiesRequest {})) .await @@ -713,6 +718,7 @@ impl ComputeRuntime { driver_info, shutdown_cleanup, startup_starter, + #[cfg(unix)] driver_process, default_image, store, @@ -3162,13 +3168,13 @@ pub async fn connect_remote_compute_driver( } #[cfg(not(unix))] -pub async fn connect_remote_compute_driver( +pub fn connect_remote_compute_driver( _name: impl Into, _socket_path: &Path, -) -> Result { - Err(ComputeError::Message( +) -> std::future::Ready> { + std::future::ready(Err(ComputeError::Message( "remote compute driver endpoints require unix domain socket support".to_string(), - )) + ))) } fn driver_sandbox_from_public( @@ -3996,6 +4002,7 @@ pub async fn new_test_runtime_with_driver( }, shutdown_cleanup: None, startup_starter: None, + #[cfg(unix)] driver_process: None, default_image: "openshell/sandbox:test".to_string(), store, @@ -4648,6 +4655,7 @@ mod tests { }, shutdown_cleanup: None, startup_starter, + #[cfg(unix)] driver_process: None, default_image: "openshell/sandbox:test".to_string(), store, diff --git a/crates/openshell-server/src/credentials.rs b/crates/openshell-server/src/credentials.rs index 71503f3bf..0f8ad3865 100644 --- a/crates/openshell-server/src/credentials.rs +++ b/crates/openshell-server/src/credentials.rs @@ -26,9 +26,12 @@ use async_trait::async_trait; #[cfg(unix)] use hyper_util::rt::TokioIo; use openshell_core::proto::credentials::v1::{ - DeleteCredentialRequest, GetCredentialDriverCapabilitiesRequest, - GetCredentialDriverCapabilitiesResponse, ResolveCredentialRequest, ResolveCredentialsRequest, - ResolvedCredential, StoreCredentialRequest, credential_driver_client::CredentialDriverClient, + DeleteCredentialRequest, ResolveCredentialRequest, ResolvedCredential, StoreCredentialRequest, +}; +#[cfg(unix)] +use openshell_core::proto::credentials::v1::{ + GetCredentialDriverCapabilitiesRequest, GetCredentialDriverCapabilitiesResponse, + ResolveCredentialsRequest, credential_driver_client::CredentialDriverClient, }; use openshell_core::proto::{CredentialHandle, Provider}; use openshell_core::{Config, Error, Result as CoreResult}; @@ -43,8 +46,10 @@ use tokio::net::UnixStream; #[cfg(unix)] use tokio::process::Command; #[cfg(unix)] +use tonic::Request; +use tonic::Status; +#[cfg(unix)] use tonic::transport::{Channel, Endpoint}; -use tonic::{Request, Status}; #[cfg(unix)] use tower::service_fn; use tracing::warn; @@ -52,6 +57,7 @@ use tracing::warn; use crate::persistence::{PersistenceError, Store, WriteCondition}; const DEFAULT_CREDENTIAL_DRIVER_STARTUP_TIMEOUT_SECS: u64 = 10; +#[cfg(unix)] const DEFAULT_CREDENTIAL_DRIVER_RPC_TIMEOUT_SECS: u64 = 30; const COMMON_CREDENTIAL_DRIVER_FIELDS: &[&str] = &[ "transport", @@ -1253,14 +1259,14 @@ async fn connect_uds_driver( } #[cfg(not(unix))] -async fn connect_uds_driver( +fn connect_uds_driver( driver_name: &str, _config: ConfiguredCredentialDriver, _socket_path: &Path, -) -> CoreResult { - Err(Error::config(format!( +) -> std::future::Ready> { + std::future::ready(Err(Error::config(format!( "credential driver '{driver_name}' uses transport = 'uds', but this platform does not support Unix domain sockets" - ))) + )))) } #[cfg(unix)] diff --git a/crates/openshell-server/src/lib.rs b/crates/openshell-server/src/lib.rs index a6031a9bc..4470345a9 100644 --- a/crates/openshell-server/src/lib.rs +++ b/crates/openshell-server/src/lib.rs @@ -585,8 +585,11 @@ pub(crate) async fn run_server( let supervisor_sessions = Arc::new(supervisor_session::SupervisorSessionRegistry::new()); let driver_startup = compute::driver_config::DriverStartupContext { file: config_file.as_ref(), + #[cfg(not(target_os = "windows"))] guest_tls: guest_tls.as_ref(), + #[cfg(not(target_os = "windows"))] gateway_port: config.bind_address.port(), + #[cfg(not(target_os = "windows"))] gateway_tls_enabled: config.tls.is_some(), endpoint_overrides: &config.compute_driver_endpoints, }; @@ -1267,6 +1270,7 @@ fn builtin_compute_driver(name: &str) -> Option { name.parse().ok() } +#[cfg(not(target_os = "windows"))] fn kubernetes_sandbox_jwt_expiry_disabled(config: &Config) -> bool { config .gateway_jwt @@ -1274,6 +1278,7 @@ fn kubernetes_sandbox_jwt_expiry_disabled(config: &Config) -> bool { .is_some_and(|jwt| jwt.ttl_secs == 0) } +#[cfg(not(target_os = "windows"))] fn warn_if_kubernetes_sandbox_jwt_expiry_disabled(config: &Config) { if kubernetes_sandbox_jwt_expiry_disabled(config) { warn!( @@ -1467,8 +1472,11 @@ mod tests { ) -> crate::compute::driver_config::DriverStartupContext<'a> { crate::compute::driver_config::DriverStartupContext { file, + #[cfg(not(target_os = "windows"))] guest_tls: None, + #[cfg(not(target_os = "windows"))] gateway_port: openshell_core::config::DEFAULT_SERVER_PORT, + #[cfg(not(target_os = "windows"))] gateway_tls_enabled: false, endpoint_overrides: &config.compute_driver_endpoints, } diff --git a/crates/openshell-server/src/persistence/tests.rs b/crates/openshell-server/src/persistence/tests.rs index 6227eec29..fd3aea350 100644 --- a/crates/openshell-server/src/persistence/tests.rs +++ b/crates/openshell-server/src/persistence/tests.rs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -use super::{ObjectType, PersistenceError, Store, generate_name, test_store}; +#[cfg(unix)] +use super::Store; +use super::{ObjectType, PersistenceError, generate_name, test_store}; use crate::policy_store::{AtomicPolicyRevisionWrite, PolicyStoreExt}; use openshell_core::proto::datamodel::v1::ObjectMeta as ProtoObjectMeta; use openshell_core::proto::{ObjectForTest, Sandbox, SandboxPolicy, SandboxSpec}; From 089e4b48a908893928277c2b3b12a0ddd1b34c42 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Fri, 14 Aug 2026 09:56:35 -0700 Subject: [PATCH 24/27] fix(windows): scope test-only server code Signed-off-by: Piotr Mlocek --- crates/openshell-server/src/auth/k8s_sa.rs | 8 ++++++-- crates/openshell-server/src/lib.rs | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/openshell-server/src/auth/k8s_sa.rs b/crates/openshell-server/src/auth/k8s_sa.rs index 626593e4d..72bce5804 100644 --- a/crates/openshell-server/src/auth/k8s_sa.rs +++ b/crates/openshell-server/src/auth/k8s_sa.rs @@ -18,17 +18,21 @@ use super::authenticator::Authenticator; use super::principal::{Principal, SandboxIdentitySource, SandboxPrincipal}; use async_trait::async_trait; +#[cfg(not(target_os = "windows"))] +use k8s_openapi::api::authentication::v1::{TokenReview, TokenReviewSpec}; #[cfg(any(not(target_os = "windows"), test))] use k8s_openapi::api::{ - authentication::v1::{TokenReview, TokenReviewSpec, TokenReviewStatus, UserInfo}, + authentication::v1::{TokenReviewStatus, UserInfo}, core::v1::Pod, }; #[cfg(any(not(target_os = "windows"), test))] use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta; #[cfg(any(not(target_os = "windows"), test))] use kube::Error as KubeError; +#[cfg(any(not(target_os = "windows"), test))] +use kube::api::ApiResource; #[cfg(not(target_os = "windows"))] -use kube::api::{Api, ApiResource, PostParams}; +use kube::api::{Api, PostParams}; #[cfg(any(not(target_os = "windows"), test))] use kube::core::DynamicObject; #[cfg(any(not(target_os = "windows"), test))] diff --git a/crates/openshell-server/src/lib.rs b/crates/openshell-server/src/lib.rs index 4470345a9..ecf97a0da 100644 --- a/crates/openshell-server/src/lib.rs +++ b/crates/openshell-server/src/lib.rs @@ -442,7 +442,10 @@ pub(crate) async fn run_server( let ServerStartupConfig { config, config_file, + #[cfg(not(target_os = "windows"))] guest_tls, + #[cfg(target_os = "windows")] + guest_tls: _, } = startup; let (shutdown_tx, shutdown_rx) = watch::channel(false); @@ -1270,7 +1273,7 @@ fn builtin_compute_driver(name: &str) -> Option { name.parse().ok() } -#[cfg(not(target_os = "windows"))] +#[cfg(any(not(target_os = "windows"), test))] fn kubernetes_sandbox_jwt_expiry_disabled(config: &Config) -> bool { config .gateway_jwt From bdecb16200de26a8a5093cfa91555d29d68cc318 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Fri, 14 Aug 2026 10:01:45 -0700 Subject: [PATCH 25/27] fix(windows): omit unused guest TLS state Signed-off-by: Piotr Mlocek --- crates/openshell-server/src/cli.rs | 5 +++++ crates/openshell-server/src/lib.rs | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/openshell-server/src/cli.rs b/crates/openshell-server/src/cli.rs index 2e86c3a1b..b2936f591 100644 --- a/crates/openshell-server/src/cli.rs +++ b/crates/openshell-server/src/cli.rs @@ -14,6 +14,7 @@ use tracing::{error, info, warn}; use tracing_subscriber::EnvFilter; use crate::certgen; +#[cfg(not(target_os = "windows"))] use crate::compute::driver_config::GuestTlsPaths; use crate::config_file::{self, ConfigFile, GatewayFileSection}; use crate::defaults::{self, LocalTlsPaths}; @@ -248,7 +249,10 @@ fn prepare_server_config(args: &mut RunArgs, matches: &ArgMatches) -> Result Result, + #[cfg(not(target_os = "windows"))] pub guest_tls: Option, } @@ -444,8 +445,6 @@ pub(crate) async fn run_server( config_file, #[cfg(not(target_os = "windows"))] guest_tls, - #[cfg(target_os = "windows")] - guest_tls: _, } = startup; let (shutdown_tx, shutdown_rx) = watch::channel(false); From 2fdb6ec0e5e4f860240894731710a5afd65e1fea Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Fri, 14 Aug 2026 10:05:48 -0700 Subject: [PATCH 26/27] fix(windows): omit Unix guest TLS paths Signed-off-by: Piotr Mlocek --- crates/openshell-server/src/compute/driver_config.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/openshell-server/src/compute/driver_config.rs b/crates/openshell-server/src/compute/driver_config.rs index 41845b8ff..5ef30a3e3 100644 --- a/crates/openshell-server/src/compute/driver_config.rs +++ b/crates/openshell-server/src/compute/driver_config.rs @@ -11,6 +11,7 @@ pub mod builtin; use crate::config_file; +#[cfg(not(target_os = "windows"))] use crate::defaults::LocalTlsPaths; use openshell_core::{Error, Result}; use serde::Deserialize; @@ -18,12 +19,14 @@ use std::collections::BTreeMap; use std::path::PathBuf; #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg(not(target_os = "windows"))] pub struct GuestTlsPaths { ca: PathBuf, cert: PathBuf, key: PathBuf, } +#[cfg(not(target_os = "windows"))] impl From<&LocalTlsPaths> for GuestTlsPaths { fn from(paths: &LocalTlsPaths) -> Self { Self { From e5f0d0172911b3c957d9f8894d9249213ffea876 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Tue, 18 Aug 2026 16:34:34 -0700 Subject: [PATCH 27/27] chore(ci): align Windows cache action with main Signed-off-by: Piotr Mlocek --- .github/workflows/windows-msvc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml index ca7cb4896..63ec10e51 100644 --- a/.github/workflows/windows-msvc.yml +++ b/.github/workflows/windows-msvc.yml @@ -121,7 +121,7 @@ jobs: targets: x86_64-pc-windows-msvc components: clippy - name: Cache Rust target and registry - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 env: RUSTC_WRAPPER: "" with: @@ -170,7 +170,7 @@ jobs: toolchain: "1.95.0" targets: x86_64-pc-windows-msvc - name: Cache Rust target and registry - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 env: RUSTC_WRAPPER: "" with: