From db42c57450deccf37b97a4ec7be1abedde73da2d Mon Sep 17 00:00:00 2001 From: Shailendra Singh Date: Mon, 1 Jun 2026 11:14:24 -0700 Subject: [PATCH] ci(windows): add MSVC mise build lane Signed-off-by: Shailendra Singh Signed-off-by: Akber Raza --- .github/workflows/windows-msvc.yml | 36 +++++ tasks/scripts/windows-msvc.ps1 | 244 +++++++++++++++++++++++++++++ tasks/windows.toml | 55 +++++++ 3 files changed, 335 insertions(+) create mode 100644 .github/workflows/windows-msvc.yml create mode 100644 tasks/scripts/windows-msvc.ps1 create mode 100644 tasks/windows.toml diff --git a/.github/workflows/windows-msvc.yml b/.github/workflows/windows-msvc.yml new file mode 100644 index 000000000..076af08a8 --- /dev/null +++ b/.github/workflows/windows-msvc.yml @@ -0,0 +1,36 @@ +name: Windows MSVC (build-only) +on: + push: + branches: [main] + pull_request: +jobs: + x64: + runs-on: windows-2025 + steps: + - uses: actions/checkout@v4 + - uses: jdx/mise-action@v3 + with: + install: false + experimental: true + - uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-pc-windows-msvc + - 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 + 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 + steps: + - uses: actions/checkout@v4 + - uses: jdx/mise-action@v3 + with: + install: false + experimental: true + - uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-pc-windows-msvc + - run: mise run --skip-tools windows:check:arm64 + - run: mise run --skip-tools windows:build:arm64 diff --git a/tasks/scripts/windows-msvc.ps1 b/tasks/scripts/windows-msvc.ps1 new file mode 100644 index 000000000..ad67b4b06 --- /dev/null +++ b/tasks/scripts/windows-msvc.ps1 @@ -0,0 +1,244 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Windows MSVC build wrapper used by the `windows:*` mise tasks. + +[CmdletBinding()] +param( + [Parameter(Mandatory = $true, Position = 0)] + [ValidateSet("check", "build", "test", "test-unsupported", "artifacts", "ci")] + [string] $Action, + + [Parameter(Position = 1)] + [ValidateSet("x86_64-pc-windows-msvc", "aarch64-pc-windows-msvc", "all")] + [string] $Target = "all", + + [string] $LogDir +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +if (-not [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Windows)) { + throw "windows-msvc.ps1 requires a Windows MSVC host." +} + +$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path +if (-not $LogDir) { + $LogDir = $RepoRoot +} +if (-not (Test-Path $LogDir)) { + New-Item -ItemType Directory -Force -Path $LogDir | Out-Null +} +$LogDir = (Resolve-Path $LogDir).Path + +$TargetDir = $env:CARGO_TARGET_DIR +if ([string]::IsNullOrWhiteSpace($TargetDir)) { + $TargetDir = Join-Path $RepoRoot "target" +} + +$UnsupportedDriverPackageExcludes = "--exclude openshell-driver-docker --exclude openshell-driver-kubernetes --exclude openshell-driver-podman --exclude openshell-driver-vm" + +function Resolve-VsDevCmd { + if ($env:OPENSHELL_VSDEVCMD -and (Test-Path $env:OPENSHELL_VSDEVCMD)) { + return (Resolve-Path $env:OPENSHELL_VSDEVCMD).Path + } + + $programFilesX86 = [Environment]::GetEnvironmentVariable("ProgramFiles(x86)") + if ($programFilesX86) { + $vswhere = Join-Path $programFilesX86 "Microsoft Visual Studio\Installer\vswhere.exe" + } else { + $vswhere = $null + } + if ($vswhere -and (Test-Path $vswhere)) { + $found = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find "Common7\Tools\VsDevCmd.bat" | Select-Object -First 1 + if ($found -and (Test-Path $found)) { + return (Resolve-Path $found).Path + } + } + + $programFiles = @( + [Environment]::GetEnvironmentVariable("ProgramFiles"), + [Environment]::GetEnvironmentVariable("ProgramFiles(x86)") + ) | Where-Object { $_ } + $versions = @("18", "17") + $editions = @("Enterprise", "Professional", "Community", "BuildTools") + foreach ($root in $programFiles) { + foreach ($version in $versions) { + foreach ($edition in $editions) { + $candidate = Join-Path $root "Microsoft Visual Studio\$version\$edition\Common7\Tools\VsDevCmd.bat" + if (Test-Path $candidate) { + return (Resolve-Path $candidate).Path + } + } + } + } + + throw "Could not find VsDevCmd.bat. Install Visual Studio Build Tools, or set OPENSHELL_VSDEVCMD." +} + +function Get-HostArch { + switch ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()) { + "Arm64" { "arm64" } + default { "amd64" } + } +} + +function Get-VsTargetArch([string] $RustTarget) { + switch ($RustTarget) { + "x86_64-pc-windows-msvc" { "amd64" } + "aarch64-pc-windows-msvc" { "arm64" } + default { throw "Unsupported target: $RustTarget" } + } +} + +function Get-SelectedTargets([string] $RequestedTarget) { + if ($RequestedTarget -eq "all") { + $targets = @("x86_64-pc-windows-msvc") + if ($env:OPENSHELL_MXC_SKIP_ARM64 -ne "1") { + $targets += "aarch64-pc-windows-msvc" + } + return $targets + } + return @($RequestedTarget) +} + +function Invoke-VsCargo { + param( + [Parameter(Mandatory = $true)] [string] $RustTarget, + [Parameter(Mandatory = $true)] [string] $CargoArgs, + [Parameter(Mandatory = $true)] [string] $LogName + ) + + & rustup target add $RustTarget + if ($LASTEXITCODE -ne 0) { + throw "rustup target add $RustTarget failed" + } + + $vsDevCmd = Resolve-VsDevCmd + $targetArch = Get-VsTargetArch $RustTarget + $hostArch = Get-HostArch + $logPath = Join-Path $LogDir $LogName + $cmd = "call `"$vsDevCmd`" -arch=$targetArch -host_arch=$hostArch && set `"CARGO_TARGET_DIR=$TargetDir`" && set `"CARGO_INCREMENTAL=0`" && set `"RUSTC_WRAPPER=`" && $CargoArgs" + + Write-Host "==> $CargoArgs" + Write-Host " target: $RustTarget" + Write-Host " log: $logPath" + + $cmdWithLog = "$cmd > `"$logPath`" 2>&1" + & cmd /v:on /d /c $cmdWithLog + $exitCode = $LASTEXITCODE + if (Test-Path $logPath) { + Get-Content $logPath + } + if ($exitCode -ne 0) { + throw "Command failed with exit code $exitCode. See $logPath" + } +} + +function Invoke-Check([string] $RustTarget) { + Invoke-VsCargo ` + -RustTarget $RustTarget ` + -CargoArgs "cargo check --workspace $UnsupportedDriverPackageExcludes --target $RustTarget" ` + -LogName "build-$RustTarget-check.log" +} + +function Invoke-Build([string] $RustTarget) { + Invoke-VsCargo ` + -RustTarget $RustTarget ` + -CargoArgs "cargo build --release --target $RustTarget --bin openshell-gateway --bin openshell" ` + -LogName "build-$RustTarget-release.log" +} + +function Invoke-Test([string] $RustTarget) { + if ($RustTarget -ne "x86_64-pc-windows-msvc") { + throw "Windows ARM64 tests require a native ARM64 runner and are not part of this build-only lane." + } + Invoke-VsCargo ` + -RustTarget $RustTarget ` + -CargoArgs "cargo test --workspace $UnsupportedDriverPackageExcludes --target $RustTarget --no-fail-fast" ` + -LogName "test-$RustTarget.log" +} + +function Invoke-UnsupportedContractTests([string] $RustTarget) { + if ($RustTarget -ne "x86_64-pc-windows-msvc") { + throw "Unsupported-driver contract tests run only on the native x64 Windows lane." + } + + $tests = @( + "windows_compute_driver_stubs_report_unsupported", + "windows_spawn_reports_unsupported" + ) + foreach ($test in $tests) { + Invoke-VsCargo ` + -RustTarget $RustTarget ` + -CargoArgs "cargo test -p openshell-server --target $RustTarget $test" ` + -LogName "test-$RustTarget-unsupported-$test.log" + } +} + +function Show-Artifacts([string[]] $RustTargets) { + $rows = @() + foreach ($rustTarget in $RustTargets) { + foreach ($binary in @("openshell-gateway.exe", "openshell.exe")) { + $path = Join-Path $TargetDir "$rustTarget\release\$binary" + if (-not (Test-Path $path)) { + continue + } + $item = Get-Item $path + $hash = Get-FileHash $path -Algorithm SHA256 + $rows += [pscustomobject]@{ + Target = $rustTarget + Binary = $binary + Size = $item.Length + SHA256 = $hash.Hash + Path = $item.FullName + } + } + } + if ($rows.Count -eq 0) { + Write-Warning "No release artifacts found under $TargetDir" + return + } + $rows | Format-Table -AutoSize +} + +$targets = Get-SelectedTargets $Target + +switch ($Action) { + "check" { + foreach ($rustTarget in $targets) { + Invoke-Check $rustTarget + } + } + "build" { + foreach ($rustTarget in $targets) { + Invoke-Build $rustTarget + } + Show-Artifacts $targets + } + "test" { + foreach ($rustTarget in $targets) { + Invoke-Test $rustTarget + } + } + "test-unsupported" { + foreach ($rustTarget in $targets) { + Invoke-UnsupportedContractTests $rustTarget + } + } + "artifacts" { + Show-Artifacts $targets + } + "ci" { + foreach ($rustTarget in $targets) { + Invoke-Check $rustTarget + } + foreach ($rustTarget in $targets) { + Invoke-Build $rustTarget + } + Invoke-Test "x86_64-pc-windows-msvc" + Invoke-UnsupportedContractTests "x86_64-pc-windows-msvc" + Show-Artifacts $targets + } +} diff --git a/tasks/windows.toml b/tasks/windows.toml new file mode 100644 index 000000000..fa3b2b60a --- /dev/null +++ b/tasks/windows.toml @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Windows MSVC build-only tasks. These intentionally live outside the default +# Linux/macOS `ci` task so the established Linux build path remains unchanged. + +["windows:check"] +description = "Check Windows x64 and ARM64 MSVC targets" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 check all" + +["windows:check:x64"] +description = "Check Windows x64 MSVC target" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 check x86_64-pc-windows-msvc" + +["windows:check:arm64"] +description = "Check Windows ARM64 MSVC target" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 check aarch64-pc-windows-msvc" + +["windows:build"] +description = "Build Windows x64 and ARM64 release binaries" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 build all" + +["windows:build:x64"] +description = "Build Windows x64 release binaries" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 build x86_64-pc-windows-msvc" + +["windows:build:arm64"] +description = "Build Windows ARM64 release binaries" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 build aarch64-pc-windows-msvc" + +["windows:test:x64"] +description = "Run Windows x64 MSVC workspace tests" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 test x86_64-pc-windows-msvc" + +["windows:test:unsupported:x64"] +description = "Run focused Windows unsupported compute-driver contract tests" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 test-unsupported x86_64-pc-windows-msvc" + +["windows:artifacts"] +description = "Report Windows release artifact sizes and SHA256 hashes" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 artifacts all" + +["windows:ci"] +description = "Run Windows MSVC checks, release builds, x64 tests, and unsupported-driver contract tests" +run = "echo 'windows:* tasks require a Windows MSVC host' && exit 1" +run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 ci all"