Prepare Windows natives with scoped compiler settings and measure servicing (#28881)

* Scope Windows native compiler setup and measure ARM inbox preparation

* Add a controlled Windows native preparation comparison

* Test native preparation through an injected process runner

* Guard reviewed Windows native batch runners
This commit is contained in:
Neil
2026-10-14 18:18:24 -07:00
committed by GitHub
parent 3b11b7ac94
commit f23fa8ca76
22 changed files with 1890 additions and 51 deletions
@@ -54,7 +54,7 @@ runs:
env:
NATIVE_RUNTIME: ${{ inputs.native-runtime }}
NODE_VERSION: ${{ inputs.node-version }}
NATIVE_SOURCE_HASH: ${{ hashFiles('pnpm-lock.yaml', 'pnpm-workspace.yaml', '.npmrc', '.pnpmfile.cjs', '.github/actions/prepare-native-runtime/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/scripts/node-pty-job-ownership.cjs', 'config/scripts/windows-pe-machine.cjs', 'config/scripts/windows-process-tree-gyp-rebuild.mjs', 'config/scripts/windows-process-tree-creation-time.cjs', 'config/scripts/install-electron-package-binary.mjs', 'config/scripts/electron-platform-path.mjs', 'config/scripts/zip-extractor-command.mjs', 'src/shared/zip-extractor-command.ts', 'config/scripts/shared-electron-dist-cache.mjs', 'config/scripts/space-sharing-copy.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch', 'native/windows-registry/src/addon.cc', 'native/windows-registry/binding.gyp', 'native/windows-registry/package.json', 'native/windows-registry/index.js', 'native/windows-security/src/addon.cc', 'native/windows-security/binding.gyp', 'native/windows-security/package.json', 'native/windows-security/index.js') }}
NATIVE_SOURCE_HASH: ${{ hashFiles('pnpm-lock.yaml', 'pnpm-workspace.yaml', '.npmrc', '.pnpmfile.cjs', '.github/actions/prepare-native-runtime/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/initialize-windows-native-toolchain.mjs', 'config/scripts/capture-windows-native-environment.cmd', 'config/scripts/rebuild-native-deps.mjs', 'config/scripts/node-pty-job-ownership.cjs', 'config/scripts/windows-pe-machine.cjs', 'config/scripts/windows-process-tree-gyp-rebuild.mjs', 'config/scripts/windows-process-tree-creation-time.cjs', 'config/scripts/install-electron-package-binary.mjs', 'config/scripts/electron-platform-path.mjs', 'config/scripts/zip-extractor-command.mjs', 'src/shared/zip-extractor-command.ts', 'config/scripts/shared-electron-dist-cache.mjs', 'config/scripts/space-sharing-copy.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch', 'native/windows-registry/src/addon.cc', 'native/windows-registry/binding.gyp', 'native/windows-registry/package.json', 'native/windows-registry/index.js', 'native/windows-security/src/addon.cc', 'native/windows-security/binding.gyp', 'native/windows-security/package.json', 'native/windows-security/index.js') }}
run: |
scope="${ImageOS:-$RUNNER_OS}"
if [ -r /etc/os-release ]; then
@@ -120,4 +120,9 @@ runs:
shell: bash
env:
NATIVE_RUNTIME: ${{ inputs.native-runtime }}
run: node config/scripts/ensure-native-runtime.mjs --runtime="$NATIVE_RUNTIME"
run: |
if [ "$RUNNER_OS" = Windows ] && [ "$NATIVE_RUNTIME" = node ]; then
node config/scripts/initialize-windows-native-toolchain.mjs
else
node config/scripts/ensure-native-runtime.mjs --runtime="$NATIVE_RUNTIME"
fi
@@ -54,6 +54,7 @@ jobs:
run: node config/scripts/ensure-native-runtime.mjs --check-only
- name: Cache Windows CLI launcher
if: runner.arch == 'X64'
uses: actions/cache@v5
with:
path: |
@@ -65,6 +66,7 @@ jobs:
key: windows-cli-launcher-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('native/windows-cli-launcher/**', 'native/windows-agent-hook/**', 'config/scripts/build-windows-cli-launcher.mjs', 'config/scripts/build-windows-agent-hook.mjs', 'config/scripts/windows-rust-executable-build.mjs', 'resources/build/icon.ico', 'package.json') }}
- name: Build the Windows native executables
if: runner.arch == 'X64'
shell: pwsh
run: |
if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) {
@@ -76,6 +78,12 @@ jobs:
node config/scripts/build-windows-cli-launcher.mjs
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Warm the Windows ARM server launcher
if: runner.arch == 'ARM64'
uses: ./.github/actions/prepare-windows-cli-launcher
with:
arches: arm64
warm-linux-package-fixtures:
concurrency:
group: ci-cache-warmup-linux-package-fixtures-${{ github.event.pull_request.number || github.ref }}
@@ -10,6 +10,7 @@ on:
- '.github/actions/install-node-dependencies/**'
- '.github/actions/restore-pnpm-verification/**'
- '.github/actions/prepare-native-runtime/**'
- '.github/actions/prepare-windows-cli-launcher/**'
- '.github/actions/prepare-git-compatibility/**'
- '.github/actions/prepare-linux-package-fixture/**'
- 'config/docker/headless-serve-shutdown/**'
@@ -21,6 +22,8 @@ on:
- '.npmrc'
- '.pnpmfile.cjs'
- 'config/scripts/ensure-native-runtime.mjs'
- 'config/scripts/initialize-windows-native-toolchain.mjs'
- 'config/scripts/capture-windows-native-environment.cmd'
- 'config/scripts/rebuild-native-deps.mjs'
- 'config/scripts/node-pty-job-ownership.cjs'
- 'config/scripts/windows-pe-machine.cjs'
+3
View File
@@ -14,6 +14,7 @@ on:
- '.github/actions/install-node-dependencies/**'
- '.github/actions/restore-pnpm-verification/**'
- '.github/actions/prepare-native-runtime/**'
- '.github/actions/prepare-windows-cli-launcher/**'
- '.github/actions/prepare-git-compatibility/**'
- '.github/actions/prepare-headless-compiler/**'
- 'config/scripts/headless-detector-compiler-cache.mjs'
@@ -30,6 +31,8 @@ on:
- '.npmrc'
- '.pnpmfile.cjs'
- 'config/scripts/ensure-native-runtime.mjs'
- 'config/scripts/initialize-windows-native-toolchain.mjs'
- 'config/scripts/capture-windows-native-environment.cmd'
- 'config/scripts/rebuild-native-deps.mjs'
- 'config/scripts/node-pty-job-ownership.cjs'
- 'config/scripts/windows-pe-machine.cjs'
+27 -18
View File
@@ -62,12 +62,23 @@ on:
description: Comma-separated cell ids from src/main/ssh/ssh-windows-host-cells.ts; empty runs the default set (orcad-cli-* cells run only when named).
required: false
default: ''
preparation_mode:
description: Compare inbox capability preparation overlapping builds or running after them.
type: choice
options: [overlap, serial]
required: false
default: overlap
arm_inbox_only:
description: Run only the native ARM inbox lane for a preparation timing comparison.
type: boolean
required: false
default: false
permissions:
contents: read
concurrency:
group: ssh-windows-hosts-${{ github.event.pull_request.number || github.ref }}
group: ssh-windows-hosts-${{ github.event.pull_request.number || github.ref }}${{ github.event_name == 'workflow_dispatch' && inputs.arm_inbox_only && format('-{0}', inputs.preparation_mode || 'overlap') || '' }}
cancel-in-progress: true
jobs:
@@ -77,21 +88,10 @@ jobs:
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: windows-2022
server: inbox
- arch: x64
runner: windows-2022
server: preview
archive: OpenSSH-Win64.zip
- arch: arm64
runner: windows-11-arm
server: inbox
- arch: arm64
runner: windows-11-arm
server: preview
archive: OpenSSH-ARM64.zip
include: >-
${{ fromJSON(github.event_name == 'workflow_dispatch' && inputs.arm_inbox_only &&
'[{"arch":"arm64","runner":"windows-11-arm","server":"inbox"}]' ||
'[{"arch":"x64","runner":"windows-2022","server":"inbox"},{"arch":"x64","runner":"windows-2022","server":"preview","archive":"OpenSSH-Win64.zip"},{"arch":"arm64","runner":"windows-11-arm","server":"inbox"},{"arch":"arm64","runner":"windows-11-arm","server":"preview","archive":"OpenSSH-ARM64.zip"}]') }}
runs-on: ${{ matrix.runner }}
# Installing the inbox capability alone can take several minutes on a fresh image; the CLI matrix
# cells launch the e2e app several times each.
@@ -99,6 +99,7 @@ jobs:
env:
ORCA_BACKGROUND_LAUNCH: '1'
ORCA_ISOLATED_SSH_CI: '1'
INBOX_PREPARATION_MODE: ${{ github.event_name == 'workflow_dispatch' && inputs.preparation_mode == 'serial' && 'serial' || 'overlap' }}
steps:
- uses: actions/checkout@v6
with:
@@ -127,11 +128,11 @@ jobs:
background: true
shell: pwsh
run: |
if('${{ matrix.server }}' -eq 'inbox' -and '${{ matrix.arch }}' -eq 'arm64'){
if('${{ matrix.server }}' -eq 'inbox' -and '${{ matrix.arch }}' -eq 'arm64' -and $env:INBOX_PREPARATION_MODE -eq 'overlap'){
$receipts=Join-Path $pwd '.build/ssh-windows-host-receipts'
New-Item -ItemType Directory -Force -Path $receipts | Out-Null
. config/ci/windows-ssh-provider/preview-ssh/windows-ssh-capability.ps1
Initialize-WindowsInboxSshCapability -Arch '${{ matrix.arch }}' -Receipt (Join-Path $receipts 'inbox-capability-preparation.json')
Initialize-WindowsInboxSshCapability -Arch '${{ matrix.arch }}' -Receipt (Join-Path $receipts 'inbox-capability-preparation.json') -PreparationMode $env:INBOX_PREPARATION_MODE
}
- uses: ./.github/actions/install-node-dependencies
id: dependencies
@@ -164,6 +165,14 @@ jobs:
pnpm build:orcad-prebuilds --require-slots "win32-${{ matrix.arch }}"
node config/scripts/build-orcad-template.mjs --targets "win32-${{ matrix.arch }}"
- wait: inbox-capability
- name: Prepare the Windows inbox SSH capability after the builds
if: ${{ matrix.server == 'inbox' && matrix.arch == 'arm64' && env.INBOX_PREPARATION_MODE == 'serial' }}
shell: pwsh
run: |
$receipts=Join-Path $pwd '.build/ssh-windows-host-receipts'
New-Item -ItemType Directory -Force -Path $receipts | Out-Null
. config/ci/windows-ssh-provider/preview-ssh/windows-ssh-capability.ps1
Initialize-WindowsInboxSshCapability -Arch '${{ matrix.arch }}' -Receipt (Join-Path $receipts 'inbox-capability-preparation.json') -PreparationMode $env:INBOX_PREPARATION_MODE
- name: Run the Windows host cells against a private ${{ matrix.server }} sshd
shell: pwsh
timeout-minutes: ${{ contains(github.event.inputs.cells || '', 'orcad-cli') && 130 || 50 }}
@@ -0,0 +1,64 @@
name: Windows native preparation comparison
on:
workflow_dispatch:
inputs:
source_sha:
description: Exact commit containing this benchmark and the Windows compiler candidate.
required: true
type: string
permissions:
contents: read
concurrency:
group: windows-native-preparation-comparison-${{ github.ref }}
cancel-in-progress: false
env:
ORCA_BACKGROUND_LAUNCH: '1'
jobs:
compare:
name: Native preparation comparison (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
max-parallel: 2
matrix:
os: [windows-2022, windows-11-arm]
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.source_sha }}
persist-credentials: false
- name: Record measurement start and validate source
shell: bash
env:
SOURCE_SHA: ${{ inputs.source_sha }}
run: |
[[ "$SOURCE_SHA" =~ ^[0-9a-f]{40}$ ]]
test "$(git rev-parse HEAD)" = "$SOURCE_SHA"
mkdir -p .build/windows-native-benchmark
node -e 'require("node:fs").writeFileSync(".build/windows-native-benchmark/job-start.json", JSON.stringify({startedAt:new Date().toISOString()}))'
- uses: ./.github/actions/install-node-dependencies
with:
node-version: '24.21.0'
native-runtime: none
cache-pnpm-store: 'false'
cache-pnpm-verification: 'false'
- name: Compare isolated cold and same-build warm preparation
shell: bash
env:
SOURCE_SHA: ${{ inputs.source_sha }}
BENCHMARK_RUNNER: ${{ matrix.os }}
run: node config/scripts/benchmark-windows-native-preparation.mjs
- uses: actions/upload-artifact@v7
if: always()
with:
name: windows-native-preparation-${{ matrix.os }}-${{ github.run_id }}-${{ github.run_attempt }}
path: .build/windows-native-benchmark/
include-hidden-files: true
if-no-files-found: error
retention-days: 14
@@ -168,7 +168,7 @@ try {
$report.nativeInputs=$verified
Write-Stage 'preview-native-input-verification-complete'
} else {
Install-WindowsInboxSshCapability $Arch $report {param($stage) Write-Stage $stage}
Install-WindowsInboxSshCapability $Arch $report {param($stage) Write-Stage $stage} ([IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($Receipt)))
$verified=@()
foreach($binary in @('sshd.exe','ssh.exe','ssh-keygen.exe','sftp.exe','sftp-server.exe')){
$path=Join-Path $sshDir $binary
@@ -38,22 +38,52 @@ try {
function Assert-IsolatedWindowsSshCi([string]$Arch){if($script:refuseCapabilityHost){throw 'Injected host refusal'}}
function Assert-WindowsSshGlobalServerDormant([string]$Server){$script:globalChecks++;if($script:globalChecks -eq $script:refuseGlobalCheck){throw 'Injected global server refusal'}}
function Assert-WindowsSshStockShell {$script:shellChecks++;if($script:shellChecks -eq $script:refuseShellCheck){throw 'Injected shell refusal'}}
function Get-WindowsCapability([switch]$Online,[string]$Name){$script:capabilityQueries++;return @{State=$script:capabilityState}}
function Add-WindowsCapability([switch]$Online,[string]$Name){$script:capabilityAdds++;if($script:failCapabilityInstall){throw 'Injected capability install failure'}}
function Assert-CapabilityCommand([switch]$Online,[string]$Name,[string]$LogPath,[object]$ErrorAction,[string]$Operation){
if(-not $Online -or $Name -ne 'OpenSSH.Server~~~~0.0.1.0' -or $ErrorAction -ne 'Stop' -or [IO.Path]::GetDirectoryName($LogPath) -ne $script:capabilityLogs -or [IO.Path]::GetFileName($LogPath) -notlike "inbox-capability-$Operation-*.log"){throw 'Capability command changed its online identity, error handling or receipt log boundary'}
$script:capabilityLogPaths.Add($LogPath)
[IO.File]::WriteAllText($LogPath,"$Operation fixture")
}
function Get-WindowsCapability([switch]$Online,[string]$Name,[string]$LogPath,[object]$ErrorAction){
$script:capabilityQueries++;Assert-CapabilityCommand -Online:$Online -Name $Name -LogPath $LogPath -ErrorAction $ErrorAction -Operation 'query'
if($script:failCapabilityQuery){Write-Error 'Injected capability query failure' -ErrorAction $ErrorAction}
return @{State=$script:capabilityState}
}
function Add-WindowsCapability([switch]$Online,[string]$Name,[string]$LogPath,[object]$ErrorAction){
$script:capabilityAdds++;Assert-CapabilityCommand -Online:$Online -Name $Name -LogPath $LogPath -ErrorAction $ErrorAction -Operation 'install'
if($script:activeCapabilityReceipt){
$script:installObservedReceipt=Get-Content -LiteralPath $script:activeCapabilityReceipt -Raw | ConvertFrom-Json
if($script:installObservedReceipt.inboxCapabilityInitialState -ne 'NotPresent' -or $script:installObservedReceipt.inboxCapabilityOperations[0].status -ne 'passed' -or $script:installObservedReceipt.inboxCapabilityOperations[1].status -ne 'running'){throw 'Initial capability state was not durably recorded before installation'}
}
if($script:failCapabilityInstall){Write-Error 'Injected capability install failure' -ErrorAction $ErrorAction}
return @{Path='C:\';Online=$true;RestartNeeded=$script:capabilityRestartNeeded}
}
function Reset-CapabilityControl([string]$State){
$script:capabilityState=$State;$script:capabilityQueries=0;$script:capabilityAdds=0
$script:globalChecks=0;$script:shellChecks=0;$script:refuseGlobalCheck=0;$script:refuseShellCheck=0
$script:refuseCapabilityHost=$false;$script:failCapabilityInstall=$false
$script:refuseCapabilityHost=$false;$script:failCapabilityInstall=$false;$script:failCapabilityQuery=$false
$script:activeCapabilityReceipt=$null;$script:installObservedReceipt=$null;$script:capabilityRestartNeeded=$false
$script:capabilityStages=[Collections.Generic.List[string]]::new()
$script:capabilityLogPaths=[Collections.Generic.List[string]]::new()
}
$script:capabilityLogs=Join-Path ([IO.Path]::GetTempPath()) ([Guid]::NewGuid().ToString('N'))
try {
foreach($state in @('Installed','NotPresent')){
Reset-CapabilityControl $state
$capabilityReport=@{}
Install-WindowsInboxSshCapability 'x64' $capabilityReport {param($name) $script:capabilityStages.Add($name)}
Install-WindowsInboxSshCapability 'x64' $capabilityReport {param($name) $script:capabilityStages.Add($name)} $script:capabilityLogs
$expectedAdds=if($state -eq 'Installed'){0}else{1}
if($capabilityReport.inboxCapabilityInitialState -ne $state -or $script:capabilityAdds -ne $expectedAdds -or $script:globalChecks -ne 2 -or $script:shellChecks -ne 2 -or ($script:capabilityStages -join ',') -ne 'inbox-capability-start,inbox-capability-complete'){throw 'Shared capability preparation did not preserve the install and guard boundaries'}
$expectedStages=@('inbox-capability-start','inbox-capability-query-start','inbox-capability-query-finished')
if($expectedAdds){$expectedStages+=@('inbox-capability-install-start','inbox-capability-install-finished')}
$expectedStages+=@('inbox-capability-guards-start','inbox-capability-complete')
if($capabilityReport.inboxCapabilityInitialState -ne $state -or $script:capabilityQueries -ne 1 -or $script:capabilityAdds -ne $expectedAdds -or $script:globalChecks -ne 2 -or $script:shellChecks -ne 2 -or ($script:capabilityStages -join ',') -ne ($expectedStages -join ',')){throw 'Shared capability preparation did not preserve the install and guard boundaries'}
if($capabilityReport.inboxCapabilityOperations.Count -ne 1+$expectedAdds){throw 'Capability operations missing'}
foreach($operation in $capabilityReport.inboxCapabilityOperations){
if($operation.status -ne 'passed' -or $operation.elapsedMs -isnot [long] -or $operation.elapsedMs -lt 0 -or -not [IO.File]::Exists((Join-Path $script:capabilityLogs $operation.log))){throw 'Capability operation did not retain its timing, verdict or diagnostic log'}
}
if($expectedAdds -and ($capabilityReport.inboxCapabilityInstallResult.online -ne $true -or $capabilityReport.inboxCapabilityInstallResult.path -ne 'C:\' -or $capabilityReport.inboxCapabilityInstallResult.restartNeeded -ne $false)){throw 'Capability install result omitted'}
if(-not $expectedAdds -and $capabilityReport.ContainsKey('inboxCapabilityInstallResult')){throw 'Installed capability invented an install result'}
}
foreach($fault in @('host','global-before','shell-before','global-after','shell-after','install')){
foreach($fault in @('host','global-before','shell-before','global-after','shell-after','query','install')){
Reset-CapabilityControl 'NotPresent'
switch($fault){
'host' {$script:refuseCapabilityHost=$true}
@@ -61,26 +91,45 @@ foreach($fault in @('host','global-before','shell-before','global-after','shell-
'shell-before' {$script:refuseShellCheck=1}
'global-after' {$script:refuseGlobalCheck=2}
'shell-after' {$script:refuseShellCheck=2}
'query' {$script:failCapabilityQuery=$true}
'install' {$script:failCapabilityInstall=$true}
}
$rejected=$false
try {Install-WindowsInboxSshCapability 'x64' @{} {param($name) $script:capabilityStages.Add($name)}} catch {$rejected=$true}
$faultReport=@{}
try {Install-WindowsInboxSshCapability 'x64' $faultReport {param($name) $script:capabilityStages.Add($name)} $script:capabilityLogs} catch {$rejected=$true}
if(-not $rejected -or $script:capabilityStages.Contains('inbox-capability-complete')){throw "Capability fault did not fail closed: $fault"}
if($fault -in @('host','global-before','shell-before') -and $script:capabilityAdds){throw 'Capability mutation preceded its host guards'}
if($fault -eq 'query' -and $script:capabilityAdds){throw 'Failed query proceeded to installation'}
if($fault -in @('query','install') -and ($faultReport.inboxCapabilityOperations[-1].status -ne 'failed' -or $faultReport.inboxCapabilityOperations[-1].elapsedMs -isnot [long])){throw 'Failed servicing operation lost its verdict or duration'}
}
Reset-CapabilityControl 'NotPresent'
foreach($invocation in 1..2){Install-WindowsInboxSshCapability 'x64' @{} {param($name) $script:capabilityStages.Add($name)} $script:capabilityLogs}
if($script:capabilityLogPaths.Count -ne 4 -or ($script:capabilityLogPaths | Select-Object -Unique).Count -ne 4){throw 'Separate servicing operations or invocations reused a diagnostic log'}
} finally {Remove-Item -LiteralPath $script:capabilityLogs -Recurse -Force -ErrorAction SilentlyContinue}
$capabilityRoot=Join-Path ([IO.Path]::GetTempPath()) ([Guid]::NewGuid().ToString('N'))
try {
New-Item -ItemType Directory -Path $capabilityRoot | Out-Null
$capabilityReceipt=Join-Path $capabilityRoot 'capability.json'
$script:capabilityLogs=$capabilityRoot
Reset-CapabilityControl 'Installed'
Initialize-WindowsInboxSshCapability 'x64' $capabilityReceipt
$completed=Get-Content -LiteralPath $capabilityReceipt -Raw | ConvertFrom-Json
if($completed.status -ne 'passed' -or $completed.inboxCapabilityInitialState -ne 'Installed'){throw 'Capability success receipt missing its observed initial state'}
Reset-CapabilityControl 'NotPresent';$script:failCapabilityInstall=$true
if($completed.status -ne 'passed' -or $completed.inboxCapabilityInitialState -ne 'Installed' -or $completed.preparationMode -ne 'overlap'){throw 'Capability success receipt missing its observed initial state or default mode'}
Reset-CapabilityControl 'NotPresent';$script:capabilityLogs=$capabilityRoot;$script:activeCapabilityReceipt=$capabilityReceipt;$script:capabilityRestartNeeded=$true
Initialize-WindowsInboxSshCapability 'x64' $capabilityReceipt 'serial'
$installed=Get-Content -LiteralPath $capabilityReceipt -Raw | ConvertFrom-Json
if($installed.status -ne 'passed' -or $installed.preparationMode -ne 'serial' -or $installed.inboxCapabilityInstallResult.restartNeeded -ne $true -or -not $script:installObservedReceipt){throw 'Serial preparation lost its mode, restart result or pre-install receipt'}
Reset-CapabilityControl 'NotPresent';$script:activeCapabilityReceipt=$capabilityReceipt;$script:failCapabilityInstall=$true
$rejected=$false
try {Initialize-WindowsInboxSshCapability 'x64' $capabilityReceipt} catch {$rejected=$true}
$failed=Get-Content -LiteralPath $capabilityReceipt -Raw | ConvertFrom-Json
if(-not $rejected -or $failed.status -ne 'failed' -or $failed.inboxCapabilityInitialState -ne 'NotPresent' -or $failed.error -ne 'Injected capability install failure'){throw 'Failed capability preparation masqueraded as a passing receipt'}
if($failed.inboxCapabilityOperations[-1].status -ne 'failed' -or -not $failed.stages.stage.Contains('inbox-capability-install-finished')){throw 'Failed preparation omitted its servicing result'}
Reset-CapabilityControl 'NotPresent';$script:failCapabilityQuery=$true
$rejected=$false
try {Initialize-WindowsInboxSshCapability 'x64' $capabilityReceipt} catch {$rejected=$true}
$failedQuery=Get-Content -LiteralPath $capabilityReceipt -Raw | ConvertFrom-Json
if(-not $rejected -or $failedQuery.status -ne 'failed' -or $failedQuery.inboxCapabilityOperations[0].status -ne 'failed' -or $failedQuery.inboxCapabilityOperations.Count -ne 1 -or $script:capabilityAdds -or $failedQuery.inboxCapabilityInitialState){throw 'Failed query receipt invented a capability state or proceeded to installation'}
} finally {Remove-Item -LiteralPath $capabilityRoot -Recurse -Force -ErrorAction SilentlyContinue}
& {
param($ProofAst)
@@ -33,26 +33,48 @@ function Write-WindowsSshReceiptStage([hashtable]$Report,[string]$Receipt,[strin
return $written
}
function Install-WindowsInboxSshCapability([ValidateSet('arm64','x64')][string]$Arch,[hashtable]$Report,[scriptblock]$Stage) {
function Install-WindowsInboxSshCapability([ValidateSet('arm64','x64')][string]$Arch,[hashtable]$Report,[scriptblock]$Stage,[Parameter(Mandatory=$true)][string]$LogDirectory) {
Assert-IsolatedWindowsSshCi $Arch
Assert-WindowsSshGlobalServerDormant 'inbox'
Assert-WindowsSshStockShell
& $Stage 'inbox-capability-start'
$capability=Get-WindowsCapability -Online -Name 'OpenSSH.Server~~~~0.0.1.0'
$Report.inboxCapabilityInitialState=[string]$capability.State
if($capability.State -ne 'Installed'){Add-WindowsCapability -Online -Name 'OpenSSH.Server~~~~0.0.1.0' | Out-Null}
New-Item -ItemType Directory -Force -Path $LogDirectory | Out-Null
$invocation=[Guid]::NewGuid().ToString('N')
$query=@{operation='query';status='running';log="inbox-capability-query-$invocation.log"}
$Report.inboxCapabilityOperations=@($query)
& $Stage 'inbox-capability-query-start'
$watch=[Diagnostics.Stopwatch]::StartNew()
try {
$capability=Get-WindowsCapability -Online -Name 'OpenSSH.Server~~~~0.0.1.0' -LogPath (Join-Path $LogDirectory $query.log) -ErrorAction Stop
$Report.inboxCapabilityInitialState=[string]$capability.State
$query.status='passed'
} catch {$query.status='failed';$query.error=$_.Exception.Message;throw}
finally {$watch.Stop();$query.elapsedMs=$watch.ElapsedMilliseconds;& $Stage 'inbox-capability-query-finished'}
if($capability.State -ne 'Installed'){
$install=@{operation='install';status='running';log="inbox-capability-install-$invocation.log"}
$Report.inboxCapabilityOperations+=@($install)
& $Stage 'inbox-capability-install-start'
$watch=[Diagnostics.Stopwatch]::StartNew()
try {
$result=Add-WindowsCapability -Online -Name 'OpenSSH.Server~~~~0.0.1.0' -LogPath (Join-Path $LogDirectory $install.log) -ErrorAction Stop
$Report.inboxCapabilityInstallResult=@{path=$result.Path;online=$result.Online;restartNeeded=$result.RestartNeeded}
$install.status='passed'
} catch {$install.status='failed';$install.error=$_.Exception.Message;throw}
finally {$watch.Stop();$install.elapsedMs=$watch.ElapsedMilliseconds;& $Stage 'inbox-capability-install-finished'}
}
& $Stage 'inbox-capability-guards-start'
Assert-WindowsSshGlobalServerDormant 'inbox'
Assert-WindowsSshStockShell
& $Stage 'inbox-capability-complete'
}
function Initialize-WindowsInboxSshCapability([ValidateSet('arm64','x64')][string]$Arch,[string]$Receipt) {
$report=@{scope='Windows inbox OpenSSH.Server capability preparation only';arch=$Arch;sourceSha=$env:GITHUB_SHA;runId=$env:GITHUB_RUN_ID;runAttempt=$env:GITHUB_RUN_ATTEMPT;runnerName=$env:RUNNER_NAME;imageVersion=$env:ImageVersion;status='running';stages=@();globalBootstrapCleanup='Disposable CI VM destruction is the boundary; no global sshd is started'}
function Initialize-WindowsInboxSshCapability([ValidateSet('arm64','x64')][string]$Arch,[string]$Receipt,[ValidateSet('overlap','serial')][string]$PreparationMode='overlap') {
$report=@{scope='Windows inbox OpenSSH.Server capability preparation only';arch=$Arch;sourceSha=$env:GITHUB_SHA;runId=$env:GITHUB_RUN_ID;runAttempt=$env:GITHUB_RUN_ATTEMPT;runnerName=$env:RUNNER_NAME;imageVersion=$env:ImageVersion;preparationMode=$PreparationMode;status='running';stages=@();globalBootstrapCleanup='Disposable CI VM destruction is the boundary; no global sshd is started'}
try {
if(-not (Write-WindowsSshReceiptStage $report $Receipt 'preparation-start')){throw 'Initial progress receipt unavailable; refuse provisioning'}
Install-WindowsInboxSshCapability $Arch $report {param($name)
if(-not (Write-WindowsSshReceiptStage $report $Receipt $name)){throw 'Capability preparation progress receipt unavailable'}
}
} ([IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($Receipt)))
$report.status='passed'
} catch {$report.status='failed';$report.error=$_.Exception.Message;throw}
finally {
@@ -0,0 +1,518 @@
import assert from 'node:assert/strict'
import { createHash } from 'node:crypto'
import {
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
readdirSync,
realpathSync,
rmSync,
statSync,
writeFileSync
} from 'node:fs'
import { createRequire } from 'node:module'
import { tmpdir } from 'node:os'
import { dirname, join, relative, resolve, sep } from 'node:path'
import { performance } from 'node:perf_hooks'
import { pathToFileURL } from 'node:url'
import { runProcess } from '@orca/process-host'
import { buildCounterbalancedSchedule } from './counterbalanced-benchmark-schedule.mjs'
import { summarizeBenchmarkSamples } from './benchmark-sample-summary.mjs'
import { resolvePnpmCliInvocation } from './pnpm-cli-invocation.mjs'
import { hasWindowsCompilerSelection } from './initialize-windows-native-toolchain.mjs'
import {
compilerEnvironmentKey,
environmentReceipt,
hash
} from './windows-native-benchmark-observer.mjs'
const addonNames = [
'node-pty',
'@orca/windows-registry',
'@orca/windows-security',
'@vscode/windows-process-tree'
]
const candidate = 'initialize-windows-native-toolchain.mjs'
const control = 'ensure-native-runtime.mjs'
const unchangedFiles = [
`.github/actions/prepare-native-runtime/action.yml`,
`config/scripts/${control}`,
`config/scripts/${candidate}`,
'config/scripts/capture-windows-native-environment.cmd',
'config/scripts/windows-native-benchmark-observer.mjs',
'config/scripts/benchmark-windows-native-preparation.mjs'
]
export function validateObservedPreparation(receipt, variant, warm = false) {
assert.equal(
receipt.parentBefore.hash,
receipt.parentAfter.hash,
'Outer compiler environment changed'
)
const calls = (phase) => receipt.calls.filter((call) => call.phase === phase)
const captured = variant !== 'control' && !warm
assert.equal(calls('discovery').length, captured ? 1 : 0, 'Unexpected compiler discovery count')
assert.equal(calls('capture').length, captured ? 1 : 0, 'Unexpected developer command count')
assert.equal(
calls('probe').length,
variant === 'control' ? 0 : 1,
'Missing helper preflight observation'
)
for (const call of receipt.calls) {
assert(
!call.error && !call.timedOut && !call.outputTruncated,
'Incomplete compiler observation'
)
}
if (variant === 'control') {
assert.equal(calls('addon-build').length, warm ? 0 : 4, 'Expected all four cold addon builds')
assert(
receipt.calls.every((call) => call.code === 0),
'Control preparation failed'
)
return
}
const [prepare] = calls('preparation')
assert.equal(calls('preparation').length, 1, 'Missing unchanged preparation child')
assert.equal(prepare.code, 0, 'Native preparation failed')
assert.equal(calls('probe')[0].code, warm ? 0 : 1, 'Unexpected helper cold/warm probe')
if (warm || variant === 'fallback') {
assert.equal(
prepare.environment.hash,
receipt.parentBefore.hash,
'Fallback/warm changed compiler selection'
)
assert.deepEqual(prepare.changedNames, [], 'Fallback/warm altered child environment')
} else {
assert.equal(calls('discovery')[0].code, 0)
assert.equal(calls('capture')[0].code, 0)
assert(prepare.changedNames.length > 0, 'Captured environment was not applied')
assert(
prepare.changedNames.every((name) => compilerEnvironmentKey.test(name)),
'Unrelated environment changed'
)
assert(prepare.environment.compiler.vcinstalldir, 'Prepared child lacks compiler selection')
}
if (variant === 'fallback' && !warm) {
assert.equal(calls('discovery')[0].code, 0)
assert.equal(calls('capture')[0].code, 7, 'Fixed failure fixture did not run')
}
}
export function assertNativeColdProbe(result) {
assert.equal(result.code, 1, 'Cold fixture unexpectedly passed')
for (const name of addonNames) {
assert(result.stderr.includes(`${name}:`), `Cold fixture did not fail ${name}`)
}
}
export function assertNoHeaderDownloads(result) {
assert(
!/gyp http (GET|200|download)/i.test(`${result.stdout}\n${result.stderr}`),
'Timed preparation downloaded headers/libraries'
)
}
function digestFiles(root, paths) {
return Object.fromEntries(
paths
.filter((path) => existsSync(join(root, path)))
.map((path) => [path, hash(readFileSync(join(root, path)))])
)
}
function treeDigest(root) {
const digest = createHash('sha256')
const files = []
const visit = (path) => {
for (const name of readdirSync(path).sort()) {
const child = join(path, name)
if (statSync(child).isDirectory()) {
visit(child)
} else {
files.push(child)
}
}
}
visit(root)
for (const file of files) {
digest.update(relative(root, file)).update('\0').update(readFileSync(file))
}
return { sha256: digest.digest('hex'), files: files.length }
}
function nativeDirectories(snapshot) {
const require = createRequire(join(snapshot, 'package.json'))
const root = realpathSync(snapshot)
return addonNames.map((name) => {
const directory = realpathSync(dirname(require.resolve(`${name}/package.json`)))
assert(directory.startsWith(`${root}${sep}`), `Addon escapes its isolated copy: ${name}`)
return { name, directory }
})
}
function binaryReceipt(snapshot) {
const require = createRequire(join(snapshot, 'package.json'))
const paths = [
join(dirname(require.resolve('node-pty/package.json')), 'build/Release/conpty.node'),
join(dirname(require.resolve('node-pty/package.json')), 'build/Release/conpty/conpty.dll'),
join(dirname(require.resolve('node-pty/package.json')), 'build/Release/conpty/OpenConsole.exe'),
join(snapshot, 'native/windows-registry/build/Release/orca_windows_registry.node'),
join(snapshot, 'native/windows-security/build/Release/orca_windows_security.node'),
join(
dirname(require.resolve('@vscode/windows-process-tree/package.json')),
'build/Release/windows_process_tree.node'
)
]
return paths.map((path) => {
assert(existsSync(path), `Missing prepared artifact: ${path}`)
return {
path: relative(snapshot, path),
bytes: statSync(path).size,
sha256: hash(readFileSync(path))
}
})
}
export async function benchmarkWindowsNativePreparation(
root = resolve(import.meta.dirname, '../..')
) {
assert.equal(process.platform, 'win32', 'This hosted comparison requires Windows')
assert(['x64', 'arm64'].includes(process.arch), 'Unsupported Windows runner')
assert.equal(process.versions.node, '24.21.0', 'Comparison requires pinned Node')
assert(
!hasWindowsCompilerSelection(process.env),
'Explicit compiler selection prevents a qualified automatic-capture comparison'
)
assert(/^[0-9a-f]{40}$/.test(process.env.SOURCE_SHA ?? ''), 'SOURCE_SHA must be an exact commit')
const output = join(root, '.build/windows-native-benchmark')
mkdirSync(output, { recursive: true })
const temporary = mkdtempSync(
join(process.env.RUNNER_TEMP || tmpdir(), 'orca-native-comparison-')
)
const archive = join(temporary, 'source.tar')
const headers = join(temporary, 'headers')
const pnpm = resolvePnpmCliInvocation()
const environment = {
...process.env,
ORCA_BACKGROUND_LAUNCH: '1',
npm_config_devdir: headers,
npm_package_config_node_gyp_devdir: headers
}
const parentBefore = environmentReceipt(process.env)
const githubEnvironmentBefore = existsSync(process.env.GITHUB_ENV ?? '')
? hash(readFileSync(process.env.GITHUB_ENV))
: null
const report = {
schemaVersion: 1,
startedAt: new Date().toISOString(),
qualification: 'incomplete',
firstRecordedJobStep: JSON.parse(readFileSync(join(output, 'job-start.json'), 'utf8')),
phases: [],
samples: [],
scope: {
warm: 'Same-build warm preparation; no Actions native-cache restore/save is performed.',
metric:
'Cold addon preparation with identical diagnostic preload; installs, header downloads, standalone qualification probes and artifact upload are recorded separately; the helper preflight remains included.',
occupancy:
'Use complete hosted job started_at/completed_at, including setup and upload/post steps, for actual runner occupancy. This artifact only measures its explicit window.',
excluded:
'No Node-to-Electron, cross-target template, exact-key restore, or CI workload gain is claimed.'
}
}
const writeReport = () =>
writeFileSync(join(output, 'receipt.json'), `${JSON.stringify(report, null, 2)}\n`)
const command = async (label, program, args, cwd = root, env = environment, accepted = [0]) => {
const startedAt = new Date().toISOString()
const start = performance.now()
const result = await runProcess({
program,
args,
cwd,
env,
timeoutMs: 1_200_000,
maxOutputBytes: 64 * 1024 * 1024,
terminationBarrier: true
})
const elapsedMs = performance.now() - start
const stdoutFile = `${label}.stdout.log`
const stderrFile = `${label}.stderr.log`
writeFileSync(join(output, stdoutFile), result.stdout)
writeFileSync(join(output, stderrFile), result.stderr)
report.phases.push({
label,
program,
args,
startedAt,
finishedAt: new Date().toISOString(),
durationMs: elapsedMs,
code: result.code,
signal: result.signal,
timedOut: result.timedOut,
outputTruncated: result.outputTruncated,
stdoutFile,
stderrFile,
stdoutSha256: hash(result.stdout),
stderrSha256: hash(result.stderr)
})
writeReport()
assert(
!result.timedOut &&
!result.signal &&
!result.outputTruncated &&
accepted.includes(result.code),
`${label} failed: ${result.stderr.slice(-4000)}`
)
return { ...result, durationMs: elapsedMs }
}
const pnpmCommand = (label, args, cwd) =>
command(label, pnpm.command, [...pnpm.prefixArgs, ...args], cwd)
try {
const head = (await command('source-head', 'git', ['rev-parse', 'HEAD'])).stdout.trim()
assert.equal(head, process.env.SOURCE_SHA, 'Checkout differs from frozen source')
await command('source-clean', 'git', ['diff', '--exit-code', 'HEAD', '--'])
const tree = (await command('source-tree', 'git', ['rev-parse', 'HEAD^{tree}'])).stdout.trim()
const pnpmVersion = (await pnpmCommand('pnpm-version', ['--version'], root)).stdout.trim()
assert.equal(pnpmVersion, '12.8.1', 'Comparison requires pinned pnpm')
const action = readFileSync(
join(root, '.github/actions/prepare-native-runtime/action.yml'),
'utf8'
)
const hashExpression = action.match(/NATIVE_SOURCE_HASH: (.+)/)?.[1]
assert(hashExpression, 'Missing production source identity')
const inputs = [...hashExpression.matchAll(/'([^']+)'/g)].map((match) => match[1])
assert(
inputs.includes(`config/scripts/${candidate}`),
'Frozen source lacks the candidate native-cache fingerprint'
)
const requiredScriptHashes = digestFiles(root, unchangedFiles)
assert.equal(
Object.keys(requiredScriptHashes).length,
unchangedFiles.length,
'Frozen source lacks required scripts'
)
const sourceInputs = digestFiles(root, inputs)
report.identity = {
sourceSha: head,
tree,
runtime: 'node',
node: process.versions.node,
nodeAbi: process.versions.modules,
arch: process.arch,
pnpm: pnpmVersion,
runner: process.env.BENCHMARK_RUNNER,
imageOS: process.env.ImageOS,
imageVersion: process.env.ImageVersion,
workflowRef: process.env.GITHUB_WORKFLOW_REF,
workflowSha: process.env.GITHUB_WORKFLOW_SHA,
runId: process.env.GITHUB_RUN_ID,
runAttempt: process.env.GITHUB_RUN_ATTEMPT,
sourceInputs,
requiredScriptHashes,
sourceInputDigest: hash(JSON.stringify(sourceInputs)),
productionHashExpression: hashExpression,
parentCompilerEnvironment: parentBefore.compiler
}
await command('archive-source', 'git', ['archive', '--format=tar', '--output', archive, 'HEAD'])
report.identity.archiveSha256 = hash(readFileSync(archive))
const require = createRequire(join(root, 'package.json'))
const nodeGyp = process.env.npm_config_node_gyp || require.resolve('node-gyp/bin/node-gyp.js')
report.identity.nodeGyp = JSON.parse(
readFileSync(resolve(dirname(nodeGyp), '..', 'package.json'), 'utf8')
).version
report.identity.nodeGypEntrySha256 = hash(readFileSync(nodeGyp))
await command('download-headers-before-measurement', process.execPath, [
nodeGyp,
'install',
`--target=${process.versions.node}`,
`--arch=${process.arch}`,
`--devdir=${headers}`
])
const headersBefore = treeDigest(headers)
report.identity.headers = headersBefore
const physicalDirectories = new Set()
const schedule = buildCounterbalancedSchedule(2, 'control', 'candidate').flat()
report.schedule = schedule
for (const [index, variant] of [...schedule, 'fallback'].entries()) {
const label = `sample-${String(index + 1).padStart(2, '0')}`
const snapshot = join(temporary, label)
mkdirSync(snapshot)
await command(`${label}-extract`, 'tar', ['-xf', archive, '-C', snapshot])
await pnpmCommand(
`${label}-install`,
[
'install',
'--offline',
'--frozen-lockfile',
'--ignore-scripts',
'--package-import-method=copy',
'--side-effects-cache=false'
],
snapshot
)
await pnpmCommand(`${label}-internal-packages`, ['run', 'build:packages'], snapshot)
const directories = nativeDirectories(snapshot)
for (const { directory } of directories) {
assert(
!physicalDirectories.has(directory.toLowerCase()),
'Native copies share a build directory'
)
physicalDirectories.add(directory.toLowerCase())
rmSync(join(directory, 'build'), { recursive: true, force: true })
}
const initial = await command(
`${label}-cold-probe`,
process.execPath,
[join(snapshot, 'config/scripts', control), '--check-only'],
snapshot,
environment,
[1]
)
assertNativeColdProbe(initial)
const snapshotScriptHashes = digestFiles(snapshot, unchangedFiles)
assert.deepEqual(
snapshotScriptHashes,
requiredScriptHashes,
'Ordinary snapshot source/config drift'
)
const originalCapture = readFileSync(
join(snapshot, 'config/scripts/capture-windows-native-environment.cmd')
)
if (variant === 'fallback') {
writeFileSync(
join(snapshot, 'config/scripts/capture-windows-native-environment.cmd'),
'@echo off\r\nexit /b 7\r\n'
)
}
const sample = {
label,
variant,
sourceHashesBeforeInjection: snapshotScriptHashes,
originalCaptureSha256: hash(originalCapture),
addonDirectories: directories,
measurements: []
}
report.samples.push(sample)
for (const warm of [false, true]) {
const stage = `${label}-${warm ? 'warm' : 'cold'}`
const traceFile = join(output, `${stage}.trace.json`)
const script = join(snapshot, 'config/scripts', variant === 'control' ? control : candidate)
const args = [
'--import',
pathToFileURL(join(snapshot, 'config/scripts/windows-native-benchmark-observer.mjs'))
.href,
script,
...(variant === 'control' ? ['--runtime=node'] : [])
]
const result = await command(stage, process.execPath, args, snapshot, {
...environment,
ORCA_NATIVE_BENCHMARK_TRACE: traceFile
})
assertNoHeaderDownloads(result)
const receipt = JSON.parse(readFileSync(traceFile, 'utf8'))
validateObservedPreparation(receipt, variant, warm)
if (variant === 'fallback' && !warm) {
assert(result.stderr.includes('retaining node-gyp discovery'), 'Fallback warning missing')
}
const final = await command(
`${stage}-final-probe`,
process.execPath,
[join(snapshot, 'config/scripts', control), '--check-only'],
snapshot
)
assert.equal(final.code, 0)
const calls = receipt.calls
const milliseconds = (phase) =>
calls
.filter((call) => call.phase === phase)
.reduce((total, call) => total + call.durationMs, 0)
sample.measurements.push({
warm,
totalPreparationMs: result.durationMs,
helperDiscoveryMs: milliseconds('discovery'),
helperCaptureMs: milliseconds('capture'),
helperPreprobeMs: milliseconds('probe'),
unchangedPreparationChildMs: variant === 'control' ? null : milliseconds('preparation'),
helperOutsidePreparationChildMs:
variant === 'control' ? null : result.durationMs - milliseconds('preparation'),
traceFile: relative(output, traceFile),
traceSha256: hash(readFileSync(traceFile)),
binaries: binaryReceipt(snapshot)
})
assert.deepEqual(
treeDigest(headers),
headersBefore,
'Timed preparation changed prefilled headers/libraries'
)
assert.equal(
environmentReceipt(process.env).hash,
parentBefore.hash,
'Parent environment changed'
)
assert.equal(
existsSync(process.env.GITHUB_ENV ?? '')
? hash(readFileSync(process.env.GITHUB_ENV))
: null,
githubEnvironmentBefore,
'Compiler setup wrote GITHUB_ENV'
)
writeReport()
}
sample.isolatedCopyWindowMs = report.phases
.filter((phase) => phase.label.startsWith(`${label}-`))
.reduce((total, phase) => total + phase.durationMs, 0)
sample.injectedCaptureSha256 =
variant === 'fallback'
? hash(
readFileSync(join(snapshot, 'config/scripts/capture-windows-native-environment.cmd'))
)
: null
}
report.comparison = Object.fromEntries(
[false, true].map((warm) => {
const timings = (variant) =>
report.samples
.filter((sample) => sample.variant === variant)
.map(
(sample) =>
sample.measurements.find((measurement) => measurement.warm === warm)
.totalPreparationMs
)
const baseline = timings('control')
const proposed = timings('candidate')
return [
warm ? 'sameBuildWarm' : 'cold',
{
control: summarizeBenchmarkSamples(baseline),
candidate: summarizeBenchmarkSamples(proposed),
pairDeltaMs: baseline.map((value, index) => proposed[index] - value),
role: 'Two counterbalanced pairs are descriptive; no significance or ordinary CI hit-rate estimate.'
}
]
})
)
report.parentEnvironment = {
before: parentBefore,
after: environmentReceipt(process.env),
githubEnvironmentBefore,
githubEnvironmentAfter: githubEnvironmentBefore
}
report.qualification = 'passed'
} catch (error) {
report.failure = error.message
report.qualification = 'failed'
throw error
} finally {
rmSync(temporary, { recursive: true, force: true })
report.finishedAt = new Date().toISOString()
report.explicitWindowMs = Date.parse(report.finishedAt) - Date.parse(report.startedAt)
report.explicitJobWindowMs =
Date.parse(report.finishedAt) - Date.parse(report.firstRecordedJobStep.startedAt)
writeReport()
}
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
await benchmarkWindowsNativePreparation()
}
@@ -0,0 +1,6 @@
@echo off
chcp 65001 >nul
call "%ORCA_WINDOWS_VSDEVCMD%" -no_logo -arch=%ORCA_WINDOWS_NATIVE_ARCH% -host_arch=%ORCA_WINDOWS_NATIVE_ARCH%
if errorlevel 1 exit /b 1
echo ORCA_WINDOWS_NATIVE_ENVIRONMENT
set
@@ -0,0 +1,159 @@
import { existsSync } from 'node:fs'
import { join } from 'node:path'
import { pathToFileURL } from 'node:url'
import { runProcessSync } from '@orca/process-host'
const ENVIRONMENT_MARKER = 'ORCA_WINDOWS_NATIVE_ENVIRONMENT'
const compilerEnvironmentKey =
/^(PATH|INCLUDE|LIB|LIBPATH|VCINSTALLDIR|VSINSTALLDIR|VisualStudioVersion|VSCMD_.+|VCTools.+|WindowsSDK.+|UniversalCRT.+|UCRTVersion)$/i
export function parseWindowsCompilerEnvironment(output, arch) {
const lines = output.split(/\r?\n/)
const marker = lines.indexOf(ENVIRONMENT_MARKER)
if (marker === -1) {
throw new Error('Developer environment receipt is missing')
}
const environment = {}
for (const line of lines.slice(marker + 1)) {
const separator = line.indexOf('=')
if (separator <= 0) {
continue
}
const name = line.slice(0, separator)
if (compilerEnvironmentKey.test(name)) {
environment[name] = line.slice(separator + 1)
}
}
const value = (name) => {
const key = Object.keys(environment).find((key) => key.toLowerCase() === name.toLowerCase())
return key ? environment[key] : undefined
}
if (!value('VCINSTALLDIR') || !value('VSCMD_VER') || !value('WindowsSDKVersion')) {
throw new Error('Developer environment lacks the compiler or Windows SDK')
}
if (
!/^\d+\.\d+\./.test(value('VSCMD_VER')) ||
!/^\d+\.\d+\.\d+\.\d+\\?$/.test(value('WindowsSDKVersion'))
) {
throw new Error('Developer environment has an invalid compiler or Windows SDK version')
}
const target = value('VSCMD_ARG_TGT_ARCH')?.toLowerCase()
if (!(target === arch || (arch === 'x64' && target === 'amd64'))) {
throw new Error('Developer environment targets a different architecture')
}
return environment
}
export function hasWindowsCompilerSelection(environment) {
return Object.entries(environment).some(
([name, value]) =>
/^(VCINSTALLDIR|GYP_MSVS_VERSION|npm_config_msvs_version|npm_package_config_node_gyp_msvs_version)$/i.test(
name
) && value
)
}
export function mergeWindowsCompilerEnvironment(environment, compilerEnvironment) {
const compilerKeys = new Set(Object.keys(compilerEnvironment).map((key) => key.toLowerCase()))
return {
...Object.fromEntries(
Object.entries(environment).filter(([key]) => !compilerKeys.has(key.toLowerCase()))
),
...compilerEnvironment
}
}
export function initializeWindowsNativeToolchain() {
if (process.platform !== 'win32') {
return
}
if (hasWindowsCompilerSelection(process.env)) {
return
}
try {
if (!['x64', 'arm64'].includes(process.arch)) {
throw new Error('Windows compiler setup requires a supported runner architecture')
}
const programFiles = Object.entries(process.env)
.filter(([key]) => /^(ProgramFiles|ProgramFiles\(x86\))$/i.test(key))
.map(([, value]) => value)
const vswhere = programFiles
.map((directory) => join(directory, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe'))
.find(existsSync)
if (!vswhere) {
throw new Error('Visual Studio discovery tool is unavailable')
}
const discovery = runProcessSync({
program: vswhere,
args: [
'-latest',
'-products',
'*',
'-utf8',
'-requires',
process.arch === 'arm64'
? 'Microsoft.VisualStudio.Component.VC.Tools.ARM64'
: 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
'-property',
'installationPath'
],
stdio: 'pipe',
timeoutMs: 30_000
})
const installations = discovery.stdout.trim().split(/\r?\n/).filter(Boolean)
if (discovery.code !== 0 || installations.length !== 1) {
throw new Error('Visual Studio discovery did not select one compiler')
}
const devcmd = join(installations[0], 'Common7', 'Tools', 'VsDevCmd.bat')
if (!existsSync(devcmd)) {
throw new Error('Visual Studio developer command is unavailable')
}
// process-host owns the fixed batch runner's quoting and hidden console.
const result = runProcessSync({
program: join(import.meta.dirname, 'capture-windows-native-environment.cmd'),
args: [],
env: {
...process.env,
ORCA_WINDOWS_VSDEVCMD: devcmd,
ORCA_WINDOWS_NATIVE_ARCH: process.arch
},
stdio: 'pipe',
timeoutMs: 60_000
})
if (result.code !== 0) {
throw new Error('Visual Studio developer command failed')
}
const environment = parseWindowsCompilerEnvironment(result.stdout, process.arch)
console.log(`[native-runtime] Initialized Windows ${process.arch} compiler environment`)
return environment
} catch {
console.warn(
'[native-runtime] Compiler environment setup unavailable; retaining node-gyp discovery'
)
}
}
export function prepareWindowsNodeRuntime(runProcess = runProcessSync) {
const script = join(import.meta.dirname, 'ensure-native-runtime.mjs')
const check = runProcess({
program: process.execPath,
args: [script, '--check-only'],
stdio: 'pipe',
timeoutMs: null
})
const compilerEnvironment = check.code === 0 ? undefined : initializeWindowsNativeToolchain()
const result = runProcess({
program: process.execPath,
args: [script, '--runtime=node'],
env: compilerEnvironment
? mergeWindowsCompilerEnvironment(process.env, compilerEnvironment)
: process.env,
stdio: 'inherit',
timeoutMs: null
})
return result.code ?? 1
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
process.exitCode = prepareWindowsNodeRuntime()
}
@@ -0,0 +1,85 @@
import { describe, expect, it, vi } from 'vitest'
import {
hasWindowsCompilerSelection,
mergeWindowsCompilerEnvironment,
parseWindowsCompilerEnvironment,
prepareWindowsNodeRuntime
} from './initialize-windows-native-toolchain.mjs'
const receipt = [
'Developer Command Prompt banner, not an environment variable',
'TOKEN=should-not-be-exported',
'ORCA_WINDOWS_NATIVE_ENVIRONMENT',
'VCINSTALLDIR=C:\\Visual Studio\\VC\\',
'VSCMD_VER=18.10.12224.181',
'WindowsSDKVersion=10.0.28000.0\\',
'VSCMD_ARG_TGT_ARCH=arm64',
'Path=C:\\工具;C:\\Program Files\\Visual Studio',
'INCLUDE=C:\\SDK=Custom\\Include',
'TOKEN=should-not-be-exported',
'=C:=C:\\',
''
].join('\r\n')
describe('Windows compiler environment receipt', () => {
it('keeps compiler paths and equals signs while excluding unrelated variables and banners', () => {
expect(parseWindowsCompilerEnvironment(receipt, 'arm64')).toEqual({
VCINSTALLDIR: 'C:\\Visual Studio\\VC\\',
VSCMD_VER: '18.10.12224.181',
WindowsSDKVersion: '10.0.28000.0\\',
VSCMD_ARG_TGT_ARCH: 'arm64',
Path: 'C:\\工具;C:\\Program Files\\Visual Studio',
INCLUDE: 'C:\\SDK=Custom\\Include'
})
})
it.each([
receipt.replace('ORCA_WINDOWS_NATIVE_ENVIRONMENT', 'missing'),
receipt.replace('VCINSTALLDIR=', 'unrelated='),
receipt.replace('VSCMD_VER=', 'unrelated='),
receipt.replace('WindowsSDKVersion=', 'unrelated='),
receipt.replace('10.0.28000.0\\', 'unavailable'),
receipt.replace('18.10.12224.181', 'unavailable'),
receipt.replace('VSCMD_ARG_TGT_ARCH=arm64', 'VSCMD_ARG_TGT_ARCH=x64')
])('rejects incomplete, invalid or wrong-architecture setup before use', (output) => {
expect(() => parseWindowsCompilerEnvironment(output, 'arm64')).toThrow()
})
})
describe('Windows native compiler environment scope', () => {
it('replaces path keys case-insensitively without changing the parent environment', () => {
const original = { PATH: 'original-path', LIB: 'original-lib', TOKEN: 'unchanged' }
expect(
mergeWindowsCompilerEnvironment(original, { Path: 'compiler-path', Lib: 'compiler-lib' })
).toEqual({ Path: 'compiler-path', Lib: 'compiler-lib', TOKEN: 'unchanged' })
expect(original).toEqual({ PATH: 'original-path', LIB: 'original-lib', TOKEN: 'unchanged' })
})
it.each([
'VCINSTALLDIR',
'GYP_MSVS_VERSION',
'npm_config_msvs_version',
'npm_package_config_node_gyp_msvs_version'
])('retains an existing compiler selection through %s', (name) => {
expect(hasWindowsCompilerSelection({ [name.toLowerCase()]: 'requested' })).toBe(true)
expect(hasWindowsCompilerSelection({ [name]: '' })).toBe(false)
})
it('uses the original preparation and environment after a passing warm probe', () => {
const runProcess = vi.fn(() => ({ code: 0 }))
expect(prepareWindowsNodeRuntime(runProcess)).toBe(0)
expect(runProcess).toHaveBeenCalledTimes(2)
expect(runProcess).toHaveBeenLastCalledWith(
expect.objectContaining({
args: [expect.stringContaining('ensure-native-runtime.mjs'), '--runtime=node'],
env: process.env,
stdio: 'inherit'
})
)
})
it('propagates native preparation failure after a passing warm probe', () => {
const runProcess = vi.fn().mockReturnValueOnce({ code: 0 }).mockReturnValueOnce({ code: 9 })
expect(prepareWindowsNodeRuntime(runProcess)).toBe(9)
})
})
@@ -41,6 +41,8 @@ const ALWAYS_FILES = new Set([
'config/scripts/workspace-source-exports.mjs',
'config/scripts/workspace-source-exports.test.mjs',
'config/scripts/headless-detector-compiler-cache.mjs',
'config/scripts/initialize-windows-native-toolchain.mjs',
'config/scripts/capture-windows-native-environment.cmd',
'config/scripts/node-server-qualification.mjs',
// The source graph sees process-host source, not the build that emits the dist servers load.
'src/packages/process-host/.gitignore',
@@ -59,6 +59,8 @@ function context(os, arch, event, ref, template = false) {
},
success: () => true,
fromJSON: JSON.parse,
format: (template, ...values) =>
template.replace(/\{(\d+)\}/g, (_match, index) => String(values[Number(index)])),
contains: (values, value) => values.includes(value)
}
}
@@ -173,6 +175,38 @@ describe('SSH Windows consumers of qualified server slots', () => {
const sshWorkflow = parse(readFileSync('.github/workflows/ssh-windows-hosts.yml', 'utf8'))
const sshSteps = sshWorkflow.jobs.hosts.steps
const sshPrepare = sshSteps.find((step) => step.uses === prepare.uses)
const inboxBackground = sshSteps.find((step) => step.id === 'inbox-capability')
const inboxSerial = sshSteps.find((step) => step.name?.endsWith('after the builds'))
const allLanes = [
{ arch: 'x64', runner: 'windows-2022', server: 'inbox' },
{ arch: 'x64', runner: 'windows-2022', server: 'preview', archive: 'OpenSSH-Win64.zip' },
{ arch: 'arm64', runner: 'windows-11-arm', server: 'inbox' },
{ arch: 'arm64', runner: 'windows-11-arm', server: 'preview', archive: 'OpenSSH-ARM64.zip' }
]
function sshContext(event, inputs = {}) {
const ctx = context('Windows', 'ARM64', event, 'refs/heads/main')
ctx.github.event = { inputs, pull_request: { number: undefined } }
ctx.inputs = inputs
ctx.env = {
INBOX_PREPARATION_MODE: sshValue(sshWorkflow.jobs.hosts.env.INBOX_PREPARATION_MODE, ctx)
}
return ctx
}
function sshValue(value, ctx) {
return evaluate(value.slice(3, -2).trim(), ctx)
}
function backgroundPreparationRuns(ctx) {
const condition = inboxBackground.run
.match(/^\s*if\((.*)\)\{\s*$/m)[1]
.replace(/'\$\{\{ matrix\.(arch|server) \}\}'/g, (_match, name) => `matrix.${name}`)
.replaceAll('$env:INBOX_PREPARATION_MODE', 'env.INBOX_PREPARATION_MODE')
.replaceAll(' -eq ', ' === ')
.replaceAll(' -and ', ' && ')
return evaluate(condition, ctx)
}
it.each(['pull_request', 'workflow_dispatch'])(
'restores only PR slots and keeps manual %s qualification fresh',
@@ -188,13 +222,8 @@ describe('SSH Windows consumers of qualified server slots', () => {
it('keeps both architectures, both sshd versions and the existing build order', () => {
expect(
sshWorkflow.jobs.hosts.strategy.matrix.include.map(({ arch, server }) => [arch, server])
).toEqual([
['x64', 'inbox'],
['x64', 'preview'],
['arm64', 'inbox'],
['arm64', 'preview']
])
sshValue(sshWorkflow.jobs.hosts.strategy.matrix.include, sshContext('pull_request'))
).toEqual(allLanes)
const addon = sshSteps.findIndex((step) =>
step.run?.includes('build-windows-process-tree-addon.mjs')
)
@@ -215,6 +244,92 @@ describe('SSH Windows consumers of qualified server slots', () => {
'config/scripts/orcad-windows-prebuild-cache.mjs'
)
})
it.each([
['pull_request', {}, 'overlap', false],
['pull_request', { preparation_mode: 'serial', arm_inbox_only: true }, 'overlap', false],
['push', { preparation_mode: 'serial', arm_inbox_only: true }, 'overlap', false],
['workflow_dispatch', {}, 'overlap', false],
['workflow_dispatch', { preparation_mode: 'overlap', arm_inbox_only: false }, 'overlap', false],
['workflow_dispatch', { preparation_mode: 'serial', arm_inbox_only: false }, 'serial', false],
['workflow_dispatch', { preparation_mode: 'overlap', arm_inbox_only: true }, 'overlap', true],
['workflow_dispatch', { preparation_mode: 'serial', arm_inbox_only: true }, 'serial', true]
])('%s inputs=%j mode=%s ARM-only=%s', (event, inputs, mode, armOnly) => {
const ctx = sshContext(event, inputs)
const lanes = sshValue(sshWorkflow.jobs.hosts.strategy.matrix.include, ctx)
expect(lanes).toEqual(armOnly ? [allLanes[2]] : allLanes)
expect(ctx.env.INBOX_PREPARATION_MODE).toBe(mode)
for (const matrix of lanes) {
ctx.matrix = matrix
const inboxArm = matrix.server === 'inbox' && matrix.arch === 'arm64'
expect(backgroundPreparationRuns(ctx)).toBe(inboxArm && mode === 'overlap')
expect(sshValue(inboxSerial.if, ctx)).toBe(inboxArm && mode === 'serial')
}
})
it('defaults to the existing overlap schedule and keeps serial after the successful wait', () => {
expect(sshWorkflow.on.workflow_dispatch.inputs.preparation_mode).toMatchObject({
type: 'choice',
default: 'overlap',
options: ['overlap', 'serial']
})
expect(sshWorkflow.on.workflow_dispatch.inputs.arm_inbox_only).toMatchObject({
type: 'boolean',
default: false
})
const dependencies = sshSteps.findIndex((step) => step.id === 'dependencies')
const template = sshSteps.findIndex((step) => step.run?.includes('build-orcad-template.mjs'))
const wait = sshSteps.findIndex((step) => step.wait === 'inbox-capability')
const serial = sshSteps.indexOf(inboxSerial)
const hosts = sshSteps.findIndex((step) => step.name?.startsWith('Run the Windows host cells'))
expect(inboxBackground.background).toBe(true)
expect(inboxBackground.if).toBeUndefined()
expect(sshSteps.indexOf(inboxBackground)).toBeLessThan(dependencies)
expect(template).toBeLessThan(wait)
expect(serial).toBe(wait + 1)
expect(hosts).toBe(serial + 1)
expect(inboxSerial.background).toBeUndefined()
for (const preparation of [inboxBackground, inboxSerial]) {
expect(preparation['continue-on-error']).toBeUndefined()
expect(preparation.run).toContain(
'. config/ci/windows-ssh-provider/preview-ssh/windows-ssh-capability.ps1'
)
expect(preparation.run).toContain(
"-Receipt (Join-Path $receipts 'inbox-capability-preparation.json') -PreparationMode $env:INBOX_PREPARATION_MODE"
)
}
expect(sshSteps[hosts].run).toContain('-InboxPreparationReceipt $preparation')
expect(sshWorkflow.jobs.hosts.env.ORCA_BACKGROUND_LAUNCH).toBe('1')
expect(sshWorkflow.jobs.hosts.env.ORCA_ISOLATED_SSH_CI).toBe('1')
for (const event of ['pull_request', 'workflow_dispatch']) {
for (const preparation_mode of ['overlap', 'serial']) {
for (const [cells, jobMinutes, hostMinutes] of [
['', 75, 50],
['orcad-cli-managed', 160, 130]
]) {
const ctx = sshContext(event, { preparation_mode, arm_inbox_only: true, cells })
expect(sshValue(sshWorkflow.jobs.hosts['timeout-minutes'], ctx)).toBe(jobMinutes)
expect(sshValue(sshSteps[hosts]['timeout-minutes'], ctx)).toBe(hostMinutes)
}
}
}
})
it('isolates manual comparison modes while preserving ordinary cancellation groups', () => {
const group = (ctx) =>
sshWorkflow.concurrency.group.replace(/\$\{\{(.*?)\}\}/g, (_match, expression) =>
String(evaluate(expression.trim(), ctx))
)
const regular = sshContext('pull_request')
regular.github.event.pull_request = { number: 28669 }
expect(group(regular)).toBe('ssh-windows-hosts-28669')
expect(group(sshContext('workflow_dispatch'))).toBe('ssh-windows-hosts-refs/heads/main')
for (const mode of ['overlap', 'serial']) {
expect(
group(sshContext('workflow_dispatch', { arm_inbox_only: true, preparation_mode: mode }))
).toBe(`ssh-windows-hosts-refs/heads/main-${mode}`)
}
})
})
const commandMocks = `
+4
View File
@@ -267,6 +267,8 @@ const MANAGED_HOOK_PREFIXES = [
const NATIVE_RUNTIME_PREFIXES = [
'config/scripts/ensure-native-runtime',
'config/scripts/initialize-windows-native-toolchain',
'config/scripts/capture-windows-native-environment',
'config/scripts/rebuild-native-deps',
'config/scripts/node-pty-job-ownership',
'config/scripts/windows-pe-machine',
@@ -288,6 +290,8 @@ const NATIVE_CACHE_FILES = new Set([
'.npmrc',
'.pnpmfile.cjs',
'config/scripts/ensure-native-runtime.mjs',
'config/scripts/initialize-windows-native-toolchain.mjs',
'config/scripts/capture-windows-native-environment.cmd',
'config/scripts/rebuild-native-deps.mjs',
'config/scripts/node-pty-job-ownership.cjs',
'config/scripts/windows-pe-machine.cjs',
@@ -2,10 +2,11 @@ import { readdirSync, readFileSync } from 'node:fs'
import path from 'node:path'
import { describe, expect, it } from 'vitest'
import { hasNodeModulesBinSpawn } from './windows-bin-spawn-predicate.mjs'
import { hasWindowsNativeBatchReferenceViolation } from './windows-native-batch-reference-policy'
/**
* Bare JS scripts cannot use the TS runProcess chokepoint; resolve package bins
* under process.execPath instead (see oxc-cli-invocation.mjs). The list only shrinks.
* Resolve package bins under process.execPath (see oxc-cli-invocation.mjs).
* The legacy list only shrinks; reviewed native compiler references use process-host.
* The literal check catches quoted .cmd/.bat paths, excluding drive letters and
* templates; comment-only lines are dropped, but trailing comments fail closed.
* The AST check catches spawn/spawnSync/execFile/execFileSync first arguments
@@ -13,10 +14,10 @@ import { hasNodeModulesBinSpawn } from './windows-bin-spawn-predicate.mjs'
* local variable initializers and ternaries. It does not follow imports, function
* returns, assignments, destructuring, aliased spawn names or computed members.
* Names are matched without scope/import resolution; shadowed names and non-path
* join/resolve calls can fail closed. Paths are joined textually, without reducing
* dot segments. Neither check proves a Windows branch or an actual unsafe spawn.
* join/resolve calls can fail closed. Package paths fold dot segments.
* Neither check proves a Windows branch or an actual unsafe spawn.
*/
const WINDOWS_SHIM_LITERAL = /['"][\w./\\-]*\.(?:cmd|bat)['"]/i
const WINDOWS_SHIM_LITERAL = /['"][\w./\\-]*\.(?:cmd|bat)['"]/gi
const SCANNED_ROOTS = ['config/scripts', 'tests/tools']
@@ -83,7 +84,13 @@ describe('windows batch shim spawn boundary', () => {
)
const offenders = scripts.filter((relativePath) => {
const contents = readFileSync(path.join(repoRoot, relativePath), 'utf8')
return WINDOWS_SHIM_LITERAL.test(codeText(contents)) || hasNodeModulesBinSpawn(contents)
const literals = [...codeText(contents).matchAll(WINDOWS_SHIM_LITERAL)].map((match) =>
match[0].slice(1, -1)
)
return (
hasWindowsNativeBatchReferenceViolation(relativePath, contents, literals) ||
hasNodeModulesBinSpawn(contents)
)
})
it('scans a plausible number of scripts', () => {
@@ -95,7 +102,7 @@ describe('windows batch shim spawn boundary', () => {
const unlisted = offenders.filter((name) => !WINDOWS_SHIM_SPAWN_ALLOWLIST.includes(name))
expect(
unlisted,
'Node cannot spawn a Windows batch shim without a shell. Resolve the real executable — see oxc-cli-invocation.mjs.'
'Resolve package shims to their real executable. Fixed native compiler batch runners must pass the scoped process-host policy.'
).toEqual([])
})
@@ -0,0 +1,166 @@
import { readFileSync } from 'node:fs'
import path from 'node:path'
import { describe, expect, it } from 'vitest'
import { hasWindowsNativeBatchReferenceViolation } from './windows-native-batch-reference-policy'
const initializer = 'config/scripts/initialize-windows-native-toolchain.mjs'
const benchmark = 'config/scripts/benchmark-windows-native-preparation.mjs'
const observer = 'config/scripts/windows-native-benchmark-observer.mjs'
const metadataCallers = [
'config/scripts/node-server-change-scope.mjs',
'config/scripts/pr-code-change-scope.mjs',
'config/scripts/windows-native-toolchain-routing.test.mjs'
]
const capture = 'capture-windows-native-environment.cmd'
const initializerSource = `
import { runProcessSync as captureEnvironment } from '@orca/process-host'
const devcmd = join(installation, 'Common7', 'Tools', 'VsDevCmd.bat')
existsSync(devcmd)
captureEnvironment({
program: join(import.meta.dirname, '${capture}'),
env: { ORCA_WINDOWS_VSDEVCMD: devcmd }
})
`
const benchmarkSource = `
import { runProcess } from '@orca/process-host'
const source = 'config/scripts/${capture}'
await runProcess({ program: process.execPath, args: [source] })
`
function hasViolation(relativePath: string, contents: string): boolean {
const literals = [...contents.matchAll(/['"][\w./\\-]*\.(?:cmd|bat)['"]/gi)].map((match) =>
match[0].slice(1, -1)
)
return hasWindowsNativeBatchReferenceViolation(relativePath, contents, literals)
}
describe('reviewed Windows native batch references', () => {
it.each([...metadataCallers, initializer, benchmark, observer])(
'accepts the current reviewed source in %s',
(relativePath) => {
const root = path.resolve(import.meta.dirname, '..', '..')
expect(hasViolation(relativePath, readFileSync(path.join(root, relativePath), 'utf8'))).toBe(
false
)
}
)
it.each(metadataCallers)('allows the fixed source path as metadata in %s', (relativePath) => {
expect(hasViolation(relativePath, `const source = 'config/scripts/${capture}'`)).toBe(false)
})
it('accepts the process-host executor through its imported alias', () => {
expect(hasViolation(initializer, initializerSource)).toBe(false)
})
it('accepts the benchmark executor', () => {
expect(hasViolation(benchmark, benchmarkSource)).toBe(false)
})
it.each([
'config/scripts/other-native-preparation.mjs',
'tests/tools/initialize-windows-native-toolchain.mjs',
`config/scripts/nested/${path.basename(initializer)}`
])('rejects the fixed runner in another caller: %s', (relativePath) => {
expect(hasViolation(relativePath, initializerSource)).toBe(true)
})
it.each([
'elsewhere/capture-windows-native-environment.cmd',
'./capture-windows-native-environment.cmd',
'CAPTURE-WINDOWS-NATIVE-ENVIRONMENT.cmd',
'other.cmd',
'other.bat'
])('rejects another batch path in a reviewed executor: %s', (literal) => {
expect(hasViolation(initializer, `${initializerSource}\nconst other = '${literal}'`)).toBe(true)
})
it.each(metadataCallers)('rejects other batch metadata in %s', (relativePath) => {
expect(
hasViolation(relativePath, `const sources = ['config/scripts/${capture}', 'other.cmd']`)
).toBe(true)
expect(hasViolation(relativePath, `const command = 'VsDevCmd.bat'`)).toBe(true)
})
it.each([
[initializer, initializerSource],
[benchmark, benchmarkSource],
[observer, `require('@orca/process-host'); const capture = '${capture}'`]
])('rejects a missing process-host load in %s', (relativePath, contents) => {
expect(hasViolation(relativePath, contents.replace('@orca/process-host', 'other-runner'))).toBe(
true
)
})
it('rejects an unused process-host import beside an unverified executor', () => {
expect(
hasViolation(initializer, initializerSource.replace('captureEnvironment({', 'otherRunner({'))
).toBe(true)
})
it('rejects another executor for the fixed capture script beside a valid call', () => {
expect(
hasViolation(
initializer,
`${initializerSource}\notherRunner({ program: join(import.meta.dirname, '${capture}') })`
)
).toBe(true)
})
it.each([
"import { spawnSync as execute } from 'node:child_process'",
"import * as cp from 'child_process'",
"await import('node:child_process')",
"const builtins = 'node:child_process'; process.getBuiltinModule(builtins)",
"const require = createRequire(import.meta.url); const cp = require('child_process')"
])('rejects raw child-process module loads: %s', (load) => {
expect(hasViolation(initializer, `${initializerSource}\n${load}`)).toBe(true)
})
it.each([
"spawn('program', [])",
"cp.spawnSync('program', [])",
"cp['execFile']('program', [])",
"execFileSync('program', [])",
"exec('program')",
"execSync('program')",
"fork('program')"
])('rejects raw process calls: %s', (call) => {
expect(hasViolation(initializer, `${initializerSource}\n${call}`)).toBe(true)
})
it.each([
"runProcess({ program: 'node_modules/.bin/pnpm' })",
"const bin = join(root, 'node_modules', '.bin', 'pnpm'); runProcess({ program: bin })",
"runProcess({ program: join(root, 'node_modules', 'tools', '..', '.bin', 'pnpm') })",
"const spec = { 'program': 'root\\\\node_modules\\\\.bin\\\\pnpm' }; runProcess(spec)",
"const program = join(root, 'node_modules', '.bin', 'pnpm'); runProcess({ program })",
"runProcess({ ['program']: join(root, 'node_modules', '.bin', 'pnpm') })"
])('rejects package-bin programs through process-host: %s', (call) => {
expect(hasViolation(benchmark, `${benchmarkSource}\n${call}`)).toBe(true)
})
it.each(metadataCallers)('rejects process execution added to metadata in %s', (relativePath) => {
expect(
hasViolation(
relativePath,
`const capture = 'config/scripts/${capture}'; runProcess({ program: capture })`
)
).toBe(true)
expect(
hasViolation(
relativePath,
`import { runProcess as execute } from '@orca/process-host'; const capture = 'config/scripts/${capture}'; execute({ program: capture })`
)
).toBe(true)
})
it.each([
"captureEnvironment({ program: 'VsDevCmd.bat' })",
'captureEnvironment({ program: devcmd })',
'const program = devcmd; captureEnvironment({ program })',
"const devcmd = join(other, 'VsDevCmd.bat')"
])('keeps the discovered developer command as metadata: %s', (extra) => {
expect(hasViolation(initializer, `${initializerSource}\n${extra}`)).toBe(true)
})
})
@@ -0,0 +1,229 @@
import ts from 'typescript-api'
import {
collectModuleSpecifiers,
literalString,
propertyName
} from './static-module-specifiers.mjs'
import { hasNodeModulesBinSpawn } from './windows-bin-spawn-predicate.mjs'
const references = new Map([
[
'config/scripts/node-server-change-scope.mjs',
'config/scripts/capture-windows-native-environment.cmd'
],
[
'config/scripts/pr-code-change-scope.mjs',
'config/scripts/capture-windows-native-environment.cmd'
],
[
'config/scripts/windows-native-toolchain-routing.test.mjs',
'config/scripts/capture-windows-native-environment.cmd'
],
[
'config/scripts/windows-native-benchmark-observer.mjs',
'capture-windows-native-environment.cmd'
],
[
'config/scripts/initialize-windows-native-toolchain.mjs',
'capture-windows-native-environment.cmd'
],
[
'config/scripts/benchmark-windows-native-preparation.mjs',
'config/scripts/capture-windows-native-environment.cmd'
]
])
const executors = new Map([
['config/scripts/initialize-windows-native-toolchain.mjs', 'runProcessSync'],
['config/scripts/benchmark-windows-native-preparation.mjs', 'runProcess']
])
const initializer = 'config/scripts/initialize-windows-native-toolchain.mjs'
const observer = 'config/scripts/windows-native-benchmark-observer.mjs'
const rawProcessMethods = new Set([
'spawn',
'spawnSync',
'exec',
'execSync',
'execFile',
'execFileSync',
'fork'
])
const processHostMethods = new Set(['runProcess', 'runProcessSync', 'spawnProcess'])
function callName(node: ts.Expression): string {
return ts.isIdentifier(node) ? node.text : (propertyName(node) ?? '')
}
function isDeveloperCommandMetadata(node: ts.StringLiteral): boolean {
const call = node.parent
const declaration = call.parent
return (
ts.isCallExpression(call) &&
callName(call.expression) === 'join' &&
call.arguments.at(-1) === node &&
ts.isVariableDeclaration(declaration) &&
ts.isIdentifier(declaration.name) &&
declaration.name.text === 'devcmd'
)
}
function isDeveloperCommandUse(node: ts.Identifier): boolean {
const parent = node.parent
return (
(ts.isVariableDeclaration(parent) && parent.name === node) ||
(ts.isCallExpression(parent) &&
callName(parent.expression) === 'existsSync' &&
parent.arguments[0] === node) ||
(ts.isPropertyAssignment(parent) &&
parent.initializer === node &&
ts.isIdentifier(parent.name) &&
parent.name.text === 'ORCA_WINDOWS_VSDEVCMD')
)
}
function isProcessHostCapture(node: ts.StringLiteral, importedMethods: Set<string>): boolean {
const path = node.parent
if (
!ts.isCallExpression(path) ||
callName(path.expression) !== 'join' ||
path.arguments.length !== 2 ||
path.arguments[0].getText() !== 'import.meta.dirname' ||
path.arguments[1] !== node
) {
return false
}
const program = path.parent
if (
!ts.isPropertyAssignment(program) ||
!ts.isIdentifier(program.name) ||
program.name.text !== 'program'
) {
return false
}
const spec = program.parent
const call = spec.parent
return (
ts.isObjectLiteralExpression(spec) &&
ts.isCallExpression(call) &&
call.arguments[0] === spec &&
ts.isIdentifier(call.expression) &&
importedMethods.has(call.expression.text)
)
}
export function hasWindowsNativeBatchReferenceViolation(
relativePath: string,
contents: string,
literals: readonly string[]
): boolean {
const capture = references.get(relativePath)
if (!capture) {
return literals.length > 0
}
if (
literals.some(
(literal) =>
literal !== capture && !(relativePath === initializer && literal === 'VsDevCmd.bat')
)
) {
return true
}
const modules = collectModuleSpecifiers(relativePath, contents)
if (modules.some((module) => module === 'child_process' || module === 'node:child_process')) {
return true
}
const expectedMethod = executors.get(relativePath)
if ((expectedMethod || relativePath === observer) && !modules.includes('@orca/process-host')) {
return true
}
if (!expectedMethod && relativePath !== observer && modules.includes('@orca/process-host')) {
return true
}
const source = ts.createSourceFile(relativePath, contents, ts.ScriptTarget.Latest, true)
const importedMethods = new Set<string>()
const calls: ts.CallExpression[] = []
const programs: ts.Expression[] = []
const captureReferences: ts.StringLiteral[] = []
let violation = false
let developerCommandDeclarations = 0
function visit(node: ts.Node): void {
if (
ts.isImportDeclaration(node) &&
ts.isStringLiteral(node.moduleSpecifier) &&
node.moduleSpecifier.text === '@orca/process-host'
) {
const bindings = node.importClause?.namedBindings
if (bindings && ts.isNamedImports(bindings)) {
for (const binding of bindings.elements) {
if ((binding.propertyName ?? binding.name).text === expectedMethod) {
importedMethods.add(binding.name.text)
}
}
}
}
if (ts.isCallExpression(node)) {
calls.push(node)
const method = callName(node.expression)
if (rawProcessMethods.has(method)) {
violation = true
}
if (!expectedMethod && relativePath !== observer && processHostMethods.has(method)) {
violation = true
}
}
if (
ts.isPropertyAssignment(node) &&
((ts.isIdentifier(node.name) && node.name.text === 'program') ||
(ts.isStringLiteral(node.name) && node.name.text === 'program') ||
(ts.isComputedPropertyName(node.name) && literalString(node.name.expression) === 'program'))
) {
programs.push(node.initializer)
}
if (ts.isShorthandPropertyAssignment(node) && node.name.text === 'program') {
programs.push(node.name)
}
if (relativePath === initializer) {
if (ts.isStringLiteral(node) && node.text === capture) {
captureReferences.push(node)
}
if (
ts.isStringLiteral(node) &&
node.text === 'VsDevCmd.bat' &&
!isDeveloperCommandMetadata(node)
) {
violation = true
}
if (ts.isIdentifier(node) && node.text === 'devcmd') {
if (!isDeveloperCommandUse(node)) {
violation = true
}
if (ts.isVariableDeclaration(node.parent) && node.parent.name === node) {
developerCommandDeclarations += 1
}
}
}
ts.forEachChild(node, visit)
}
visit(source)
if (
expectedMethod &&
!calls.some(
(call) => ts.isIdentifier(call.expression) && importedMethods.has(call.expression.text)
)
) {
violation = true
}
if (relativePath === initializer && developerCommandDeclarations !== 1) {
violation = true
}
if (captureReferences.some((node) => !isProcessHostCapture(node, importedMethods))) {
violation = true
}
// Reuse package-path folding for process-host's named program option.
return (
violation ||
hasNodeModulesBinSpawn(contents) ||
programs.some((program) =>
hasNodeModulesBinSpawn(`${contents}\nspawnSync(${program.getText(source)})`)
)
)
}
@@ -0,0 +1,118 @@
import assert from 'node:assert/strict'
import { createHash } from 'node:crypto'
import { writeFileSync } from 'node:fs'
import { createRequire } from 'node:module'
import { basename } from 'node:path'
import { performance } from 'node:perf_hooks'
export const compilerEnvironmentKey =
/^(PATH|INCLUDE|LIB|LIBPATH|VCINSTALLDIR|VSINSTALLDIR|VisualStudioVersion|VSCMD_.+|VCTools.+|WindowsSDK.+|UniversalCRT.+|UCRTVersion)$/i
export const hash = (value) => createHash('sha256').update(value).digest('hex')
export function environmentReceipt(environment) {
const entries = Object.entries(environment)
.filter(([, value]) => value !== undefined)
.map(([name, value]) => [name.toLowerCase(), String(value)])
.sort(([left], [right]) => left.localeCompare(right))
assert.equal(
new Set(entries.map(([name]) => name)).size,
entries.length,
'Duplicate environment keys'
)
return {
hash: hash(JSON.stringify(entries)),
versions: Object.fromEntries(
entries.filter(
([name, value]) =>
/^(visualstudioversion|vscmd_ver|windowssdkversion|vctoolsversion|vscmd_arg_tgt_arch)$/.test(
name
) && /^(?:[\d.]+\\?|x64|amd64|arm64)$/.test(value)
)
),
compiler: Object.fromEntries(
entries
.filter(([name]) => compilerEnvironmentKey.test(name))
.map(([name, value]) => [name, hash(value)])
)
}
}
export function changedEnvironmentNames(before, after) {
const normalize = (environment) =>
new Map(Object.entries(environment).map(([name, value]) => [name.toLowerCase(), value]))
const original = normalize(before)
const prepared = normalize(after)
return [...new Set([...original.keys(), ...prepared.keys()])]
.filter((name) => original.get(name) !== prepared.get(name))
.sort()
}
export function processPhase(spec) {
const name = basename(spec.program).toLowerCase()
if (name === 'vswhere.exe') {
return 'discovery'
}
if (name === 'capture-windows-native-environment.cmd') {
return 'capture'
}
if (spec.args?.some((arg) => arg.endsWith('ensure-native-runtime.mjs'))) {
return spec.args.includes('--check-only') ? 'probe' : 'preparation'
}
return spec.args?.includes('rebuild') ? 'addon-build' : 'other'
}
export function installNativeBenchmarkObserver(api, output, environment = process.env) {
const original = api.runProcessSync
const parent = environmentReceipt(environment)
const receipt = { parentBefore: parent, parentAfter: parent, calls: [] }
writeFileSync(output, `${JSON.stringify(receipt, null, 2)}\n`)
api.runProcessSync = (spec) => {
const startedAt = new Date().toISOString()
const start = performance.now()
const childEnvironment = spec.env ?? environment
const call = {
phase: processPhase(spec),
program: basename(spec.program),
args: spec.args,
startedAt,
environment: environmentReceipt(childEnvironment),
changedNames: changedEnvironmentNames(environment, childEnvironment)
}
try {
const result = original(spec)
Object.assign(call, {
code: result.code,
timedOut: result.timedOut,
outputTruncated: result.outputTruncated,
stdoutSha256: hash(result.stdout ?? ''),
stderrSha256: hash(result.stderr ?? ''),
stdoutBytes: Buffer.byteLength(result.stdout ?? ''),
stderrBytes: Buffer.byteLength(result.stderr ?? '')
})
return result
} catch (error) {
call.error = error.message
throw error
} finally {
call.durationMs = performance.now() - start
call.finishedAt = new Date().toISOString()
receipt.calls.push(call)
receipt.parentAfter = environmentReceipt(environment)
assert.equal(
receipt.parentAfter.hash,
parent.hash,
'Compiler setup changed its parent environment'
)
writeFileSync(output, `${JSON.stringify(receipt, null, 2)}\n`)
}
}
return receipt
}
if (process.env.ORCA_NATIVE_BENCHMARK_TRACE) {
const require = createRequire(import.meta.url)
installNativeBenchmarkObserver(
require('@orca/process-host'),
process.env.ORCA_NATIVE_BENCHMARK_TRACE
)
}
@@ -0,0 +1,212 @@
import assert from 'node:assert/strict'
import { mkdtempSync, readFileSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { pathToFileURL } from 'node:url'
import { test } from 'vitest'
import { parse } from 'yaml'
import { runProcess } from '@orca/process-host'
import {
assertNativeColdProbe,
assertNoHeaderDownloads,
validateObservedPreparation
} from './benchmark-windows-native-preparation.mjs'
import {
changedEnvironmentNames,
environmentReceipt,
installNativeBenchmarkObserver
} from './windows-native-benchmark-observer.mjs'
const original = { Path: 'unchanged', TOKEN: 'private' }
const parent = environmentReceipt(original)
const captureEnvironment = { ...original, VCINSTALLDIR: 'compiler' }
const call = (phase, code = 0, prepared = false) => ({
phase,
code,
environment: prepared ? environmentReceipt(captureEnvironment) : parent,
changedNames: prepared ? ['vcinstalldir'] : []
})
const receipt = (calls) => ({ parentBefore: parent, parentAfter: parent, calls })
const candidate = () =>
receipt([call('probe', 1), call('discovery'), call('capture'), call('preparation', 0, true)])
for (const [variant, warm, calls] of [
[
'control',
false,
[call('addon-build'), call('addon-build'), call('addon-build'), call('addon-build')]
],
['control', true, []],
['candidate', false, candidate().calls],
['candidate', true, [call('probe'), call('preparation')]],
[
'fallback',
false,
[call('probe', 1), call('discovery'), call('capture', 7), call('preparation')]
],
['fallback', true, [call('probe'), call('preparation')]]
]) {
test(`qualifies ${variant} ${warm ? 'warm' : 'cold'} receipts`, () =>
validateObservedPreparation(receipt(calls), variant, warm))
}
test('fails closed on an unobserved or unchanged candidate', () => {
assert.throws(() => validateObservedPreparation(receipt([]), 'candidate'), /discovery count/)
const missingCapture = candidate()
missingCapture.calls.splice(2, 1)
assert.throws(
() => validateObservedPreparation(missingCapture, 'candidate'),
/developer command count/
)
const unchanged = candidate()
unchanged.calls[3] = call('preparation')
assert.throws(() => validateObservedPreparation(unchanged, 'candidate'), /not applied/)
})
test('rejects failed preparation and unrelated or persistent environment changes', () => {
for (const mutate of [
(value) => {
value.calls[3].code = 2
},
(value) => {
value.calls[3].changedNames = ['token']
},
(value) => {
value.parentAfter = environmentReceipt(captureEnvironment)
},
(value) => {
value.calls[2].timedOut = true
}
]) {
const value = candidate()
mutate(value)
assert.throws(() => validateObservedPreparation(value, 'candidate'))
}
assert.throws(
() =>
validateObservedPreparation(
receipt([call('probe'), call('preparation', 0, true)]),
'candidate',
true
),
/changed compiler/
)
})
test('requires all four initial addon failures and excludes timed header downloads', () => {
const result = {
code: 1,
stderr: [
'node-pty',
'@orca/windows-registry',
'@orca/windows-security',
'@vscode/windows-process-tree'
]
.map((name) => `${name}: unavailable`)
.join('\n')
}
assertNativeColdProbe(result)
assert.throws(() =>
assertNativeColdProbe({ ...result, stderr: result.stderr.replace('node-pty:', 'missing:') })
)
assertNoHeaderDownloads({ stdout: '', stderr: 'gyp info find VS using VS2026' })
assert.throws(
() =>
assertNoHeaderDownloads({
stdout: '',
stderr: 'gyp http GET https://nodejs.org/header.tar.gz'
}),
/downloaded/
)
})
test('uses case-insensitive environment comparisons and never publishes values', () => {
assert.equal(
environmentReceipt(original).hash,
environmentReceipt({ PATH: 'unchanged', token: 'private' }).hash
)
assert.deepEqual(
changedEnvironmentNames(original, {
PATH: 'unchanged',
TOKEN: 'private',
VCINSTALLDIR: 'compiler'
}),
['vcinstalldir']
)
assert(!JSON.stringify(parent).includes('private'))
assert.throws(() => environmentReceipt({ PATH: 'first', Path: 'second' }), /Duplicate/)
})
test('writes an empty warm trace and observes calls without changing execution', () => {
const directory = mkdtempSync(join(tmpdir(), 'orca-native-observer-test-'))
try {
const output = join(directory, 'trace.json')
const result = { code: 0, stdout: 'original stdout', stderr: '', timedOut: false }
const seen = []
const api = {
runProcessSync: (spec) => {
seen.push(spec)
return result
}
}
installNativeBenchmarkObserver(api, output, original)
assert.deepEqual(JSON.parse(readFileSync(output, 'utf8')).calls, [])
const spec = { program: 'vswhere.exe', args: ['-latest'], stdio: 'pipe' }
assert.equal(api.runProcessSync(spec), result)
assert.deepEqual(seen, [spec])
const value = JSON.parse(readFileSync(output, 'utf8'))
assert.equal(value.calls[0].phase, 'discovery')
assert.equal(value.calls[0].stdoutBytes, result.stdout.length)
assert.equal(value.parentBefore.hash, value.parentAfter.hash)
assert(!readFileSync(output, 'utf8').includes('original stdout'))
} finally {
rmSync(directory, { recursive: true, force: true })
}
})
test('preload observes the CJS process-host export imported by production ESM code', async () => {
const directory = mkdtempSync(join(tmpdir(), 'orca-native-observer-esm-test-'))
try {
const trace = join(directory, 'trace.json')
const program = `import { runProcessSync } from '@orca/process-host'; const value = runProcessSync({program:process.execPath,args:['-e','process.stdout.write("proof")']}); if(value.stdout !== 'proof') process.exit(2);`
const result = await runProcess({
program: process.execPath,
args: [
'--import',
pathToFileURL(join(import.meta.dirname, 'windows-native-benchmark-observer.mjs')).href,
'--input-type=module',
'-e',
program
],
cwd: join(import.meta.dirname, '../..'),
env: { ...process.env, ORCA_BACKGROUND_LAUNCH: '1', ORCA_NATIVE_BENCHMARK_TRACE: trace }
})
assert.equal(result.code, 0, result.stderr)
const value = JSON.parse(readFileSync(trace, 'utf8'))
assert.equal(value.calls.length, 1)
assert.equal(value.calls[0].code, 0)
} finally {
rmSync(directory, { recursive: true, force: true })
}
})
test('manual workflow freezes source and limits Windows occupancy without changing a PR gate', () => {
const workflow = parse(
readFileSync(
join(import.meta.dirname, '../../.github/workflows/windows-native-preparation-benchmark.yml'),
'utf8'
)
)
assert.deepEqual(Object.keys(workflow.on), ['workflow_dispatch'])
assert.equal(workflow.jobs.compare.strategy['max-parallel'], 2)
assert.deepEqual(workflow.jobs.compare.strategy.matrix.os, ['windows-2022', 'windows-11-arm'])
assert.equal(workflow.jobs.compare.steps[0].with.ref, '${{ inputs.source_sha }}')
const install = workflow.jobs.compare.steps.find(
(step) => step.uses === './.github/actions/install-node-dependencies'
)
assert.equal(install.with['native-runtime'], 'none')
assert.equal(install.with['node-version'], '24.21.0')
assert.equal(install.with['cache-pnpm-store'], 'false')
assert.equal(workflow.jobs.compare.steps.at(-1).if, 'always()')
assert(!Object.hasOwn(workflow.jobs, 'verify'))
})
@@ -0,0 +1,55 @@
import { describe, expect, it, vi } from 'vitest'
import { classifyPrJobs } from './pr-code-change-scope.mjs'
import { classifyNodeServerChanges } from './node-server-change-scope.mjs'
import { nodeServerQualification } from './node-server-qualification.mjs'
const toolchainSources = [
'config/scripts/initialize-windows-native-toolchain.mjs',
'config/scripts/capture-windows-native-environment.cmd'
]
describe('Windows native toolchain CI routing', () => {
it.each(toolchainSources)(
'prepares native caches and packages for a change to %s alone',
(file) => {
expect(classifyPrJobs([file])).toMatchObject({
should_run: true,
native_cache_changed: true,
package: true,
package_windows: true
})
}
)
it.each(toolchainSources)(
'selects both Windows server runners for a change to %s alone',
async (file) => {
const collect = vi.fn(async () => new Set())
for (const options of [
{},
{ deferGraph: true },
{ modifiedFiles: [file] },
{ deferGraph: true, modifiedFiles: [file] }
]) {
const scope = await classifyNodeServerChanges([file], collect, options)
expect(scope).toEqual({ shouldRun: true, reason: `Build or CI input changed: ${file}` })
expect(nodeServerQualification([file], scope)).toEqual({
qualification: false,
runners: ['ubuntu-22.04', 'windows-2022', 'windows-11-arm']
})
}
expect(collect).not.toHaveBeenCalled()
}
)
it('preserves unrelated build-script routing', async () => {
const file = 'config/scripts/unrelated-toolchain.mjs'
expect(classifyPrJobs([file])).toMatchObject({
test: true,
native_cache_changed: false,
package: false,
package_windows: false
})
expect((await classifyNodeServerChanges([file], async () => new Set())).shouldRun).toBe(false)
})
})