Skip to content

rust-release

rust-release #11

Workflow file for this run

name: rust-release
on:
push:
branches:
- main
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
jobs:
metadata:
runs-on: ubuntu-latest
outputs:
release_version: ${{ steps.compute.outputs.release_version }}
steps:
- uses: actions/checkout@v6
- name: Compute release version
id: compute
shell: bash
run: |
set -euo pipefail
base_version="$(grep -m1 '^version' codex-rs/Cargo.toml | sed -E 's/version *= *"([^"]+)".*/\1/')"
short_sha="${GITHUB_SHA::7}"
echo "release_version=${base_version}-${short_sha}" >> "$GITHUB_OUTPUT"
build-unix:
needs: metadata
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
timeout-minutes: 120
permissions:
contents: read
defaults:
run:
working-directory: codex-rs
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
target: x86_64-unknown-linux-musl
- runner: macos-15-xlarge
target: x86_64-apple-darwin
- runner: macos-15-xlarge
target: aarch64-apple-darwin
steps:
- uses: actions/checkout@v6
- name: Install Linux build dependencies
if: ${{ runner.os == 'Linux' }}
shell: bash
run: |
set -euo pipefail
sudo apt-get update -y
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev libubsan1
- uses: dtolnay/rust-toolchain@1.93.0
with:
targets: ${{ matrix.target }}
- name: Use hermetic Cargo home
if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
shell: bash
run: |
set -euo pipefail
cargo_home="${GITHUB_WORKSPACE}/.cargo-home"
mkdir -p "${cargo_home}/bin"
echo "CARGO_HOME=${cargo_home}" >> "$GITHUB_ENV"
echo "${cargo_home}/bin" >> "$GITHUB_PATH"
: > "${cargo_home}/config.toml"
- name: Install Zig
if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29
with:
version: 0.14.0
- name: Install musl build tools
if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
env:
TARGET: ${{ matrix.target }}
shell: bash
run: bash "${GITHUB_WORKSPACE}/.github/scripts/install-musl-build-tools.sh"
- name: Configure rustc UBSan wrapper
if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
shell: bash
run: |
set -euo pipefail
ubsan=""
if command -v ldconfig >/dev/null 2>&1; then
ubsan="$(ldconfig -p | grep -m1 'libubsan\.so\.1' | sed -E 's/.*=> (.*)$/\1/')"
fi
wrapper_root="${RUNNER_TEMP:-/tmp}"
wrapper="${wrapper_root}/rustc-ubsan-wrapper"
cat > "${wrapper}" <<EOF
#!/usr/bin/env bash
set -euo pipefail
if [[ -n "${ubsan}" ]]; then
export LD_PRELOAD="${ubsan}\${LD_PRELOAD:+:\${LD_PRELOAD}}"
fi
exec "\$1" "\${@:2}"
EOF
chmod +x "${wrapper}"
echo "RUSTC_WRAPPER=${wrapper}" >> "$GITHUB_ENV"
echo "RUSTC_WORKSPACE_WRAPPER=" >> "$GITHUB_ENV"
- name: Clear sanitizer flags
if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
shell: bash
run: |
set -euo pipefail
echo "AWS_LC_SYS_NO_JITTER_ENTROPY=1" >> "$GITHUB_ENV"
target_no_jitter="AWS_LC_SYS_NO_JITTER_ENTROPY_${{ matrix.target }}"
target_no_jitter="${target_no_jitter//-/_}"
echo "${target_no_jitter}=1" >> "$GITHUB_ENV"
echo "RUSTFLAGS=" >> "$GITHUB_ENV"
echo "CARGO_ENCODED_RUSTFLAGS=" >> "$GITHUB_ENV"
echo "RUSTDOCFLAGS=" >> "$GITHUB_ENV"
echo "CARGO_BUILD_RUSTFLAGS=" >> "$GITHUB_ENV"
echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS=" >> "$GITHUB_ENV"
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS=" >> "$GITHUB_ENV"
echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS=" >> "$GITHUB_ENV"
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS=" >> "$GITHUB_ENV"
- name: Configure musl rusty_v8 artifact overrides
if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
env:
TARGET: ${{ matrix.target }}
shell: bash
run: |
set -euo pipefail
version="$(python3 "${GITHUB_WORKSPACE}/.github/scripts/rusty_v8_bazel.py" resolved-v8-crate-version)"
release_tag="rusty-v8-v${version}"
base_url="https://github.com/openai/codex/releases/download/${release_tag}"
archive="${base_url}/librusty_v8_release_${TARGET}.a.gz"
binding_dir="${RUNNER_TEMP}/rusty_v8"
binding_path="${binding_dir}/src_binding_release_${TARGET}.rs"
mkdir -p "${binding_dir}"
curl -fsSL "${base_url}/src_binding_release_${TARGET}.rs" -o "${binding_path}"
echo "RUSTY_V8_ARCHIVE=${archive}" >> "$GITHUB_ENV"
echo "RUSTY_V8_SRC_BINDING_PATH=${binding_path}" >> "$GITHUB_ENV"
- name: Cargo build
shell: bash
run: cargo build --target ${{ matrix.target }} --release --bin codex
- uses: actions/upload-artifact@v7
with:
name: codex-bin-${{ matrix.target }}
path: codex-rs/target/${{ matrix.target }}/release/codex
if-no-files-found: error
build-windows:
needs: metadata
name: Build - windows-2025 - ${{ matrix.target }}
runs-on: windows-2025
timeout-minutes: 90
permissions:
contents: read
defaults:
run:
working-directory: codex-rs
strategy:
fail-fast: false
matrix:
target:
- x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@1.93.0
with:
targets: ${{ matrix.target }}
- name: Cargo build
shell: bash
run: |
cargo build --target ${{ matrix.target }} --release \
--bin codex \
--bin codex-windows-sandbox-setup \
--bin codex-command-runner
- uses: actions/upload-artifact@v7
with:
name: codex-bin-${{ matrix.target }}
path: |
codex-rs/target/${{ matrix.target }}/release/codex.exe
codex-rs/target/${{ matrix.target }}/release/codex-windows-sandbox-setup.exe
codex-rs/target/${{ matrix.target }}/release/codex-command-runner.exe
if-no-files-found: error
publish-npm:
needs:
- metadata
- build-unix
- build-windows
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
registry-url: https://registry.npmjs.org
- name: Update npm
run: npm install -g npm@latest
- name: Download build artifacts
uses: actions/download-artifact@v8
with:
pattern: codex-bin-*
path: ${{ runner.temp }}/artifacts
- name: Assemble vendor tree
shell: bash
run: |
set -euo pipefail
artifacts_root="${RUNNER_TEMP}/artifacts"
vendor_root="${RUNNER_TEMP}/npm-root/vendor"
mkdir -p \
"${vendor_root}/x86_64-unknown-linux-musl/codex" \
"${vendor_root}/x86_64-apple-darwin/codex" \
"${vendor_root}/aarch64-apple-darwin/codex" \
"${vendor_root}/x86_64-pc-windows-msvc/codex"
cp "${artifacts_root}/codex-bin-x86_64-unknown-linux-musl/codex" \
"${vendor_root}/x86_64-unknown-linux-musl/codex/codex"
cp "${artifacts_root}/codex-bin-x86_64-apple-darwin/codex" \
"${vendor_root}/x86_64-apple-darwin/codex/codex"
cp "${artifacts_root}/codex-bin-aarch64-apple-darwin/codex" \
"${vendor_root}/aarch64-apple-darwin/codex/codex"
cp "${artifacts_root}/codex-bin-x86_64-pc-windows-msvc/codex.exe" \
"${vendor_root}/x86_64-pc-windows-msvc/codex/codex.exe"
cp "${artifacts_root}/codex-bin-x86_64-pc-windows-msvc/codex-windows-sandbox-setup.exe" \
"${vendor_root}/x86_64-pc-windows-msvc/codex/codex-windows-sandbox-setup.exe"
cp "${artifacts_root}/codex-bin-x86_64-pc-windows-msvc/codex-command-runner.exe" \
"${vendor_root}/x86_64-pc-windows-msvc/codex/codex-command-runner.exe"
- uses: facebook/install-dotslash@v2
- name: Install ripgrep payloads
run: python3 codex-cli/scripts/install_native_deps.py --component rg "${RUNNER_TEMP}/npm-root"
- name: Stage npm tarballs
env:
VERSION: ${{ needs.metadata.outputs.release_version }}
shell: bash
run: |
set -euo pipefail
out_dir="${GITHUB_WORKSPACE}/dist/npm"
mkdir -p "${out_dir}"
vendor_src="${RUNNER_TEMP}/npm-root/vendor"
packages=(
codex
codex-linux-x64
codex-darwin-x64
codex-darwin-arm64
codex-win32-x64
)
for package in "${packages[@]}"; do
stage_dir="$(mktemp -d "${RUNNER_TEMP}/npm-stage-${package}-XXXXXX")"
if [[ "${package}" == "codex" ]]; then
pack_output="${out_dir}/codex-npm-${VERSION}.tgz"
python3 codex-cli/scripts/build_npm_package.py \
--package "${package}" \
--release-version "${VERSION}" \
--staging-dir "${stage_dir}" \
--pack-output "${pack_output}"
else
platform="${package#codex-}"
pack_output="${out_dir}/codex-npm-${platform}-${VERSION}.tgz"
python3 codex-cli/scripts/build_npm_package.py \
--package "${package}" \
--release-version "${VERSION}" \
--staging-dir "${stage_dir}" \
--pack-output "${pack_output}" \
--vendor-src "${vendor_src}"
fi
rm -rf "${stage_dir}"
done
- name: Publish to npm
env:
VERSION: ${{ needs.metadata.outputs.release_version }}
shell: bash
run: |
set -euo pipefail
shopt -s nullglob
tarballs=(dist/npm/*-"${VERSION}".tgz)
if [[ ${#tarballs[@]} -eq 0 ]]; then
echo "No npm tarballs found in dist/npm for version ${VERSION}"
exit 1
fi
for tarball in "${tarballs[@]}"; do
filename="$(basename "${tarball}")"
publish_cmd=(npm publish "${GITHUB_WORKSPACE}/${tarball}" --access public)
tag=""
case "${filename}" in
codex-npm-linux-*-"${VERSION}".tgz)
tag="${filename#codex-npm-}"
tag="${tag%-${VERSION}.tgz}"
;;
codex-npm-darwin-*-"${VERSION}".tgz)
tag="${filename#codex-npm-}"
tag="${tag%-${VERSION}.tgz}"
;;
codex-npm-win32-*-"${VERSION}".tgz)
tag="${filename#codex-npm-}"
tag="${tag%-${VERSION}.tgz}"
;;
codex-npm-"${VERSION}".tgz)
tag="latest"
;;
*)
echo "Unexpected npm tarball: ${filename}"
exit 1
;;
esac
if [[ -n "${tag}" ]]; then
publish_cmd+=(--tag "${tag}")
fi
echo "+ ${publish_cmd[*]}"
set +e
publish_output="$("${publish_cmd[@]}" 2>&1)"
publish_status=$?
set -e
echo "${publish_output}"
if [[ ${publish_status} -eq 0 ]]; then
continue
fi
if grep -qiE "previously published|cannot publish over|version already exists" <<< "${publish_output}"; then
echo "Skipping already-published package version for ${filename}"
continue
fi
exit "${publish_status}"
done