name: rust-release-windows on: workflow_call: inputs: release-lto: required: true type: string secrets: AZURE_TRUSTED_SIGNING_CLIENT_ID: required: true AZURE_TRUSTED_SIGNING_TENANT_ID: required: true AZURE_TRUSTED_SIGNING_SUBSCRIPTION_ID: required: true AZURE_TRUSTED_SIGNING_ENDPOINT: required: true AZURE_TRUSTED_SIGNING_ACCOUNT_NAME: required: true AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE_NAME: required: true jobs: build-windows-binaries: name: Build Windows binaries - ${{ matrix.runner }} - ${{ matrix.target }} - ${{ matrix.bundle }} runs-on: ${{ matrix.runs_on }} timeout-minutes: 60 permissions: contents: read defaults: run: working-directory: codex-rs env: CARGO_PROFILE_RELEASE_LTO: ${{ inputs.release-lto }} strategy: fail-fast: false matrix: include: - runner: windows-x64 target: x86_64-pc-windows-msvc bundle: primary build_args: --bin codex --bin codex-responses-api-proxy runs_on: group: codex-runners labels: codex-windows-x64 - runner: windows-arm64 target: aarch64-pc-windows-msvc bundle: primary build_args: --bin codex --bin codex-responses-api-proxy runs_on: group: codex-runners labels: codex-windows-arm64 - runner: windows-x64 target: x86_64-pc-windows-msvc bundle: helpers build_args: --bin codex-windows-sandbox-setup --bin codex-command-runner runs_on: group: codex-runners labels: codex-windows-x64 - runner: windows-arm64 target: aarch64-pc-windows-msvc bundle: helpers build_args: --bin codex-windows-sandbox-setup --bin codex-command-runner runs_on: group: codex-runners labels: codex-windows-arm64 steps: - uses: actions/checkout@v6 - 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@1.93.0 with: targets: ${{ matrix.target }} - name: Cargo build (Windows binaries) shell: bash run: | cargo build --target ${{ matrix.target }} --release --timings ${{ matrix.build_args }} - name: Upload Cargo timings uses: actions/upload-artifact@v6 with: name: cargo-timings-rust-release-windows-${{ matrix.target }}-${{ matrix.bundle }} path: codex-rs/target/**/cargo-timings/cargo-timing.html if-no-files-found: warn - name: Stage Windows binaries shell: bash run: | output_dir="target/${{ matrix.target }}/release/staged-${{ matrix.bundle }}" mkdir -p "$output_dir" if [[ "${{ matrix.bundle }}" == "primary" ]]; then cp target/${{ matrix.target }}/release/codex.exe "$output_dir/codex.exe" cp target/${{ matrix.target }}/release/codex-responses-api-proxy.exe "$output_dir/codex-responses-api-proxy.exe" else cp target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe "$output_dir/codex-windows-sandbox-setup.exe" cp target/${{ matrix.target }}/release/codex-command-runner.exe "$output_dir/codex-command-runner.exe" fi - name: Upload Windows binaries uses: actions/upload-artifact@v6 with: name: windows-binaries-${{ matrix.target }}-${{ matrix.bundle }} path: | codex-rs/target/${{ matrix.target }}/release/staged-${{ matrix.bundle }}/* build-windows: needs: - build-windows-binaries name: Build - ${{ matrix.runner }} - ${{ matrix.target }} runs-on: ${{ matrix.runs_on }} timeout-minutes: 60 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: codex-runners labels: codex-windows-x64 - runner: windows-arm64 target: aarch64-pc-windows-msvc runs_on: group: codex-runners labels: codex-windows-arm64 steps: - uses: actions/checkout@v6 - name: Download prebuilt Windows primary binaries uses: actions/download-artifact@v7 with: name: windows-binaries-${{ matrix.target }}-primary path: codex-rs/target/${{ matrix.target }}/release - name: Download prebuilt Windows helper binaries uses: actions/download-artifact@v7 with: name: windows-binaries-${{ matrix.target }}-helpers path: codex-rs/target/${{ matrix.target }}/release - name: Verify binaries shell: bash run: | set -euo pipefail ls -lh target/${{ matrix.target }}/release/codex.exe ls -lh target/${{ matrix.target }}/release/codex-responses-api-proxy.exe ls -lh target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe ls -lh target/${{ matrix.target }}/release/codex-command-runner.exe - name: Sign Windows binaries with Azure Trusted Signing uses: ./.github/actions/windows-code-sign with: target: ${{ matrix.target }} client-id: ${{ secrets.AZURE_TRUSTED_SIGNING_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TRUSTED_SIGNING_TENANT_ID }} subscription-id: ${{ secrets.AZURE_TRUSTED_SIGNING_SUBSCRIPTION_ID }} endpoint: ${{ secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }} account-name: ${{ secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }} certificate-profile-name: ${{ secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE_NAME }} - name: Stage artifacts shell: bash run: | dest="dist/${{ matrix.target }}" mkdir -p "$dest" cp target/${{ matrix.target }}/release/codex.exe "$dest/codex-${{ matrix.target }}.exe" cp target/${{ matrix.target }}/release/codex-responses-api-proxy.exe "$dest/codex-responses-api-proxy-${{ matrix.target }}.exe" cp target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe "$dest/codex-windows-sandbox-setup-${{ matrix.target }}.exe" cp target/${{ matrix.target }}/release/codex-command-runner.exe "$dest/codex-command-runner-${{ matrix.target }}.exe" - name: Install DotSlash uses: facebook/install-dotslash@v2 - name: Compress artifacts shell: bash run: | # Path that contains the uncompressed binaries for the current # ${{ matrix.target }} dest="dist/${{ matrix.target }}" repo_root=$PWD # 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-.zst # codex-.tar.gz # codex-.zip for f in "$dest"/*; do base="$(basename "$f")" # Skip files that are already archives (shouldn't happen, but be # safe). if [[ "$base" == *.tar.gz || "$base" == *.zip || "$base" == *.dmg ]]; then continue fi # Don't try to compress signature bundles. if [[ "$base" == *.sigstore ]]; then continue 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 won't embed the # directory path inside the zip. if [[ "$base" == "codex-${{ matrix.target }}.exe" ]]; then # Bundle the sandbox helper binaries into the main codex zip so # WinGet installs include the required helpers next to codex.exe. # Fall back to the single-binary zip if the helpers are missing # to avoid breaking releases. bundle_dir="$(mktemp -d)" runner_src="$dest/codex-command-runner-${{ matrix.target }}.exe" setup_src="$dest/codex-windows-sandbox-setup-${{ matrix.target }}.exe" if [[ -f "$runner_src" && -f "$setup_src" ]]; then cp "$dest/$base" "$bundle_dir/$base" cp "$runner_src" "$bundle_dir/codex-command-runner.exe" cp "$setup_src" "$bundle_dir/codex-windows-sandbox-setup.exe" # Use an absolute path so bundle zips land in the real dist # dir even when 7z runs from a temp directory. (cd "$bundle_dir" && 7z a "$repo_root/$dest/${base}.zip" .) else echo "warning: missing sandbox binaries; falling back to single-binary zip" echo "warning: expected $runner_src and $setup_src" (cd "$dest" && 7z a "${base}.zip" "$base") fi 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" done - uses: actions/upload-artifact@v6 with: name: ${{ matrix.target }} path: | codex-rs/dist/${{ matrix.target }}/*