From 95202ed2120c490f12f954daeb9ca8167f4e6dc8 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 3 Jun 2026 09:50:44 -0700 Subject: [PATCH 1/2] Restore release symbol artifacts with line tables --- ...hive-release-symbols-and-strip-binaries.sh | 119 ++++++++++++++++++ .github/workflows/rust-release-windows.yml | 37 +++++- .github/workflows/rust-release.yml | 43 ++++++- 3 files changed, 196 insertions(+), 3 deletions(-) create mode 100755 .github/scripts/archive-release-symbols-and-strip-binaries.sh diff --git a/.github/scripts/archive-release-symbols-and-strip-binaries.sh b/.github/scripts/archive-release-symbols-and-strip-binaries.sh new file mode 100755 index 000000000000..3e5894bb99e2 --- /dev/null +++ b/.github/scripts/archive-release-symbols-and-strip-binaries.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + cat <<'EOF' +Usage: archive-release-symbols-and-strip-binaries.sh \ + --target \ + --artifact-name \ + --release-dir \ + --archive-dir \ + --binaries "" +EOF +} + +target="" +artifact_name="" +release_dir="" +archive_dir="" +binaries="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --target) + target="${2:?--target requires a value}" + shift 2 + ;; + --artifact-name) + artifact_name="${2:?--artifact-name requires a value}" + shift 2 + ;; + --release-dir) + release_dir="${2:?--release-dir requires a value}" + shift 2 + ;; + --archive-dir) + archive_dir="${2:?--archive-dir requires a value}" + shift 2 + ;; + --binaries) + binaries="${2:?--binaries requires a value}" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unexpected argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ -z "$target" || -z "$artifact_name" || -z "$release_dir" || -z "$archive_dir" || -z "$binaries" ]]; then + usage >&2 + exit 1 +fi + +symbols_root="${RUNNER_TEMP:-/tmp}/codex-symbols-${artifact_name}" +symbols_dir="${symbols_root}/codex-symbols-${artifact_name}" +archive_path="${archive_dir%/}/codex-symbols-${artifact_name}.tar.gz" +rm -rf "$symbols_root" +mkdir -p "$symbols_dir" "$archive_dir" +read -r -a binary_names <<< "$binaries" + +case "$target" in + *apple-darwin) + for binary in "${binary_names[@]}"; do + binary_path="${release_dir%/}/${binary}" + dsym_path="${binary_path}.dSYM" + if [[ ! -f "$binary_path" ]]; then + echo "Binary $binary_path not found" >&2 + exit 1 + fi + if [[ ! -d "$dsym_path" ]]; then + echo "dSYM $dsym_path not found" >&2 + exit 1 + fi + + cp -RL "$dsym_path" "${symbols_dir}/${binary}.dSYM" + strip -S -x "$binary_path" + done + ;; + *linux*) + objcopy_bin="${OBJCOPY:-objcopy}" + strip_bin="${STRIP:-strip}" + for binary in "${binary_names[@]}"; do + binary_path="${release_dir%/}/${binary}" + debug_path="${symbols_dir}/${binary}.debug" + if [[ ! -f "$binary_path" ]]; then + echo "Binary $binary_path not found" >&2 + exit 1 + fi + + "$objcopy_bin" --only-keep-debug "$binary_path" "$debug_path" + "$strip_bin" --strip-debug --strip-unneeded "$binary_path" + "$objcopy_bin" --add-gnu-debuglink="$debug_path" "$binary_path" + done + ;; + *windows*) + for binary in "${binary_names[@]}"; do + pdb_path="${release_dir%/}/${binary}.pdb" + if [[ ! -f "$pdb_path" ]]; then + echo "PDB $pdb_path not found" >&2 + exit 1 + fi + + cp "$pdb_path" "${symbols_dir}/${binary}.pdb" + done + ;; + *) + echo "No symbols packaging support for target: $target" >&2 + exit 1 + ;; +esac + +rm -f "$archive_path" +tar -C "$symbols_root" -czf "$archive_path" "codex-symbols-${artifact_name}" diff --git a/.github/workflows/rust-release-windows.yml b/.github/workflows/rust-release-windows.yml index 89bcd33ea1fa..ec13064f6706 100644 --- a/.github/workflows/rust-release-windows.yml +++ b/.github/workflows/rust-release-windows.yml @@ -39,6 +39,10 @@ jobs: working-directory: codex-rs env: CARGO_PROFILE_RELEASE_LTO: ${{ inputs.release-lto }} + # Line tables keep release stack traces symbolicateable without the + # compile-time and memory cost of full debuginfo. + CARGO_PROFILE_RELEASE_DEBUG: line-tables-only + CARGO_PROFILE_RELEASE_STRIP: "false" strategy: fail-fast: false @@ -132,10 +136,22 @@ jobs: - name: Stage Windows binaries shell: bash run: | - output_dir="target/${{ matrix.target }}/release/staged-${{ matrix.bundle }}" + release_dir="target/${{ matrix.target }}/release" + output_dir="$release_dir/staged-${{ matrix.bundle }}" mkdir -p "$output_dir" for binary in ${{ matrix.binaries }}; do - cp "target/${{ matrix.target }}/release/${binary}.exe" "$output_dir/${binary}.exe" + 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 @@ -218,6 +234,23 @@ jobs: account-name: ${{ secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }} certificate-profile-name: ${{ secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE_NAME }} + - 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 "target/${{ matrix.target }}/release" \ + --archive-dir "symbols-dist/${{ matrix.target }}" \ + --binaries "${WINDOWS_BINARIES}" + + - name: Upload symbols archive + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: ${{ matrix.target }}-symbols + path: codex-rs/symbols-dist/${{ matrix.target }}/* + if-no-files-found: error + - name: Stage artifacts shell: bash run: | diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index 55f95fa27098..40caaafae215 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -149,6 +149,11 @@ jobs: # 2026-03-04: temporarily change releases to use thin LTO because # Ubuntu ARM is timing out at 60 minutes. CARGO_PROFILE_RELEASE_LTO: ${{ contains(github.ref_name, '-alpha') && 'thin' || 'thin' }} + # Line tables keep release stack traces symbolicateable without the + # compile-time and memory cost of full debuginfo. + CARGO_PROFILE_RELEASE_DEBUG: line-tables-only + CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO: ${{ contains(matrix.target, 'apple-darwin') && 'packed' || 'off' }} + CARGO_PROFILE_RELEASE_STRIP: "false" # Use the git CLI instead of Cargo's libgit2 path for git dependencies. # macOS release runners have intermittently failed to fetch nested # submodules through SecureTransport/libgit2, especially libwebrtc's @@ -249,7 +254,7 @@ jobs: run: | set -euo pipefail sudo apt-get update -y - sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends binutils pkg-config libcap-dev - uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0 with: targets: ${{ matrix.target }} @@ -308,6 +313,10 @@ jobs: exit 1 fi + # Codex embeds this digest at build time and verifies the bundled + # bwrap resource before use. Strip bwrap before hashing so the digest + # covers the exact bytes that the release packages. + strip --strip-debug --strip-unneeded "$bwrap_path" digest="$(sha256sum "$bwrap_path" | awk '{print $1}')" echo "CODEX_BWRAP_SHA256=${digest}" >> "$GITHUB_ENV" echo "Built bwrap ${bwrap_path} with sha256:${digest}" @@ -321,6 +330,11 @@ jobs: fi build_args=() for binary in ${{ matrix.binaries }}; do + # bwrap was built, finalized, and hashed before this build so + # Codex can embed the digest of the bytes that will be packaged. + if [[ "$binary" == "bwrap" ]]; then + continue + fi build_args+=(--bin "$binary") done echo "CARGO_PROFILE_RELEASE_LTO: ${CARGO_PROFILE_RELEASE_LTO}" @@ -333,6 +347,32 @@ jobs: path: codex-rs/target/**/cargo-timings/cargo-timing.html if-no-files-found: warn + - name: Build symbols archive and strip binaries + shell: bash + run: | + binaries=() + for binary in ${{ matrix.binaries }}; do + # bwrap is already stripped before hashing. Its symbols are not + # useful enough to justify a separate pre-Codex symbols pass. + if [[ "$binary" == "bwrap" ]]; then + continue + fi + binaries+=("$binary") + done + bash "${GITHUB_WORKSPACE}/.github/scripts/archive-release-symbols-and-strip-binaries.sh" \ + --target "${{ matrix.target }}" \ + --artifact-name "${{ matrix.artifact_name }}" \ + --release-dir "target/${{ matrix.target }}/release" \ + --archive-dir "symbols-dist/${{ matrix.artifact_name }}" \ + --binaries "${binaries[*]}" + + - name: Upload symbols archive + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: ${{ matrix.artifact_name }}-symbols + path: codex-rs/symbols-dist/${{ matrix.artifact_name }}/* + if-no-files-found: error + - if: ${{ runner.os == 'macOS' && env.SIGN_MACOS != 'true' }} name: Stage unsigned macOS artifacts shell: bash @@ -1030,6 +1070,7 @@ jobs: run: | find dist -mindepth 1 -maxdepth 1 -type d \ ! -name '*-apple-darwin*-unsigned' \ + ! -name '*-symbols' \ ! -name 'aarch64-unknown-linux-musl' \ ! -name 'aarch64-unknown-linux-musl-app-server' \ ! -name 'x86_64-unknown-linux-musl' \ From 0fd91f10f38d70146f7b1d6ed6a3df34207c97cd Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Fri, 5 Jun 2026 10:01:11 -0700 Subject: [PATCH 2/2] Move release symbol profile into Cargo config --- .github/workflows/rust-release-windows.yml | 5 ----- .github/workflows/rust-release.yml | 5 +---- codex-rs/Cargo.toml | 7 ++++--- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/.github/workflows/rust-release-windows.yml b/.github/workflows/rust-release-windows.yml index de152af1caad..67c5c63ac904 100644 --- a/.github/workflows/rust-release-windows.yml +++ b/.github/workflows/rust-release-windows.yml @@ -20,11 +20,6 @@ jobs: defaults: run: working-directory: codex-rs - env: - # Line tables keep release stack traces symbolicateable without the - # compile-time and memory cost of full debuginfo. - CARGO_PROFILE_RELEASE_DEBUG: line-tables-only - CARGO_PROFILE_RELEASE_STRIP: "false" strategy: fail-fast: false matrix: diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index b34e8c3fed94..4b9526b60111 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -149,11 +149,8 @@ jobs: run: working-directory: codex-rs env: - # Line tables keep release stack traces symbolicateable without the - # compile-time and memory cost of full debuginfo. - CARGO_PROFILE_RELEASE_DEBUG: line-tables-only + # macOS release packages archive packed dSYM bundles before stripping. CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO: ${{ contains(matrix.target, 'apple-darwin') && 'packed' || 'off' }} - CARGO_PROFILE_RELEASE_STRIP: "false" # Use the git CLI instead of Cargo's libgit2 path for git dependencies. # macOS release runners have intermittently failed to fetch nested # submodules through SecureTransport/libgit2, especially libwebrtc's diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 5d6d11604949..270d72391bbf 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -502,10 +502,11 @@ strip = "symbols" [profile.release] lto = "thin" +debug = "line-tables-only" split-debuginfo = "off" -# Because we bundle some of these executables with the TypeScript CLI, we -# remove everything to make the binary as small as possible. -strip = "symbols" +# Keep release binaries symbolicateable until packaging has archived the +# sidecar symbols and stripped the binaries. +strip = false # See https://github.com/openai/codex/issues/1411 for details. codegen-units = 1