mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
## What changed - Remove automatic BuildBuddy configuration and credential forwarding from Bazel CI, release, SDK, and voice builds. Strip remote execution CI configs in the shared wrapper while retaining explicit remote configurations for local use. - Use native Windows host tools and audio dependencies for Windows Bazel actions, forwarding the required toolchain and environment settings. - Initialize message-board MCP servers through a per-session `OnceCell` so server startup does not hold the shared registry lock across an await. - Expose the message-board test helper to the core Bazel package and update the runtime-auth test call for the `reauth` argument. GitOrigin-RevId: 5d5c1f4d71fa841090dea8eec8006380981fb65b
724 lines
32 KiB
YAML
724 lines
32 KiB
YAML
name: rust-release-windows
|
|
|
|
on:
|
|
workflow_call:
|
|
|
|
env:
|
|
WINDOWS_BINARIES: "codex codex-code-mode-host codex-exec-server 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 }}
|
|
# Release Cargo artifacts only while Bazel releases are disabled.
|
|
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 releases are disabled while the BuildBuddy key is revoked.
|
|
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-exec-server 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-exec-server 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 codex-exec-server"
|
|
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 codex-exec-server"
|
|
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
|
|
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 }}
|
|
# Use local Bazel while BuildBuddy credentials are unavailable.
|
|
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 }}
|
|
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 releases are disabled while the BuildBuddy key is revoked.
|
|
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 }}
|
|
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 releases are disabled while the BuildBuddy key is revoked.
|
|
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 executor signatures and bytes
|
|
shell: pwsh
|
|
run: |
|
|
$target = "${{ matrix.target }}"
|
|
$source = Join-Path $env:CARGO_TARGET_DIR "$target/release/codex-exec-server.exe"
|
|
foreach ($stem in @("codex-package", "codex-app-server-package")) {
|
|
$package = Join-Path $env:RUNNER_TEMP "verify-executor-$stem-$target"
|
|
New-Item -ItemType Directory -Path $package | Out-Null
|
|
tar -xzf "dist/$target/$stem-$target.tar.gz" -C $package
|
|
if ($LASTEXITCODE -ne 0) { throw "Cannot extract executor package" }
|
|
$binary = Join-Path $package "bin/codex-exec-server.exe"
|
|
if ((Get-FileHash $binary).Hash -ne (Get-FileHash $source).Hash) {
|
|
throw "Packaged executor differs from the signed input"
|
|
}
|
|
$signature = Get-AuthenticodeSignature $binary
|
|
if ($signature.Status -ne "Valid" -or $null -eq $signature.TimeStamperCertificate) {
|
|
throw "Invalid or untimestamped executor signature"
|
|
}
|
|
}
|
|
|
|
- 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: Set up Python release tools
|
|
if: ${{ matrix.build-system == 'cargo' }}
|
|
uses: ./.github/actions/setup-python-release-tools
|
|
with:
|
|
group: runtime
|
|
|
|
- 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
|
|
|
|
# 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"
|
|
uv build --offline --no-build-isolation --no-create-gitignore \
|
|
--python "${RUNNER_TEMP}/python-runtime-build-venv" --wheel --out-dir "$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 }}/*
|