mirror of
https://github.com/openai/codex.git
synced 2026-09-15 12:08:01 +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
627 lines
28 KiB
YAML
627 lines
28 KiB
YAML
name: rust-release-windows
|
|
|
|
on:
|
|
workflow_call:
|
|
|
|
env:
|
|
WINDOWS_BINARIES: "codex codex-code-mode-host codex-responses-api-proxy codex-windows-sandbox-setup codex-windows-sandbox-service codex-command-runner codex-app-server"
|
|
|
|
jobs:
|
|
build-windows-binaries:
|
|
name: Build Windows binaries - ${{ matrix.runner }} - ${{ matrix.target }} - ${{ matrix.bundle }}
|
|
runs-on: ${{ matrix.runs_on }}
|
|
# Windows release builds can exceed an hour, so keep the timeout aligned
|
|
# with the top-level release build headroom.
|
|
timeout-minutes: 90
|
|
permissions:
|
|
contents: read
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: windows-x64
|
|
target: x86_64-pc-windows-msvc
|
|
bundle: primary
|
|
binaries: "codex codex-code-mode-host codex-responses-api-proxy"
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-x64
|
|
- runner: windows-arm64
|
|
target: aarch64-pc-windows-msvc
|
|
bundle: primary
|
|
binaries: "codex codex-code-mode-host codex-responses-api-proxy"
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-arm64
|
|
- runner: windows-x64
|
|
target: x86_64-pc-windows-msvc
|
|
bundle: helpers
|
|
binaries: "codex-windows-sandbox-setup codex-windows-sandbox-service codex-command-runner"
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-x64
|
|
- runner: windows-arm64
|
|
target: aarch64-pc-windows-msvc
|
|
bundle: helpers
|
|
binaries: "codex-windows-sandbox-setup codex-windows-sandbox-service codex-command-runner"
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-arm64
|
|
- runner: windows-x64
|
|
target: x86_64-pc-windows-msvc
|
|
bundle: app-server
|
|
binaries: "codex-app-server codex-code-mode-host"
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-x64
|
|
- runner: windows-arm64
|
|
target: aarch64-pc-windows-msvc
|
|
bundle: app-server
|
|
binaries: "codex-app-server codex-code-mode-host"
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-arm64
|
|
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-ci
|
|
- name: Print runner specs (Windows)
|
|
shell: powershell
|
|
run: |
|
|
$computer = Get-CimInstance Win32_ComputerSystem
|
|
$cpu = Get-CimInstance Win32_Processor | Select-Object -First 1
|
|
$ramGiB = [math]::Round($computer.TotalPhysicalMemory / 1GB, 1)
|
|
Write-Host "Runner: $env:RUNNER_NAME"
|
|
Write-Host "OS: $([System.Environment]::OSVersion.VersionString)"
|
|
Write-Host "CPU: $($cpu.Name)"
|
|
Write-Host "Logical CPUs: $($computer.NumberOfLogicalProcessors)"
|
|
Write-Host "Physical CPUs: $($computer.NumberOfProcessors)"
|
|
Write-Host "Total RAM: $ramGiB GiB"
|
|
Write-Host "Disk usage:"
|
|
Get-PSDrive -PSProvider FileSystem | Format-Table -AutoSize Name, @{Name='Size(GB)';Expression={[math]::Round(($_.Used + $_.Free) / 1GB, 1)}}, @{Name='Free(GB)';Expression={[math]::Round($_.Free / 1GB, 1)}}
|
|
- uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0
|
|
with:
|
|
targets: ${{ matrix.target }}
|
|
|
|
- name: Configure rusty_v8 artifact overrides and verify checksums
|
|
uses: ./.github/actions/setup-rusty-v8
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
|
|
- name: Configure LLVM linker
|
|
uses: ./.github/actions/setup-msvc-env
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
|
|
- name: Cargo build (Windows binaries)
|
|
shell: bash
|
|
run: |
|
|
target="${{ matrix.target }}"
|
|
if [[ "$target" == "x86_64-pc-windows-msvc" ]]; then
|
|
export LIBSQLITE3_FLAGS=SQLITE_DISABLE_INTRINSIC
|
|
fi
|
|
build_args=()
|
|
for binary in ${{ matrix.binaries }}; do
|
|
build_args+=(--bin "$binary")
|
|
done
|
|
STABLE_GIT_COMMIT="$(git rev-parse HEAD)"
|
|
export STABLE_GIT_COMMIT
|
|
cargo build --target "$target" --release --timings "${build_args[@]}"
|
|
|
|
- name: Upload Cargo timings
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: cargo-timings-rust-release-windows-${{ matrix.target }}-${{ matrix.bundle }}
|
|
path: ${{ env.CARGO_TARGET_DIR }}/**/cargo-timings/cargo-timing.html
|
|
if-no-files-found: warn
|
|
|
|
- name: Stage Windows binaries
|
|
shell: bash
|
|
run: |
|
|
release_dir="$CARGO_TARGET_DIR/${{ matrix.target }}/release"
|
|
output_dir="$release_dir/staged-${{ matrix.bundle }}"
|
|
mkdir -p "$output_dir"
|
|
for binary in ${{ matrix.binaries }}; do
|
|
pdb_name="${binary//-/_}"
|
|
pdb_path="$release_dir/${pdb_name}.pdb"
|
|
if [[ ! -f "$pdb_path" ]]; then
|
|
pdb_path="$release_dir/${binary}.pdb"
|
|
fi
|
|
if [[ ! -f "$pdb_path" ]]; then
|
|
echo "PDB for $binary not found at $release_dir/${pdb_name}.pdb or $release_dir/${binary}.pdb" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cp "$release_dir/${binary}.exe" "$output_dir/${binary}.exe"
|
|
cp "$pdb_path" "$output_dir/${binary}.pdb"
|
|
done
|
|
|
|
- name: Upload Windows binaries
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: windows-binaries-${{ matrix.target }}-${{ matrix.bundle }}
|
|
path: |
|
|
${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/release/staged-${{ matrix.bundle }}/*
|
|
|
|
build-windows-voice:
|
|
name: Build Windows voice - ${{ matrix.target }}
|
|
runs-on: ${{ matrix.runs_on }}
|
|
timeout-minutes: 120
|
|
permissions:
|
|
contents: read
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- target: x86_64-pc-windows-msvc
|
|
arch: x86_64
|
|
python_arch: x64
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-x64
|
|
- target: aarch64-pc-windows-msvc
|
|
arch: aarch64
|
|
python_arch: arm64
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-arm64
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: "3.12"
|
|
architecture: ${{ matrix.python_arch }}
|
|
- name: Prepare Bazel CI
|
|
uses: ./.github/actions/prepare-bazel-ci
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
cache-scope: release-voice-windows
|
|
- uses: ./.github/actions/setup-msvc-env
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
- name: Refresh Bazel PATH for the selected MSVC target
|
|
shell: pwsh
|
|
run: ./.github/scripts/compute-bazel-windows-path.ps1
|
|
- name: Download pinned Windows build inputs
|
|
shell: pwsh
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
$manifest = Get-Content -Raw .github/scripts/voice-cygwin-snapshot.json | ConvertFrom-Json
|
|
$pin = $manifest.archive
|
|
$source = $manifest.sourceArchive
|
|
$directory = Join-Path $env:RUNNER_TEMP "voice-cygwin-snapshot"
|
|
New-Item -ItemType Directory -Path $directory | Out-Null
|
|
gh release download $pin.tag --repo "${{ github.repository }}" --pattern $pin.name --pattern $source.name --dir $directory
|
|
if ($LASTEXITCODE -ne 0) { throw "Cannot obtain the public Cygwin inputs and source" }
|
|
$sourceFile = Join-Path $directory $source.name
|
|
if ((Get-Item $sourceFile).Length -ne $source.bytes -or
|
|
(Get-FileHash $sourceFile -Algorithm SHA256).Hash.ToLowerInvariant() -ne $source.sha256) {
|
|
throw "Public Cygwin source archive mismatch"
|
|
}
|
|
"VOICE_CYGWIN_ARCHIVE=$(Join-Path $directory $pin.name)" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append
|
|
- name: Verify and install pinned public build tools
|
|
shell: pwsh
|
|
run: |
|
|
& ./.github/scripts/setup-voice-windows.ps1 -Target "${{ matrix.target }}" -SnapshotArchive $env:VOICE_CYGWIN_ARCHIVE
|
|
if (-not $env:SystemRoot) { throw "Windows SystemRoot is required for native audio actions" }
|
|
"VOICE_WINDOWS_SYSTEM_ROOT=$env:SystemRoot" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append
|
|
$hostArch = $env:PROCESSOR_ARCHITEW6432
|
|
if (-not $hostArch) { $hostArch = $env:PROCESSOR_ARCHITECTURE }
|
|
if (-not $hostArch) { throw "Windows host architecture is required" }
|
|
"VOICE_WINDOWS_HOST_ARCH=$hostArch" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append
|
|
- name: Build same-commit native runtime and helper
|
|
shell: bash
|
|
env:
|
|
ARCH: ${{ matrix.arch }}
|
|
VOICE_ARCH: ${{ matrix.arch }}
|
|
# Avoid Java JIT crashes in the Windows ARM64 voice build.
|
|
BAZEL_HOST_JVM_ARG: ${{ matrix.arch == 'aarch64' && '-Xint' || '' }}
|
|
BUILDBUDDY_API_KEY: ""
|
|
run: |
|
|
(cd codex-rs && cargo update --workspace)
|
|
python .github/scripts/watch_voice_bazel.py "$(cygpath -w "$BASH")" ./.github/scripts/run-bazel-ci.sh \
|
|
--remote-download-toplevel \
|
|
--print-failed-action-summary \
|
|
--windows-msvc-host-platform \
|
|
-- \
|
|
test -c opt \
|
|
--platforms=//:local_windows_msvc \
|
|
--extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows,@local_config_cc//:cc-toolchain-arm64_windows,//third_party/voice:windows_pkg_config_toolchain,//third_party/voice:windows_cmake_toolchain \
|
|
--repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=0 \
|
|
--repo_env=BAZEL_MSVC_RUNTIME_VISUAL_STUDIO_EULA=1 \
|
|
--inject_repository="voice_windows_tools=$VOICE_WINDOWS_BAZEL_REPOSITORY" \
|
|
--//third_party/voice:windows_installed_tools=@voice_windows_tools//:tools \
|
|
--action_env="SystemRoot=$VOICE_WINDOWS_SYSTEM_ROOT" \
|
|
--host_action_env="SystemRoot=$VOICE_WINDOWS_SYSTEM_ROOT" \
|
|
--action_env="PROCESSOR_ARCHITECTURE=$VOICE_WINDOWS_HOST_ARCH" \
|
|
--host_action_env="PROCESSOR_ARCHITECTURE=$VOICE_WINDOWS_HOST_ARCH" \
|
|
--output_groups=default,receipt,sdk \
|
|
--workspace_status_command=./scripts/workspace-status.cmd \
|
|
--build_metadata=COMMIT_SHA="$GITHUB_SHA" \
|
|
-- \
|
|
"//third_party/voice:native_runtime_windows_$ARCH" \
|
|
@rules_rust//cargo/private/cargo_build_script_runner:test \
|
|
//codex-rs/voice-host:codex-voice-host
|
|
- name: Stage verified voice build output
|
|
shell: bash
|
|
env:
|
|
TARGET: ${{ matrix.target }}
|
|
ARCH: ${{ matrix.arch }}
|
|
run: |
|
|
set -euo pipefail
|
|
runtime="bazel-bin/third_party/voice/native_runtime_windows_${ARCH}"
|
|
PYTHONPATH=third_party/voice python - "$runtime" "$TARGET" <<'PY'
|
|
from pathlib import Path
|
|
import sys
|
|
from package_runtime import runtime_files
|
|
runtime_files(Path(sys.argv[1]).resolve(strict=True), sys.argv[2])
|
|
PY
|
|
output="voice-unsigned/${TARGET}"
|
|
mkdir -p "$output"
|
|
cp -R "$runtime" "$output/runtime"
|
|
cp bazel-bin/codex-rs/voice-host/codex-voice-host.exe "$output/codex-voice-host.exe"
|
|
chmod -R u+w "$output"
|
|
tar -C "$output" -czf "voice-unsigned-${TARGET}.tar.gz" runtime codex-voice-host.exe
|
|
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: voice-${{ matrix.target }}-unsigned
|
|
path: voice-unsigned-${{ matrix.target }}.tar.gz
|
|
if-no-files-found: error
|
|
|
|
build-windows-symbols:
|
|
needs:
|
|
- build-windows-binaries
|
|
name: Build Windows symbols - ${{ matrix.target }}
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 15
|
|
permissions:
|
|
contents: read
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
target:
|
|
- aarch64-pc-windows-msvc
|
|
- x86_64-pc-windows-msvc
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-ci
|
|
- name: Download prebuilt Windows binaries
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
pattern: windows-binaries-${{ matrix.target }}-*
|
|
merge-multiple: true
|
|
path: ${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/release
|
|
- name: Build symbols archive
|
|
shell: bash
|
|
run: |
|
|
bash "${GITHUB_WORKSPACE}/.github/scripts/archive-release-symbols-and-strip-binaries.sh" \
|
|
--target "${{ matrix.target }}" \
|
|
--artifact-name "${{ matrix.target }}" \
|
|
--release-dir "${CARGO_TARGET_DIR}/${{ matrix.target }}/release" \
|
|
--archive-dir "symbols-dist/${{ matrix.target }}" \
|
|
--binaries "${WINDOWS_BINARIES}"
|
|
- name: Upload symbols archive
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: ${{ matrix.target }}-symbols
|
|
path: codex-rs/symbols-dist/${{ matrix.target }}/*
|
|
if-no-files-found: error
|
|
|
|
build-windows:
|
|
needs:
|
|
- build-windows-binaries
|
|
- build-windows-voice
|
|
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
|
|
runs-on: ${{ matrix.runs_on }}
|
|
environment:
|
|
name: azure-artifact-signing
|
|
deployment: false
|
|
timeout-minutes: 120
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: windows-x64
|
|
target: x86_64-pc-windows-msvc
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-x64
|
|
- runner: windows-x64
|
|
target: aarch64-pc-windows-msvc
|
|
runs_on:
|
|
group: ${{ github.event.repository.name }}-runners
|
|
labels: ${{ github.event.repository.name }}-windows-x64
|
|
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: ./.github/actions/setup-ci
|
|
|
|
- name: Download prebuilt Windows primary binaries
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: windows-binaries-${{ matrix.target }}-primary
|
|
path: ${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/release
|
|
|
|
- name: Download prebuilt Windows helper binaries
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: windows-binaries-${{ matrix.target }}-helpers
|
|
path: ${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/release
|
|
|
|
- name: Download prebuilt Windows app-server binary
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: windows-binaries-${{ matrix.target }}-app-server
|
|
path: ${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/release
|
|
|
|
- name: Verify binaries
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
for binary in ${WINDOWS_BINARIES}; do
|
|
ls -lh "$CARGO_TARGET_DIR/${{ matrix.target }}/release/${binary}.exe"
|
|
done
|
|
|
|
- name: Sign Windows binaries with Azure Trusted Signing
|
|
uses: ./.github/actions/windows-code-sign
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
binaries: ${{ env.WINDOWS_BINARIES }}
|
|
client-id: ${{ secrets.AZURE_ARTIFACT_SIGNING_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_ARTIFACT_SIGNING_TENANT_ID }}
|
|
subscription-id: ${{ secrets.AZURE_ARTIFACT_SIGNING_SUBSCRIPTION_ID }}
|
|
endpoint: ${{ secrets.AZURE_ARTIFACT_SIGNING_ENDPOINT }}
|
|
account-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }}
|
|
certificate-profile-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }}
|
|
|
|
- name: Download matching native voice build
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: voice-${{ matrix.target }}-unsigned
|
|
path: ${{ runner.temp }}/unsigned-voice
|
|
|
|
- name: Stage voice files for signing
|
|
id: voice_files
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
target="${{ matrix.target }}"
|
|
unsigned="${RUNNER_TEMP}/unsigned-voice/extracted"
|
|
signed="${GITHUB_WORKSPACE}/signed-voice/${target}"
|
|
mkdir -p "$unsigned" "$signed"
|
|
tar -xzf "$(cygpath -u "${RUNNER_TEMP}/unsigned-voice/voice-unsigned-${target}.tar.gz")" -C "$(cygpath -u "$unsigned")"
|
|
python "${GITHUB_WORKSPACE}/third_party/voice/release_runtime.py" stage \
|
|
--source "$unsigned/runtime" --target "$target" --output "$signed/runtime"
|
|
cp "$unsigned/codex-voice-host.exe" "$signed/codex-voice-host.exe"
|
|
chmod -R u+w "$signed"
|
|
{
|
|
echo 'files<<EOF'
|
|
echo "$signed/codex-voice-host.exe"
|
|
find "$signed/runtime/bin" -name '*.dll' -type f -print
|
|
echo 'EOF'
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Sign Windows voice helper and native DLLs
|
|
uses: azure/trusted-signing-action@1d365fec12862c4aa68fcac418143d73f0cea293 # v0.5.11
|
|
with:
|
|
endpoint: ${{ secrets.AZURE_ARTIFACT_SIGNING_ENDPOINT }}
|
|
trusted-signing-account-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }}
|
|
certificate-profile-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }}
|
|
exclude-environment-credential: true
|
|
exclude-workload-identity-credential: true
|
|
exclude-managed-identity-credential: true
|
|
exclude-shared-token-cache-credential: true
|
|
exclude-visual-studio-credential: true
|
|
exclude-visual-studio-code-credential: true
|
|
exclude-azure-cli-credential: false
|
|
exclude-azure-powershell-credential: true
|
|
exclude-azure-developer-cli-credential: true
|
|
exclude-interactive-browser-credential: true
|
|
cache-dependencies: false
|
|
files: ${{ steps.voice_files.outputs.files }}
|
|
|
|
- uses: ./.github/actions/setup-msvc-env
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
|
|
- name: Seal and verify signed voice output
|
|
shell: pwsh
|
|
run: |
|
|
$target = "${{ matrix.target }}"
|
|
$signed = Join-Path $env:GITHUB_WORKSPACE "signed-voice/$target"
|
|
python (Join-Path $env:GITHUB_WORKSPACE 'third_party/voice/windows_crt.py') --root (Join-Path $signed 'runtime') --target $target --helper (Join-Path $signed 'codex-voice-host.exe')
|
|
if ($LASTEXITCODE -ne 0) { throw 'Cannot stage verified Microsoft CRT' }
|
|
$files = @(Join-Path $signed "codex-voice-host.exe") + @(
|
|
Get-ChildItem (Join-Path $signed "runtime/bin") -Filter *.dll -File |
|
|
ForEach-Object FullName
|
|
)
|
|
if ($files.Count -lt 8) { throw "Voice DLL closure is incomplete" }
|
|
foreach ($file in $files) {
|
|
$signature = Get-AuthenticodeSignature $file
|
|
if ($signature.Status -ne 'Valid') { throw "Unsigned voice file: $file ($($signature.Status))" }
|
|
}
|
|
python (Join-Path $env:GITHUB_WORKSPACE 'third_party/voice/release_runtime.py') seal --target $target --output (Join-Path $signed 'runtime')
|
|
if ($LASTEXITCODE -ne 0) { throw 'Cannot seal signed voice runtime' }
|
|
"VOICE_RELEASE_DIR=$signed" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append
|
|
|
|
- name: Stage artifacts
|
|
shell: bash
|
|
run: |
|
|
dest="dist/${{ matrix.target }}"
|
|
mkdir -p "$dest"
|
|
|
|
for binary in ${WINDOWS_BINARIES}; do
|
|
cp "$CARGO_TARGET_DIR/${{ matrix.target }}/release/${binary}.exe" \
|
|
"$dest/${binary}-${{ matrix.target }}.exe"
|
|
done
|
|
|
|
- name: Build Codex package archives
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
target="${{ matrix.target }}"
|
|
archive_script="${GITHUB_WORKSPACE}/.github/scripts/build-codex-package-archive.sh"
|
|
voice_args=(--voice-release-dir "$VOICE_RELEASE_DIR")
|
|
voice_args+=(--release-version "${GITHUB_REF_NAME#rust-v}")
|
|
bash "$archive_script" \
|
|
--target "$target" --bundle primary \
|
|
--entrypoint-dir "$CARGO_TARGET_DIR/$target/release" \
|
|
--archive-dir "dist/$target" "${voice_args[@]}"
|
|
bash "$archive_script" \
|
|
--target "$target" --bundle app-server \
|
|
--entrypoint-dir "$CARGO_TARGET_DIR/$target/release" \
|
|
--archive-dir "dist/$target"
|
|
|
|
- name: Verify packaged Windows voice closure
|
|
shell: pwsh
|
|
run: |
|
|
$target = "${{ matrix.target }}"
|
|
$package = Join-Path $env:RUNNER_TEMP "verify-voice-archive-$target"
|
|
New-Item -ItemType Directory -Path $package | Out-Null
|
|
tar -xzf "dist/$target/codex-package-$target.tar.gz" -C $package
|
|
if ($LASTEXITCODE -ne 0) { throw "Cannot extract the final Windows package" }
|
|
$voice = Join-Path $package 'codex-resources/voice'
|
|
$helper = Join-Path $voice 'bin/codex-voice-host.exe'
|
|
if (-not (Test-Path $helper) -or -not (Test-Path (Join-Path $voice 'bin/gstreamer-1.0-0.dll'))) {
|
|
throw 'Signed Windows voice files are missing from the canonical package'
|
|
}
|
|
$signature = Get-AuthenticodeSignature $helper
|
|
if ($signature.Status -ne 'Valid') { throw "Packaged helper signature: $($signature.Status)" }
|
|
python -c 'import sys; from pathlib import Path; sys.path.insert(0, sys.argv[3]); from package_runtime import runtime_files; runtime_files(Path(sys.argv[1]), sys.argv[2], public_release=True)' $voice $target (Join-Path $env:GITHUB_WORKSPACE 'third_party/voice')
|
|
if ($LASTEXITCODE -ne 0) { throw 'Packaged runtime receipt verification failed' }
|
|
|
|
- name: Build Python runtime wheel
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
case "${{ matrix.target }}" in
|
|
aarch64-pc-windows-msvc)
|
|
platform_tag="win_arm64"
|
|
;;
|
|
x86_64-pc-windows-msvc)
|
|
platform_tag="win_amd64"
|
|
;;
|
|
*)
|
|
echo "No Python runtime wheel platform tag for ${{ matrix.target }}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
python -m venv "${RUNNER_TEMP}/python-runtime-build-venv"
|
|
"${RUNNER_TEMP}/python-runtime-build-venv/Scripts/python.exe" -m pip install build
|
|
|
|
# The wheel's Windows support floor predates the native voice
|
|
# runtime's verified device/VC++ prerequisites. Keep it voice-free.
|
|
wheel_archives="${RUNNER_TEMP}/voice-free-wheel/${{ matrix.target }}"
|
|
bash "${GITHUB_WORKSPACE}/.github/scripts/build-codex-package-archive.sh" \
|
|
--target "${{ matrix.target }}" --bundle primary \
|
|
--entrypoint-dir "$CARGO_TARGET_DIR/${{ matrix.target }}/release" \
|
|
--archive-dir "$wheel_archives"
|
|
python - "$wheel_archives/codex-package-${{ matrix.target }}.tar.gz" <<'PY'
|
|
import sys
|
|
import tarfile
|
|
with tarfile.open(sys.argv[1]) as archive:
|
|
assert not any("codex-resources/voice/" in member.name for member in archive)
|
|
PY
|
|
stage_dir="${RUNNER_TEMP}/openai-codex-cli-bin-${{ matrix.target }}"
|
|
wheel_dir="${GITHUB_WORKSPACE}/python-runtime-dist/${{ matrix.target }}"
|
|
python "${GITHUB_WORKSPACE}/sdk/python/scripts/update_sdk_artifacts.py" \
|
|
stage-runtime \
|
|
"$stage_dir" \
|
|
"$wheel_archives/codex-package-${{ matrix.target }}.tar.gz" \
|
|
--codex-version "${GITHUB_REF_NAME}" \
|
|
--platform-tag "$platform_tag"
|
|
"${RUNNER_TEMP}/python-runtime-build-venv/Scripts/python.exe" -m build --wheel --outdir "$wheel_dir" "$stage_dir"
|
|
|
|
- name: Upload Python runtime wheel
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: python-runtime-wheel-${{ matrix.target }}
|
|
path: python-runtime-dist/${{ matrix.target }}/*.whl
|
|
if-no-files-found: error
|
|
|
|
- name: Compress artifacts
|
|
shell: bash
|
|
run: |
|
|
# Path that contains the uncompressed binaries for the current
|
|
# ${{ matrix.target }}
|
|
dest="dist/${{ matrix.target }}"
|
|
repo_root=$PWD
|
|
target="${{ matrix.target }}"
|
|
export dest repo_root target
|
|
|
|
# For compatibility with environments that lack the `zstd` tool we
|
|
# additionally create a `.tar.gz` and `.zip` for every Windows binary.
|
|
# The end result is:
|
|
# codex-<target>.zst
|
|
# codex-<target>.tar.gz
|
|
# codex-<target>.zip
|
|
# Variables in the single-quoted script expand in the child shell.
|
|
# shellcheck disable=SC2016
|
|
printf '%s\0' "$dest"/* |
|
|
xargs -0 -n1 -P2 bash -c '
|
|
set -euo pipefail
|
|
f=$1
|
|
base="$(basename "$f")"
|
|
# Skip files that are already archives (should not happen, but be
|
|
# safe).
|
|
if [[ "$base" == *.tar.gz || "$base" == *.tar.zst || "$base" == *.zip || "$base" == *.dmg ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Do not try to compress signature bundles.
|
|
if [[ "$base" == *.sigstore ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Create per-binary tar.gz
|
|
tar -C "$dest" -czf "$dest/${base}.tar.gz" "$base"
|
|
|
|
# Create zip archive for Windows binaries.
|
|
# Must run from inside the dest dir so 7z does not embed the
|
|
# directory path inside the zip.
|
|
if [[ "$base" == "codex-${target}.exe" ]]; then
|
|
# Preserve WinGet executable paths while including the signed
|
|
# runtime, resources, and package metadata from the canonical tar.
|
|
bundle_dir="$(mktemp -d)"
|
|
tar -xzf "$dest/codex-package-${target}.tar.gz" -C "$bundle_dir"
|
|
python "${GITHUB_WORKSPACE}/scripts/build_winget_package.py" "$(cygpath -w "$bundle_dir")"
|
|
(cd "$bundle_dir" && 7z a "$repo_root/$dest/${base}.zip" .)
|
|
rm -rf "$bundle_dir"
|
|
else
|
|
(cd "$dest" && 7z a "${base}.zip" "$base")
|
|
fi
|
|
|
|
# Keep raw executables and produce .zst alongside them.
|
|
"${GITHUB_WORKSPACE}/.github/workflows/zstd" -T0 -19 "$dest/$base"
|
|
' _
|
|
|
|
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: ${{ matrix.target }}
|
|
path: |
|
|
codex-rs/dist/${{ matrix.target }}/*
|