39 Commits

  • [codex] package Windows ARM64 on x64 (#28001)
    The first release after parallelizing Windows packaging moved the
    critical path to the ARM64 packaging job:
    
    https://github.com/openai/codex/actions/runs/27451157324
    
    The x64 job started immediately and finished in 5m29s. The ARM64
    job waited 76s for its runner and then took 5m56s, holding the
    release for 1m43s after x64 had finished.
    
    Packaging only downloads, signs, archives, and compresses already
    built binaries. It does not execute target code. Run both packaging
    jobs on x64 runners, keeping ARM64 hardware for compilation.
  • [codex] parallelize Windows package archives (#27854)
    In the Windows x64 packaging job from
    
    https://github.com/openai/codex/actions/runs/27391514823
    
    building the primary and app-server package archives serially took 116
    seconds.
    
    Both archives read the same signed-binary directory but write separate
    package trees and output files. Run them concurrently with xargs -P2.
    
    The package helper rewrites DotSlash executables under the process temp
    directory. A naive concurrent run failed when one process tried to
    replace an executable used by the other. Give each bundle separate TMP
    and TEMP roots to keep those caches independent.
    
    On Windows x64 in
    
    https://github.com/openai/codex/actions/runs/27397197944
    
    three serial trials took 127, 128, and 126 seconds. Concurrent trials
    took 76, 74, and 74 seconds, saving 52 to 54 seconds. This removes about
    50 seconds from the release critical path without changing the packaging
    commands or output set.
  • [codex] package Windows symbols in parallel (#27856)
    In the x64 packaging job from
    
    https://github.com/openai/codex/actions/runs/27391514823
    
    archiving and uploading PDBs took 65 seconds after signing. Release
    packaging could not start until that work completed.
    
    Windows code signing changes executables but not their PDBs. Package
    the PDBs in a sibling Ubuntu job as soon as all binary artifacts are
    available. Signing and release packaging can then proceed without
    waiting for the symbols archive, reducing the critical path by about
    one minute.
  • [codex] parallelize Windows compression (#27855)
    Each Windows packaging job creates three compressed forms of five
    binaries in sequence. This takes roughly two minutes and is on the
    release critical path.
    
    Use two xargs workers to compress independent binaries concurrently.
    The workers only read the raw executables and write per-binary archive
    names. The Codex zip can safely read the helper executables while their
    own archives are generated.
    
    On a 16-vCPU AMD EPYC 9V74 Windows x64 release runner, alternating
    trials against artifacts from release run 27391514823 measured:
    
      serial:   121 s, 123 s, 121 s
      parallel:  73 s,  73 s,  74 s
    
    This saves 47 to 50 seconds in the x64 packaging lane, reducing the
    observed release critical path by about 48 seconds when x64 remains the
    limiting lane.
    
    https://github.com/openai/codex/actions/runs/27401905938
  • [codex] link Windows releases with LLD (#27315)
    Windows x64 release builds spend about 36.5 of 48 minutes in final
    LLVM code generation and MSVC linking. Use the existing target-aware
    MSVC
    setup action to select LLD for release builds; the Windows ARM64 archive
    path already exercises the action and its LLD wrapper.
    
    In https://github.com/openai/codex/actions/runs/27242495616, macOS
    becomes
    the critical path after roughly four minutes of Windows improvement, so
    this is expected to reduce total workflow time by about four minutes.
  • ci: template custom runner names by repo (#27024)
    ## Why
    
    These workflows currently hard-code the `codex` runner group and custom
    runner labels. That makes the same workflow definitions less portable
    across repository copies or renamed repos, even though the runner fleet
    follows the repository name scheme. Template the runner identities from
    the repository name so `openai/codex` still resolves to the existing
    `codex-*` runners while other repos can use their own `<repo>-*` runner
    names.
    
    ## What Changed
    
    - Replaced custom runner `group` values such as `codex-runners` with
    `${{ github.event.repository.name }}-runners`.
    - Replaced custom runner labels such as `codex-linux-x64` and
    `codex-windows-arm64` with `${{ github.event.repository.name }}-...`.
    - Covered direct `runs-on` objects, matrix `runs_on` entries, reusable
    workflow runner inputs, and release runner labels.
    
    ## Verification
    
    - Parsed all `.github/workflows/*.yml` files as YAML with Ruby.
    - Searched `.github/workflows` to confirm no hardcoded runner-field
    `codex-runners` or `codex-*` labels remain.
  • [codex] Restore release symbol artifacts with line tables (#26202)
    ## Summary
    
    - Restore separate release symbol archives for macOS, Linux, and Windows
    binaries.
    - Build release binaries with `line-tables-only` debuginfo instead of
    full debuginfo.
    - Strip Unix distribution binaries after extracting symbols, preserve
    Windows PDBs, and keep symbol archives available to the release job.
    - Strip the packaged Linux `bwrap` binary before hashing it so the
    embedded digest matches the distributed bytes.
    
    ## Root cause
    
    The first symbol-artifact implementation enabled
    `CARGO_PROFILE_RELEASE_DEBUG=full`. In the June 2 release runs, macOS
    ARM primary builds reached the 90-minute timeout while still inside
    `Cargo build`. After the symbol changes were reverted, the same primary
    build completed in about 22 minutes. The archive step itself completed
    in tens of seconds when reached.
    
    Rust's `line-tables-only` debuginfo level preserves function names and
    source locations for symbolication without emitting the heavier variable
    and type information from full debuginfo.
    
    ## Validation
    
    - Ran `just fmt` from `codex-rs`.
    - Ran `just test-github-scripts` from the repository root: 23 tests
    passed.
    - Ran `bash -n` and `shellcheck` on
    `.github/scripts/archive-release-symbols-and-strip-binaries.sh`.
    - Parsed both modified workflows as YAML and ran `git diff --check`.
    - Built a macOS release smoke binary with `line-tables-only`, archived
    its dSYM through the restored script, stripped the production binary,
    and verified that `atos` resolves `symbol_smoke_function` to
    `main.rs:2`.
    - Ran Linux archive-script control-flow coverage with stubbed `objcopy`
    and `strip` commands.
    - Ran Windows PDB archive staging coverage and verified
    underscore-emitted Rust PDB names are staged under shipped hyphenated
    binary names.
    
    ## Follow-up
    
    The release workflow only runs for tags or manual dispatches, so CI
    cannot dry-run the full release matrix on this PR. The next release run
    will verify runner time and memory behavior under `line-tables-only`.
  • build: use ThinLTO for release binaries (#23710)
    ## Why
    
    Fat LTO makes release builds substantially slower without providing
    enough measured runtime benefit to justify the release CI long pole. The
    build-profile investigation found that keeping Cargo's default release
    `opt-level=3` and switching from fat LTO to ThinLTO (`3/thin/1`) reduced
    a clean `codex-cli` release build from 2073.893 seconds to 1243.172
    seconds, a 40.06% improvement.
    
    The resulting binary increased from 196.7 MiB to 211.8 MiB (+7.63%).
    Measured runtime changes were small: the worst image workload median was
    +0.86% and app-server startup was +0.31% relative to fat LTO. ThinLTO
    retains cross-crate optimization while avoiding most of the fat-LTO
    build cost.
    
    This deliberately avoids global size optimization: final-executable
    testing showed a substantial regression on the image request path, which
    is expected to become more important as image usage grows.
    
    ## What changed
    
    - Set the workspace release profile to `lto = "thin"`, retaining Cargo's
    default release `opt-level=3`.
    - Remove release and CI workflow-specific LTO overrides so
    release-profile builds consistently use the workspace setting.
    - Remove the now-unused Windows release workflow input and related
    diagnostic output.
    
    ## Validation
    
    - Confirmed the release profile parses with `cargo metadata --no-deps
    --format-version 1`.
    - CI validates release builds across the supported target matrix.
  • Use Azure artifact signing environment secrets (#25945)
    ## Why
    Windows release signing should read Azure signing credentials from the
    `azure-artifact-signing` environment instead of the old repo-level
    `AZURE_TRUSTED_SIGNING_*` names. The smoke runs confirmed the
    environment secrets resolve with the new `AZURE_ARTIFACT_SIGNING_*`
    names once the Windows signing job is attached to that environment.
    
    ## What Changed
    - Put the real Windows signing job in the `azure-artifact-signing`
    environment.
    - Switch the Windows signing action inputs from
    `AZURE_TRUSTED_SIGNING_*` to `AZURE_ARTIFACT_SIGNING_*`.
    - Drop the obsolete `workflow_call.secrets` declarations for the old
    repo-level secret names; the caller continues to use `secrets: inherit`.
    - Remove the temporary branch-trigger and Windows-only smoke-test
    workflow changes before finalizing this PR.
    
    ## Validation
    - `git diff --check -- .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
    - `ruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f); puts
    "yaml ok: #{f}" }' .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
  • Use environment secrets for Azure signing (#24859)
    ## Summary
    - Move Azure Trusted Signing values out of reusable workflow-call
    secrets and into the `azure-artifact-signing` environment scope
    - Attach the Windows signing job to the `azure-artifact-signing`
    environment so it can resolve the signing secrets directly
    - Stop inheriting caller secrets for the Windows release reusable
    workflow
    
    ## Validation
    - `git diff --check -- .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
    - `ruby -e 'require "yaml"; ARGV.each { |path| YAML.load_file(path);
    puts "ok #{path}" }' .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
  • Fix Windows release PDB staging (#25916)
    ## Summary
    - Teach the Windows release prebuild staging step to locate Rust/MSVC
    PDBs emitted with crate-style underscore names.
    - Stage PDBs under the shipped hyphenated binary names so the downstream
    symbol archive step keeps the same artifact contract.
    - Keep a fallback for already-hyphenated PDB names and fail with a clear
    diagnostic if neither form exists.
    
    ## Root cause
    The recent symbol publishing change in #25649 started copying
    `${binary}.pdb` from `target/<triple>/release` during Windows prebuild
    staging. Cargo still emits the `.exe` with the hyphenated binary name,
    but MSVC PDBs for hyphenated Rust crates are emitted with underscores,
    for example `codex_app_server.pdb` for `codex-app-server.exe`. The
    release workflow was still building into the expected directory; the new
    PDB copy step was looking for the wrong filename.
    
    ## Impact
    This unblocks the `rust-release` Windows prebuilt-binary jobs for
    hyphenated binaries while preserving the hyphenated PDB names consumed
    by the final Windows release packaging and symbol archive steps.
    
    ## Validation
    - `just fmt` from `codex-rs`
    - `git diff --check -- .github/workflows/rust-release-windows.yml`
    - Parsed `.github/workflows/rust-release-windows.yml` as YAML locally
    - Local bash staging sanity test for both underscore-emitted and
    hyphenated PDB filenames
  • [codex] Use git CLI for Cargo fetches across Rust workflows (#25775)
    ## Why
    Cargo's libgit2 transport has intermittently failed while fetching git
    dependencies with nested submodules.
    [#25644](https://github.com/openai/codex/pull/25644) applied
    `CARGO_NET_GIT_FETCH_WITH_CLI=true` to the main Rust release build after
    macOS SecureTransport/libgit2 failures while cloning `libwebrtc`'s
    nested `libyuv` submodule. Similar flakes can affect other Cargo-bearing
    Rust jobs.
    
    ## What changed
    Configure `CARGO_NET_GIT_FETCH_WITH_CLI=true` at workflow scope for the
    remaining Cargo-bearing Rust workflows:
    
    - fast Rust CI and `cargo-deny`
    - reusable Windows and argument-comment-lint release workflows
    - `rusty-v8-release` and `v8-canary` Cargo builds and smoke tests
    
    The full Rust CI, reusable nextest workflow, and primary Rust release
    build already had the override. Bazel-only workflows are unchanged
    because they use a different dependency fetch path.
    
    ## Validation
    - Parsed all `.github/workflows/*.yml` files as YAML.
    - Scanned Cargo-bearing workflows to confirm they configure
    `CARGO_NET_GIT_FETCH_WITH_CLI`.
  • [codex] Publish release symbol artifacts (#25649)
    ## Why
    
    Production Codex binaries are stripped for distribution, which leaves
    crashes and samples from released builds without the symbols needed for
    useful stack traces. Publish symbols as separate release assets so
    production artifacts stay small while released builds remain
    symbolicateable.
    
    ## What changed
    
    - Add `.github/scripts/archive-release-symbols-and-strip-binaries.sh` to
    package platform-native symbols into `codex-symbols-<artifact>.tar.gz`
    assets while stripping the corresponding Unix binaries before signing.
    - Build release binaries with full debug information before producing
    distribution artifacts.
    - Publish macOS `.dSYM` bundles, Linux `.debug` files with
    `.gnu_debuglink`, and Windows `.pdb` files.
    - Strip Linux `bwrap` before computing its packaged-resource digest, but
    intentionally omit `bwrap` from symbol archives.
    - Preserve symbols artifacts in the unsigned macOS promotion flow.
    
    ## Verification
    
    - Ran `shellcheck` and `bash -n` on
    `.github/scripts/archive-release-symbols-and-strip-binaries.sh`.
    - Parsed the modified workflow YAML files and ran `git diff --check`.
    - Built a macOS release smoke binary and verified that the archived
    `.dSYM` contains DWARF application source information and has the same
    UUID as the stripped production binary.
    - Built Linux smoke binaries and verified that the symbol archive
    contains `codex.debug`, excludes `bwrap.debug`, leaves the expected
    `.gnu_debuglink` in `codex`, and does not mutate the separately stripped
    `bwrap` digest.
    - Staged a Windows smoke archive and verified that it contains the
    expected `.pdb` file.
  • Disable SQLite intrinsics for Windows x64 releases (#25490)
    ## Why
    
    Codex 0.135.0 started shipping bundled SQLite 3.51.x via SQLx 0.9.0 to
    avoid the older WAL corruption bug fixed by #24728. On Windows x64,
    #25367 reports an immediate `STATUS_ILLEGAL_INSTRUCTION` crash on a
    Haswell CPU when starting normal Codex paths.
    
    Rather than downgrading SQLite, this keeps the newer bundled SQLite
    source and removes SQLite compiler-intrinsic code paths from the Windows
    x64 release build.
    
    ## What changed
    
    For `x86_64-pc-windows-msvc` release builds, export
    `LIBSQLITE3_FLAGS=SQLITE_DISABLE_INTRINSIC` before `cargo build` in:
    
    - `.github/workflows/rust-release.yml`
    - `.github/workflows/rust-release-windows.yml`
    
    Other targets keep their current SQLite build flags.
    
    ## Verification
    
    - `git diff --check`
  • Uprev Rust toolchain pins to 1.95.0 (#24684)
    ## Summary
    - Bump the workspace Rust toolchain from `1.93.0` to `1.95.0` across
    Cargo, Bazel, CI, release workflows, devcontainers, and the Codex
    environment config.
    - Refresh `MODULE.bazel.lock` so the Bazel Rust toolchain artifacts
    match the new version.
    - Leave purpose-specific toolchains unchanged, including the
    `argument-comment-lint` nightly and the upstream `rusty_v8` `1.91.0`
    build pin.
    - Includes fixes for new lints from `just fix` and a few codex-authored
    fixes for lints without a suggestion.
  • sdk: launch packaged Codex runtimes (#23786)
    ## Why
    
    The Python and TypeScript SDKs launch the native Codex runtime directly,
    so they need to consume the same package artifact shape that release
    jobs now produce. The runtime wheel should be built from the canonical
    Codex package archive rather than reconstructing a parallel layout from
    loose binaries.
    
    ## What Changed
    
    - Stage `openai-codex-cli-bin` by extracting
    `codex-package-<target>.tar.gz` into `src/codex_cli_bin` and validating
    the expected package layout.
    - Update release workflows to pass the generated package archive into
    `stage-runtime` instead of the temporary package directory.
    - Update Python runtime setup to download `codex-package-*.tar.gz`
    release assets directly.
    - Expose Python runtime helpers for the bundled package directory and
    `codex-path`, and prepend that path when `openai_codex` launches the
    installed runtime without duplicating Windows `Path`/`PATH` keys.
    - Teach the TypeScript SDK to resolve package-layout optional
    dependencies while keeping the existing npm fallback layout, and
    preserve the existing Windows path variable casing when prepending
    `codex-path`.
    
    ## Test Plan
    
    - `python3 -m py_compile sdk/python/scripts/update_sdk_artifacts.py
    sdk/python/_runtime_setup.py sdk/python/src/openai_codex/client.py
    sdk/python-runtime/src/codex_cli_bin/__init__.py`
    - `uv run --frozen --project sdk/python --extra dev ruff check
    sdk/python/scripts/update_sdk_artifacts.py sdk/python/_runtime_setup.py
    sdk/python/src/openai_codex/client.py
    sdk/python/tests/test_artifact_workflow_and_binaries.py
    sdk/python-runtime/src/codex_cli_bin/__init__.py`
    - `uv run --frozen --project sdk/python --extra dev pytest
    sdk/python/tests/test_artifact_workflow_and_binaries.py`
    - `pnpm eslint src/exec.ts tests/exec.test.ts`
    - `pnpm test --runInBand tests/exec.test.ts`
  • dotslash: publish Codex entrypoints from package archives (#23638)
    ## Summary
    
    DotSlash should resolve the same canonical package archives used by
    standalone installers and npm platform packages, rather than continuing
    to point at single-binary zstd artifacts or the older Linux bundle
    archive.
    
    This updates the Codex CLI and `codex-app-server` DotSlash release
    config entries to match `codex-package-<target>.tar.gz` and
    `codex-app-server-package-<target>.tar.gz`, with paths that select
    `bin/codex` or `bin/codex-app-server` inside the extracted package. The
    other helper outputs stay on their existing per-binary artifacts for
    now.
    
    ## Test plan
    
    - `python3 -m json.tool .github/dotslash-config.json > /dev/null`
    - Ran a Python regex smoke test that checked every updated `codex` and
    `codex-app-server` platform entry against the archive names emitted by
    `.github/scripts/build-codex-package-archive.sh`.
  • ci: build Codex package archives in release workflow (#23582)
    ## Why
    
    Release CI already builds the Codex entrypoints before staging
    artifacts, and the package builder can now package those prebuilt
    binaries directly. The workflow should produce package-shaped sidecar
    archives from the same staged entrypoints that downstream distribution
    channels will eventually consume, without rebuilding `codex` or
    `codex-app-server` inside the packaging step.
    
    This intentionally does **not** publish the new package archives as
    GitHub Release assets yet. The archives are kept with workflow artifacts
    until npm, Homebrew, `install.sh`, winget, and related consumers are
    ready to switch over.
    
    ## What changed
    
    - Adds a `Build Codex package archive` step to
    `.github/workflows/rust-release.yml` after target artifacts are staged.
    - Runs `scripts/build_codex_package.py` for both release bundles:
    - `primary` builds `codex-package-${TARGET}.tar.gz` with `--variant
    codex`.
    - `app-server` builds `codex-app-server-package-${TARGET}.tar.gz` with
    `--variant codex-app-server`.
    - Passes `--entrypoint-bin target/${TARGET}/release/<entrypoint>` so
    packages contain the entrypoint already built by the workflow.
    - Deletes both package archive names before the final GitHub Release
    upload so they remain workflow artifacts only for now.
    
    ## Verification
    
    - Parsed `.github/workflows/rust-release.yml` with Ruby's YAML loader.
    
    
    
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23582).
    * #23596
    * __->__ #23582
  • [1/8] Pin Python SDK runtime dependency (#21891)
    ## Why
    
    The Python SDK depends on the app-server runtime package for the bundled
    `codex` binary and schema source of truth. That relationship should be
    explicit in package metadata instead of inferred from matching version
    numbers, so installers, lockfiles, and reviewers can see exactly which
    runtime the SDK expects.
    
    ## What
    
    - Declare `openai-codex-cli-bin==0.131.0a4` as a Python SDK dependency.
    - Update runtime setup helpers to resolve the runtime version from the
    declared dependency pin.
    - Refresh the SDK lockfile for the pinned runtime wheel.
    - Update package/runtime tests and docs that describe where the runtime
    version comes from.
    
    ## Stack
    
    1. This PR `[1/8]` Pin Python SDK runtime dependency
    2. #21893 `[2/8]` Generate Python SDK types from pinned runtime
    3. #21895 `[3/8]` Run Python SDK tests in CI
    4. #21896 `[4/8]` Define Python SDK public API surface
    5. #21905 `[5/8]` Rename Python SDK package to `openai-codex`
    6. #21910 `[6/8]` Add high-level Python SDK approval mode
    7. #22014 `[7/8]` Add Python SDK app-server integration harness
    8. #22021 `[8/8]` Add Python SDK Ruff formatting
    
    ## Verification
    
    - Added coverage for the SDK runtime dependency pin and runtime
    distribution naming.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Publish Python runtime wheels on release (#21784)
    ## Why
    
    Published Python SDK builds depend on an exact `openai-codex-cli-bin`
    runtime package, but the release workflow did not publish that runtime
    package to PyPI. That left the SDK packaging story incomplete: release
    artifacts could produce Codex binaries, but Python users still needed a
    matching wheel carrying the platform-specific runtime and helper
    executables.
    
    This PR is stacked on #21787 so release jobs can include helper binaries
    in runtime wheels: Linux wheels include `bwrap` for sandbox fallback,
    and Windows wheels include the signed sandbox/elevation helpers beside
    `codex.exe`.
    
    ## What changed
    
    - Builds platform-specific `openai-codex-cli-bin` wheels from signed
    release binaries on macOS, Linux, and Windows release runners.
    - Packages Linux `bwrap` into musllinux runtime wheels.
    - Packages Windows sandbox helper executables into Windows runtime
    wheels.
    - Uploads runtime wheels as GitHub release assets and publishes them to
    PyPI using trusted publishing from the `pypi` GitHub environment.
    - Keeps the new Python runtime publish job non-blocking so failures need
    follow-up but do not fail the Rust release workflow.
    - Pins the PyPA publish action to the `v1.13.0` commit SHA for
    reproducible release publishing.
    - Documents that runtime wheels are platform wheels published through
    PyPI trusted publishing.
    
    ## Testing
    
    - `ruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f); puts "ok
    #{f}" }' .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
    - `git diff --check`
    
    CI is the real end-to-end verification for the release workflow path.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • [codex] Address some more GHA hygiene issues (#21622)
    This does two things:
    
    - We use `persist-credentials: false` everywhere now. This is
    unfortunately not the default in GitHub Actions, but it prevents
    `actions/checkout` from dropping `secrets.GITHUB_TOKEN` onto disk.
    - We interpose (some) template expansions through environment variables.
    I've limited this to contexts that have non-fixed values; contexts that
    are fixed (like `*.result`) are not dangerous to expand directly inline
    (but maybe we should clean those up in the future for consistency
    anyways).
    
    This is a medium-risk change in terms of CI breakage: I did a scan for
    usage of `git push` and other commands that implicitly use the persisted
    credential, but couldn't find any. Even still, some implicit usages of
    the persisted credentials may be lurking. Please ping ww@ if any issues
    arise.
  • Use --locked in cargo build and lint invocations (#21602)
    This ensures CI fails if the committed lockfile is outdated
  • [codex] Fully qualify hash-pins in GitHub Actions (#21436)
    This builds on top of https://github.com/openai/codex/pull/15828 by
    ensuring that hash-pinned actions with version comments are fully
    qualified, rather than referencing floating/mutable comments like "v7".
    This makes actions management tools behave more consistently.
    
    This shouldn't break anything, since it's comment only. But if it does,
    ping ww@ 🙂
  • ci: increase Windows release workflow timeouts (#20343)
    ## Why
    
    #20271 increased the `90`-minute timeout in `rust-release.yml`, but it
    did not update the reusable Windows workflow in
    `rust-release-windows.yml`. As a result, the Windows release compile
    jobs were still capped at `60` minutes and the `windows-x64` primary
    build could continue timing out.
    
    We are keeping the existing `90`-minute timeout in `rust-release.yml`.
    That increase was still directionally correct because the top-level
    release build benefits from extra headroom; the mistake was assuming it
    also covered the reusable Windows jobs.
    
    ## What Changed
    - increase the reusable Windows release workflow timeouts in
    `rust-release-windows.yml` from `60` minutes to `90` minutes
    - update the comment in `rust-release.yml` so it no longer implies that
    the top-level timeout covers the Windows reusable jobs
  • ci: publish codex-app-server release artifacts (#19447)
    ## Why
    The VS Code extension and desktop app do not need the full TUI binary,
    and `codex-app-server` is materially smaller than standalone `codex`. We
    still want to publish it as an official release artifact, but building
    it by tacking another `--bin` onto the existing release `cargo build`
    invocations would lengthen those jobs.
    
    This change keeps `codex-app-server` on its own release bundle so it can
    build in parallel with the existing `codex` and helper bundles.
    
    ## What changed
    - Made `.github/workflows/rust-release.yml` bundle-aware so each macOS
    and Linux MUSL target now builds either the existing `primary` bundle
    (`codex` and `codex-responses-api-proxy`) or a standalone `app-server`
    bundle (`codex-app-server`).
    - Preserved the historical artifact names for the primary macOS/Linux
    bundles so `scripts/stage_npm_packages.py` and
    `codex-cli/scripts/install_native_deps.py` continue to find release
    assets under the paths they already expect, while giving the new
    app-server artifacts distinct names.
    - Added a matching `app-server` bundle to
    `.github/workflows/rust-release-windows.yml`, and updated the final
    Windows packaging job to download, sign, stage, and archive
    `codex-app-server.exe` alongside the existing release binaries.
    - Generalized the shared signing actions in
    `.github/actions/linux-code-sign/action.yml`,
    `.github/actions/macos-code-sign/action.yml`, and
    `.github/actions/windows-code-sign/action.yml` so each workflow row
    declares its binaries once and reuses that list for build, signing, and
    staging.
    - Added `codex-app-server` to `.github/dotslash-config.json` so releases
    also publish a generated DotSlash manifest for the standalone app-server
    binary.
    - Kept the macOS DMG focused on the existing `primary` bundle;
    `codex-app-server` ships as the regular standalone archives and DotSlash
    manifest.
    
    ## Verification
    - Parsed the modified workflow and action YAML files locally with
    `python3` + `yaml.safe_load(...)`.
    - Parsed `.github/dotslash-config.json` locally with `python3` +
    `json.loads(...)`.
    - Reviewed the resulting release matrices, artifact names, and packaging
    paths to confirm that `codex-app-server` is built separately on macOS,
    Linux MUSL, and Windows, while the existing npm staging and Windows
    `codex` zip bundling contracts remain intact.
  • [codex] Pin GitHub Actions workflow references (#15828)
    Pin floating external GitHub Actions workflow refs to immutable SHAs.
    
    Why are we doing this? Please see the rationale doc:
    https://docs.google.com/document/d/1qOURCNx2zszQ0uWx7Fj5ERu4jpiYjxLVWBWgKa2wTsA/edit?tab=t.0
    
    Did this break you? Please roll back and let hintz@ know
  • chore(deps): bump actions/upload-artifact from 6 to 7 (#13207)
    Bumps
    [actions/upload-artifact](https://github.com/actions/upload-artifact)
    from 6 to 7.
    <details>
    <summary>Release notes</summary>
    <p><em>Sourced from <a
    href="https://github.com/actions/upload-artifact/releases">actions/upload-artifact's
    releases</a>.</em></p>
    <blockquote>
    <h2>v7.0.0</h2>
    <h2>v7 What's new</h2>
    <h3>Direct Uploads</h3>
    <p>Adds support for uploading single files directly (unzipped). Callers
    can set the new <code>archive</code> parameter to <code>false</code> to
    skip zipping the file during upload. Right now, we only support single
    files. The action will fail if the glob passed resolves to multiple
    files. The <code>name</code> parameter is also ignored with this
    setting. Instead, the name of the artifact will be the name of the
    uploaded file.</p>
    <h3>ESM</h3>
    <p>To support new versions of the <code>@actions/*</code> packages,
    we've upgraded the package to ESM.</p>
    <h2>What's Changed</h2>
    <ul>
    <li>Add proxy integration test by <a
    href="https://github.com/Link"><code>@​Link</code></a>- in <a
    href="https://redirect.github.com/actions/upload-artifact/pull/754">actions/upload-artifact#754</a></li>
    <li>Upgrade the module to ESM and bump dependencies by <a
    href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
    <a
    href="https://redirect.github.com/actions/upload-artifact/pull/762">actions/upload-artifact#762</a></li>
    <li>Support direct file uploads by <a
    href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
    <a
    href="https://redirect.github.com/actions/upload-artifact/pull/764">actions/upload-artifact#764</a></li>
    </ul>
    <h2>New Contributors</h2>
    <ul>
    <li><a href="https://github.com/Link"><code>@​Link</code></a>- made
    their first contribution in <a
    href="https://redirect.github.com/actions/upload-artifact/pull/754">actions/upload-artifact#754</a></li>
    </ul>
    <p><strong>Full Changelog</strong>: <a
    href="https://github.com/actions/upload-artifact/compare/v6...v7.0.0">https://github.com/actions/upload-artifact/compare/v6...v7.0.0</a></p>
    </blockquote>
    </details>
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="https://github.com/actions/upload-artifact/commit/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f"><code>bbbca2d</code></a>
    Support direct file uploads (<a
    href="https://redirect.github.com/actions/upload-artifact/issues/764">#764</a>)</li>
    <li><a
    href="https://github.com/actions/upload-artifact/commit/589182c5a4cec8920b8c1bce3e2fab1c97a02296"><code>589182c</code></a>
    Upgrade the module to ESM and bump dependencies (<a
    href="https://redirect.github.com/actions/upload-artifact/issues/762">#762</a>)</li>
    <li><a
    href="https://github.com/actions/upload-artifact/commit/47309c993abb98030a35d55ef7ff34b7fa1074b5"><code>47309c9</code></a>
    Merge pull request <a
    href="https://redirect.github.com/actions/upload-artifact/issues/754">#754</a>
    from actions/Link-/add-proxy-integration-tests</li>
    <li><a
    href="https://github.com/actions/upload-artifact/commit/02a8460834e70dab0ce194c64360c59dc1475ef0"><code>02a8460</code></a>
    Add proxy integration test</li>
    <li>See full diff in <a
    href="https://github.com/actions/upload-artifact/compare/v6...v7">compare
    view</a></li>
    </ul>
    </details>
    <br />
    
    
    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=6&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
    
    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.
    
    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)
    
    ---
    
    <details>
    <summary>Dependabot commands and options</summary>
    <br />
    
    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)
    
    
    </details>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Eric Traut <etraut@openai.com>
  • chore(deps): bump actions/download-artifact from 7 to 8 (#13208)
    Bumps
    [actions/download-artifact](https://github.com/actions/download-artifact)
    from 7 to 8.
    <details>
    <summary>Release notes</summary>
    <p><em>Sourced from <a
    href="https://github.com/actions/download-artifact/releases">actions/download-artifact's
    releases</a>.</em></p>
    <blockquote>
    <h2>v8.0.0</h2>
    <h2>v8 - What's new</h2>
    <h3>Direct downloads</h3>
    <p>To support direct uploads in <code>actions/upload-artifact</code>,
    the action will no longer attempt to unzip all downloaded files.
    Instead, the action checks the <code>Content-Type</code> header ahead of
    unzipping and skips non-zipped files. Callers wishing to download a
    zipped file as-is can also set the new <code>skip-decompress</code>
    parameter to <code>false</code>.</p>
    <h3>Enforced checks (breaking)</h3>
    <p>A previous release introduced digest checks on the download. If a
    download hash didn't match the expected hash from the server, the action
    would log a warning. Callers can now configure the behavior on mismatch
    with the <code>digest-mismatch</code> parameter. To be secure by
    default, we are now defaulting the behavior to <code>error</code> which
    will fail the workflow run.</p>
    <h3>ESM</h3>
    <p>To support new versions of the @actions/* packages, we've upgraded
    the package to ESM.</p>
    <h2>What's Changed</h2>
    <ul>
    <li>Don't attempt to un-zip non-zipped downloads by <a
    href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
    <a
    href="https://redirect.github.com/actions/download-artifact/pull/460">actions/download-artifact#460</a></li>
    <li>Add a setting to specify what to do on hash mismatch and default it
    to <code>error</code> by <a
    href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
    <a
    href="https://redirect.github.com/actions/download-artifact/pull/461">actions/download-artifact#461</a></li>
    </ul>
    <p><strong>Full Changelog</strong>: <a
    href="https://github.com/actions/download-artifact/compare/v7...v8.0.0">https://github.com/actions/download-artifact/compare/v7...v8.0.0</a></p>
    </blockquote>
    </details>
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="https://github.com/actions/download-artifact/commit/70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3"><code>70fc10c</code></a>
    Merge pull request <a
    href="https://redirect.github.com/actions/download-artifact/issues/461">#461</a>
    from actions/danwkennedy/digest-mismatch-behavior</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/f258da9a506b755b84a09a531814700b86ccfc62"><code>f258da9</code></a>
    Add change docs</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/ccc058e5fbb0bb2352213eaec3491e117cbc4a5c"><code>ccc058e</code></a>
    Fix linting issues</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/bd7976ba57ecea96e6f3df575eb922d11a12a9fd"><code>bd7976b</code></a>
    Add a setting to specify what to do on hash mismatch and default it to
    <code>error</code></li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/ac21fcf45e0aaee541c0f7030558bdad38d77d6c"><code>ac21fcf</code></a>
    Merge pull request <a
    href="https://redirect.github.com/actions/download-artifact/issues/460">#460</a>
    from actions/danwkennedy/download-no-unzip</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/15999bff51058bc7c19b50ebbba518eaef7c26c0"><code>15999bf</code></a>
    Add note about package bumps</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/974686ed5098c7f9c9289ec946b9058e496a2561"><code>974686e</code></a>
    Bump the version to <code>v8</code> and add release notes</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/fbe48b1d2756394be4cd4358ed3bc1343b330e75"><code>fbe48b1</code></a>
    Update test names to make it clearer what they do</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/96bf374a614d4360e225874c3efd6893a3f285e7"><code>96bf374</code></a>
    One more test fix</li>
    <li><a
    href="https://github.com/actions/download-artifact/commit/b8c4819ef592cbe04fd93534534b38f853864332"><code>b8c4819</code></a>
    Fix skip decompress test</li>
    <li>Additional commits viewable in <a
    href="https://github.com/actions/download-artifact/compare/v7...v8">compare
    view</a></li>
    </ul>
    </details>
    <br />
    
    
    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=7&new-version=8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
    
    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.
    
    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)
    
    ---
    
    <details>
    <summary>Dependabot commands and options</summary>
    <br />
    
    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)
    
    
    </details>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Try fixing windows pipeline (#12848)
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
  • fix(ci) lock rust toolchain at 1.93.0 to unblock (#11703)
    ## Summary
    CI is broken on main because our CI toolchain is trying to run 1.93.1
    while our rust toolchain is locked at 1.93.0. I'm sure it's likely safe
    to upgrade, but let's keep things stable for now.
    
    ## Testing
    - [x] CI should hopefully pass
  • ci: capture cargo timings in Rust CI and release workflows (#11543)
    ## Why
    We want actionable build-hotspot data from CI so we can tune Rust
    workflow performance (for example, target coverage, cache behavior, and
    job shape) based on actual compile-time bottlenecks.
    
    `cargo` timing reports are lightweight and provide a direct way to
    inspect where compilation time is spent.
    
    ## What Changed
    - Updated `.github/workflows/rust-release.yml` to run `cargo build` with
    `--timings` and upload `target/**/cargo-timings/cargo-timing.html`.
    - Updated `.github/workflows/rust-release-windows.yml` to run `cargo
    build` with `--timings` and upload
    `target/**/cargo-timings/cargo-timing.html`.
    - Updated `.github/workflows/rust-ci.yml` to:
      - run `cargo clippy` with `--timings`
      - run `cargo nextest run` with `--timings` (stable-compatible)
    - upload `target/**/cargo-timings/cargo-timing.html` artifacts for both
    the clippy and nextest jobs
    
    Artifacts are matrix-scoped via artifact names so timings can be
    compared per target/profile.
    
    ## Verification
    - Confirmed the net diff is limited to:
      - `.github/workflows/rust-ci.yml`
      - `.github/workflows/rust-release.yml`
      - `.github/workflows/rust-release-windows.yml`
    - Verified timing uploads are added immediately after the corresponding
    timed commands in each workflow.
    - Confirmed stable Cargo accepts plain `--timings` for the compile phase
    (`cargo test --no-run --timings`) and generates
    `target/cargo-timings/cargo-timing.html`.
    - Ran VS Code diagnostics on modified workflow files; no new diagnostics
    were introduced by these changes.
  • ci(windows): use DotSlash for zstd in rust-release-windows (#11542)
    ## Why
    Installing `zstd` via Chocolatey in
    `.github/workflows/rust-release-windows.yml` has been taking about a
    minute on Windows release runs. This adds avoidable latency to each
    release job.
    
    Using DotSlash removes that package-manager install step and pins the
    exact binary we use for compression.
    
    ## What Changed
    - Added `.github/workflows/zstd`, a DotSlash wrapper that fetches
    `zstd-v1.5.7-win64.zip` with pinned size and digest.
    - Updated `.github/workflows/rust-release-windows.yml` to:
      - install DotSlash via `facebook/install-dotslash@v2`
    - replace `zstd -T0 -19 ...` with
    `${GITHUB_WORKSPACE}/.github/workflows/zstd -T0 -19 ...`
    - `windows-aarch64` uses the same win64 upstream zstd artifact because
    upstream releases currently publish `win32` and `win64` binaries.
    
    ## Verification
    - Verified the workflow now resolves the DotSlash file from
    `${GITHUB_WORKSPACE}` while the job runs with `working-directory:
    codex-rs`.
    - Ran VS Code diagnostics on changed files:
      - `.github/workflows/rust-release-windows.yml`
      - `.github/workflows/zstd`
  • ci: remove actions/cache from rust release workflows (#11540)
    ## Why
    
    `rust-release` cache restore has had very low practical value, while
    cache save consistently costs significant time (usually adding ~3
    minutes to the critical path of a release workflow).
    
    From successful release-tag runs with cache steps (`289` runs total):
    - Alpha tags: cache download averaged ~5s/run, cache upload averaged
    ~230s/run.
    - Stable tags: cache download averaged ~5s/run, cache upload averaged
    ~227s/run.
    - Windows release builds specifically: download ~2s/run vs upload
    ~169-170s/run.
    
    Hard step-level signal from the same successful release-tag runs:
    - Cache restore (`Run actions/cache`): `2,314` steps, total `1,515s`
    (~0.65s/step).
    - `95.3%` of restore steps finished in `<=1s`; `99.7%` finished in
    `<=2s`; `0` steps took `>=10s`.
    - Cache save (`Post Run actions/cache`): `2,314` steps, total `66,295s`
    (~28.65s/step).
    
    Run-level framing:
    - Download total was `<=10s` in `288/289` runs (`99.7%`).
    - Upload total was `>=120s` in `285/289` runs (`98.6%`).
    
    The net effect is that release jobs are spending time uploading caches
    that are rarely useful for subsequent runs.
    
    ## What Changed
    
    - Removed the `actions/cache@v5` step from
    `.github/workflows/rust-release.yml`.
    - Removed the `actions/cache@v5` step from
    `.github/workflows/rust-release-windows.yml`.
    - Left build, signing, packaging, and publishing flow unchanged.
    
    ## Validation
    
    - Queried historical `rust-release` run/job step timing and compared
    cache download vs upload for alpha and stable release tags.
    - Spot-checked release logs and observed repeated `Cache not found ...`
    followed by `Cache saved ...` patterns.
  • feat: build windows support binaries in parallel (#11500)
    Windows release builds were compiling and linking four release binaries
    on a single runner, which slowed the release pipeline. The
    Windows-specific logic also made `rust-release.yml` harder to read and
    maintain.
    
    ## What Changed
    
    - Extracted Windows release logic into a reusable workflow at
    `.github/workflows/rust-release-windows.yml`.
    - Updated `.github/workflows/rust-release.yml` to call the reusable
    Windows workflow via `workflow_call`.
    - Parallelized Windows binary builds with one 4-entry matrix over two
    targets (`x86_64-pc-windows-msvc`, `aarch64-pc-windows-msvc`) and two
    bundles (`primary`, `helpers`).
    - Kept signing centralized per target by downloading both prebuilt
    bundles and signing all four executables together.
    - Preserved final release artifact behavior and filtered intermediate
    `windows-binaries*` artifacts out of the published release asset set.