mirror of
https://github.com/openai/codex.git
synced 2026-09-16 12:13:30 +00:00
## Why Windows release packages need the voice helper and native audio libraries. Realtime TLS connections on fresh Windows installations also need platform certificate validation so Windows can retrieve missing trusted roots on demand. ## What changed - Build and sign the voice helper and audio DLLs for Windows x64 and ARM64, bundle a pinned Microsoft CRT DLL, and verify signatures and runtime receipts before packaging. - Add verified, pinned Cygwin and native build tools plus MSVC linker, compiler, and path handling fixes for the Windows Bazel builds. - Include voice resources in primary release archives and WinGet packages. Preserve WinGet executable names, update manifest hashes, and recognize the package root through matching entrypoint metadata. Keep Python runtime wheels voice-free to preserve their existing Windows support floor. - Use Windows platform TLS validation for realtime WebSockets when no custom CA bundle is configured, preserving custom CA behavior. ## Testing Add coverage for build-input integrity and unsafe paths, signed Windows runtime assembly, WinGet file and hash preservation, package discovery, and TLS trust selection, untrusted certificate rejection, and hostname validation. GitOrigin-RevId: 423da35872fa5549d69fd4ca97d922bb49599386
97 lines
5.6 KiB
PowerShell
97 lines
5.6 KiB
PowerShell
# CI-only prerequisites. Never install these tools into a Codex package.
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$Target,
|
|
[Parameter(Mandatory = $true)][string]$SnapshotArchive
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$PkgHashes = @{
|
|
"x86_64-pc-windows-msvc" = @("x64", "5604cf25ef38bb6a09520cff25ae9f0ecd8c2443053b15e40df4ad1eae0e4405")
|
|
"aarch64-pc-windows-msvc" = @("arm64", "d5752ce2ac2296c8abb91fb12c12e75ee99ba8a18b52ce5febf325847b6f062b")
|
|
}
|
|
if (-not $PkgHashes.ContainsKey($Target)) { throw "Unsupported target: $Target" }
|
|
$Root = Join-Path $env:RUNNER_TEMP "voice-windows-build-tools"
|
|
$Evidence = Join-Path $Root "evidence"
|
|
$Cygwin = Join-Path $Root "cygwin"
|
|
$Cache = Join-Path $Root "cache"
|
|
New-Item -ItemType Directory -Path $Root, $Evidence | Out-Null
|
|
$ManifestPath = Join-Path $PSScriptRoot "voice-cygwin-snapshot.json"
|
|
$Manifest = Get-Content -Raw $ManifestPath | ConvertFrom-Json
|
|
$SnapshotTool = Join-Path $PSScriptRoot "voice-cygwin-inputs.py"
|
|
& python $SnapshotTool extract --archive $SnapshotArchive --directory (Join-Path $Cache $Manifest.cacheDirectory)
|
|
if ($LASTEXITCODE -ne 0) { throw "Cygwin snapshot could not be verified and extracted" }
|
|
Copy-Item $ManifestPath (Join-Path $Evidence "cygwin-snapshot.json")
|
|
|
|
# Official https://cygwin.com/setup/sha512.sum and pkgconf release asset digests.
|
|
# The complete package closure is pinned separately in cygwin-snapshot.json.
|
|
$Inputs = @(
|
|
@{
|
|
url = "https://cygwin.com/setup/setup-2.937.x86_64.exe"
|
|
file = "setup.exe"
|
|
algorithm = "SHA512"
|
|
digest = "6acea47c59781c9e7f544a18d53935d59df6e44d5d52ac95ee165671b8e388820455eebf30ccc7d254b00c3d0eb694269a0f8dc84b17944c1f355dac9c5aafcc"
|
|
},
|
|
@{
|
|
url = "https://github.com/pkgconf/pkgconf/releases/download/pkgconf-3.0.6/pkgconf-$($PkgHashes[$Target][0])-3.0.6.msi"
|
|
file = "pkgconf.msi"
|
|
algorithm = "SHA256"
|
|
digest = $PkgHashes[$Target][1]
|
|
}
|
|
)
|
|
foreach ($InputFile in $Inputs) {
|
|
$Destination = Join-Path $Root $InputFile.file
|
|
Invoke-WebRequest -Uri $InputFile.url -OutFile $Destination
|
|
$Actual = (Get-FileHash -Path $Destination -Algorithm $InputFile.algorithm).Hash.ToLowerInvariant()
|
|
if ($Actual -ne $InputFile.digest) { throw "Build input digest mismatch: $($InputFile.file)" }
|
|
}
|
|
$Inputs | ConvertTo-Json | Set-Content (Join-Path $Evidence "bootstrap-inputs.json")
|
|
$Packages = $Manifest.requestedPackages -join ","
|
|
# Only setup.xz + setup.xz.sig are present: local mode still verifies that
|
|
# signature. Never substitute an unsigned setup.ini or enable a network fallback.
|
|
$Setup = Start-Process -FilePath (Join-Path $Root "setup.exe") -Wait -PassThru -ArgumentList @(
|
|
"--quiet-mode", "--no-admin", "--no-shortcuts", "--only-site",
|
|
"--local-install", "--no-version-check",
|
|
"--root", "`"$Cygwin`"", "--local-package-dir", "`"$Cache`"",
|
|
"--packages", $Packages
|
|
)
|
|
if ($Setup.ExitCode -ne 0) { throw "Cygwin setup failed: $($Setup.ExitCode)" }
|
|
Copy-Item (Join-Path $Cygwin "var/log/setup.log*") $Evidence
|
|
Copy-Item (Join-Path $Cygwin "etc/setup/installed.db") $Evidence
|
|
& (Join-Path $Cygwin "bin/cygcheck.exe") -cd | Set-Content (Join-Path $Evidence "packages.txt")
|
|
if ($LASTEXITCODE -ne 0) { throw "Cannot inventory Cygwin packages" }
|
|
& python $SnapshotTool check-installed --inventory (Join-Path $Evidence "packages.txt")
|
|
if ($LASTEXITCODE -ne 0) { throw "Installed Cygwin package set differs from the snapshot" }
|
|
Get-ChildItem $Cache -File -Recurse | ForEach-Object {
|
|
@{ file = [IO.Path]::GetRelativePath($Cache, $_.FullName); bytes = $_.Length;
|
|
sha512 = (Get-FileHash $_.FullName -Algorithm SHA512).Hash.ToLowerInvariant() }
|
|
} | ConvertTo-Json | Set-Content (Join-Path $Evidence "package-cache.json")
|
|
|
|
# Administrative extraction uses TARGETDIR, not a normal MSI installation:
|
|
# no product registration or system PATH modification. Fail rather than fall
|
|
# back to an ambient executable or ordinary installer if the payload is absent.
|
|
$Image = Join-Path $Root "pkgconf-image"
|
|
$Extract = Start-Process msiexec.exe -Wait -PassThru -ArgumentList @(
|
|
"/a", "`"$(Join-Path $Root 'pkgconf.msi')`"", "/qn", "/norestart",
|
|
"TARGETDIR=`"$Image`"", "/L*v", "`"$(Join-Path $Evidence 'pkgconf-extract.log')`""
|
|
)
|
|
if ($Extract.ExitCode -ne 0) { throw "pkgconf extraction failed: $($Extract.ExitCode)" }
|
|
$Candidates = @(Get-ChildItem $Image -Filter pkgconf.exe -File -Recurse)
|
|
if ($Candidates.Count -ne 1) { throw "Expected exactly one native pkgconf executable" }
|
|
# Bazel shell-quotes execpaths containing spaces; Cargo executes PKG_CONFIG
|
|
# directly. Keep the executable and its support files at a space-free execpath.
|
|
$Native = Join-Path $Image "native"
|
|
if (Test-Path $Native) { throw "Native pkgconf destination must be fresh" }
|
|
Move-Item -LiteralPath $Candidates[0].Directory.FullName -Destination $Native
|
|
$PkgConfig = Join-Path $Native "pkgconf.exe"
|
|
$Version = & $PkgConfig --version
|
|
if ($LASTEXITCODE -ne 0 -or $Version -ne "3.0.6") { throw "Unexpected native pkgconf version" }
|
|
@{ target = $Target; cygwin_root = $Cygwin; pkg_config = $PkgConfig;
|
|
pkgconf_version = $Version; requested_packages = $Packages } |
|
|
ConvertTo-Json | Set-Content (Join-Path $Evidence "tools.json")
|
|
# Declare complete installed support trees only after snapshot and tool checks.
|
|
& python (Join-Path $PSScriptRoot "voice_windows_tools.py") --root $Root --target $Target --pkg-config $PkgConfig
|
|
if ($LASTEXITCODE -ne 0) { throw "Cannot declare Windows Bazel tool inputs" }
|
|
"VOICE_WINDOWS_BAZEL_REPOSITORY=$Root" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append
|
|
"VOICE_CYGWIN_ROOT=$Cygwin" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append
|
|
"VOICE_PKG_CONFIG=$PkgConfig" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append
|