mirror of
https://github.com/openai/codex.git
synced 2026-10-20 00:18:49 +00:00
## What changed Pass `BUILDBUDDY_API_KEY` to Linux, macOS, and Windows voice release builds, and give the dedicated macOS and Windows voice jobs access to the `bazel` environment without creating deployments. Use the shared Bazel preparation action and BuildBuddy wrapper for Linux and macOS voice builds so they inherit the existing repository cache and remote cache configuration. GitOrigin-RevId: 52cdf05bc4567f3e8c460d2509e57bb30e667868
705 lines
31 KiB
YAML
705 lines
31 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 }} - ${{ matrix.build-system }}
|
|
# Parallel Bazel artifacts are advisory while Cargo remains the release path.
|
|
continue-on-error: ${{ matrix.build-system == 'bazel' }}
|
|
runs-on: ${{ matrix.runs_on }}
|
|
environment:
|
|
name: bazel
|
|
deployment: false
|
|
# Temporary increase from 90 minutes while Cargo and Bazel build paths coexist.
|
|
# Reassess after the transition using Bazel release build timings.
|
|
timeout-minutes: 120
|
|
permissions:
|
|
contents: read
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
env:
|
|
# Preserve Cargo names while teams opt into the additional Bazel artifacts.
|
|
ARTIFACT_SUFFIX: ${{ matrix.build-system == 'bazel' && '-bazel' || '' }}
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
build-system: [cargo, bazel]
|
|
target:
|
|
- x86_64-pc-windows-msvc
|
|
- aarch64-pc-windows-msvc
|
|
bundle: [primary, helpers, app-server]
|
|
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
|
|
if: matrix.build-system == 'cargo'
|
|
- 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)}}
|
|
- name: Set up Rust toolchain
|
|
uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0
|
|
with:
|
|
targets: ${{ matrix.build-system == 'cargo' && matrix.target || '' }}
|
|
|
|
- name: Prepare Bazel release build
|
|
if: ${{ matrix.build-system == 'bazel' }}
|
|
uses: ./.github/actions/prepare-bazel-ci
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
cache-scope: bazel-release-${{ matrix.bundle }}
|
|
|
|
- name: Configure rusty_v8 artifact overrides and verify checksums
|
|
if: matrix.build-system == 'cargo'
|
|
uses: ./.github/actions/setup-rusty-v8
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
|
|
- name: Configure MSVC environment
|
|
uses: ./.github/actions/setup-msvc-env
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
|
|
- name: Build Bazel release binaries and symbols
|
|
if: ${{ matrix.build-system == 'bazel' }}
|
|
uses: ./.github/actions/build-bazel-release
|
|
env:
|
|
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
bundle: ${{ matrix.bundle }}
|
|
release-dir: ${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/release
|
|
|
|
- name: Cargo build (Windows binaries)
|
|
if: ${{ matrix.build-system == 'cargo' }}
|
|
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: 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 }}${{ env.ARTIFACT_SUFFIX }}
|
|
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 }}
|
|
environment:
|
|
name: bazel
|
|
deployment: false
|
|
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 }}
|
|
BUILDBUDDY_API_KEY: ${{ secrets.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 --config=release \
|
|
--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 }} - ${{ matrix.build-system }}
|
|
continue-on-error: ${{ matrix.build-system == 'bazel' }}
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 15
|
|
permissions:
|
|
contents: read
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
env:
|
|
ARTIFACT_SUFFIX: ${{ matrix.build-system == 'bazel' && '-bazel' || '' }}
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
build-system: [cargo, bazel]
|
|
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 }}-{primary,helpers,app-server}${{ env.ARTIFACT_SUFFIX }}
|
|
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: Suffix Bazel artifact filenames
|
|
if: ${{ matrix.build-system == 'bazel' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
for artifact in "symbols-dist/${{ matrix.target }}"/*; do
|
|
name="${artifact##*/}"
|
|
stem="${name%%.*}"
|
|
mv "$artifact" "${artifact%/*}/${stem}-bazel${name#"$stem"}"
|
|
done
|
|
|
|
- name: Upload symbols archive
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: ${{ matrix.target }}-symbols${{ env.ARTIFACT_SUFFIX }}
|
|
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 }} - ${{ matrix.build-system }}
|
|
continue-on-error: ${{ matrix.build-system == 'bazel' }}
|
|
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
|
|
env:
|
|
ARTIFACT_SUFFIX: ${{ matrix.build-system == 'bazel' && '-bazel' || '' }}
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
build-system: [cargo, bazel]
|
|
target:
|
|
- x86_64-pc-windows-msvc
|
|
- aarch64-pc-windows-msvc
|
|
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${{ env.ARTIFACT_SUFFIX }}
|
|
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${{ env.ARTIFACT_SUFFIX }}
|
|
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${{ env.ARTIFACT_SUFFIX }}
|
|
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 release files with Azure Trusted Signing
|
|
uses: ./.github/actions/windows-code-sign
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
binaries: ${{ env.WINDOWS_BINARIES }}
|
|
# The installer is architecture-independent; sign it only in the x64 job.
|
|
additional-files: ${{ matrix.target == 'x86_64-pc-windows-msvc' && format('{0}/scripts/install/install.ps1', github.workspace) || '' }}
|
|
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
|
|
if: ${{ matrix.build-system == 'cargo' }}
|
|
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_package="${RUNNER_TEMP}/codex-package-${{ matrix.target }}"
|
|
python - "$wheel_package" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
assert not (Path(sys.argv[1]) / "codex-resources" / "voice").exists()
|
|
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_package" \
|
|
--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
|
|
if: ${{ matrix.build-system == 'cargo' }}
|
|
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
|
|
# Start larger binaries first so both workers stay busy.
|
|
find "$dest" -maxdepth 1 -type f -printf '%s %p\0' |
|
|
sort -z -nr |
|
|
cut -z -d ' ' -f 2- |
|
|
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"
|
|
' _
|
|
|
|
- name: Verify and stage signed PowerShell installer
|
|
if: matrix.build-system == 'cargo' && matrix.target == 'x86_64-pc-windows-msvc'
|
|
shell: powershell
|
|
run: |
|
|
$installer = Join-Path $env:GITHUB_WORKSPACE 'scripts/install/install.ps1'
|
|
$signature = Get-AuthenticodeSignature $installer
|
|
if ($signature.Status -ne 'Valid' -or $null -eq $signature.TimeStamperCertificate) {
|
|
throw "Installer signature is invalid or missing a timestamp: $($signature.Status)"
|
|
}
|
|
# Stage after compression so the installer remains a plain script.
|
|
Copy-Item $installer 'dist/${{ matrix.target }}/install.ps1'
|
|
|
|
- name: Suffix Bazel artifact filenames
|
|
if: ${{ matrix.build-system == 'bazel' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
for artifact in "dist/${{ matrix.target }}"/*; do
|
|
name="${artifact##*/}"
|
|
stem="${name%%.*}"
|
|
mv "$artifact" "${artifact%/*}/${stem}-bazel${name#"$stem"}"
|
|
done
|
|
|
|
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: ${{ matrix.target }}${{ env.ARTIFACT_SUFFIX }}
|
|
path: |
|
|
codex-rs/dist/${{ matrix.target }}/*
|