Skip to content

chore: automate codext packaging release #1

chore: automate codext packaging release

chore: automate codext packaging release #1

Workflow file for this run

name: rust-release
on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
jobs:
metadata:
runs-on: ubuntu-latest
outputs:
base_version: ${{ steps.compute.outputs.base_version }}
release_tag: ${{ steps.compute.outputs.release_tag }}
version: ${{ steps.compute.outputs.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 "base_version=${base_version}" >> "$GITHUB_OUTPUT"
echo "release_tag=rust-v${base_version}-${short_sha}" >> "$GITHUB_OUTPUT"
echo "version=${base_version}-${short_sha}" >> "$GITHUB_OUTPUT"
build-unix:
needs: metadata
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
defaults:
run:
working-directory: codex-rs
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
target: x86_64-unknown-linux-musl
artifact_name: codex-bin-x86_64-unknown-linux-musl
- runner: macos-15-xlarge
target: aarch64-apple-darwin
artifact_name: codex-bin-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@v2
with:
version: 0.14.0
- name: Install musl build tools
if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
env:
TARGET: ${{ matrix.target }}
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"
echo "AWS_LC_SYS_NO_JITTER_ENTROPY_X86_64_UNKNOWN_LINUX_MUSL=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_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS=" >> "$GITHUB_ENV"
- name: Cargo build
shell: bash
run: cargo build --target ${{ matrix.target }} --release --bin codex
- uses: actions/upload-artifact@v7
with:
name: ${{ matrix.artifact_name }}
path: codex-rs/target/${{ matrix.target }}/release/codex
if-no-files-found: error
build-windows:
needs: metadata
name: Build - windows-x64 - x86_64-pc-windows-msvc
runs-on:
group: codex-runners
labels: codex-windows-x64
timeout-minutes: 60
defaults:
run:
working-directory: codex-rs
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@1.93.0
with:
targets: x86_64-pc-windows-msvc
- name: Cargo build
shell: bash
run: |
cargo build --target x86_64-pc-windows-msvc --release \
--bin codex \
--bin codex-windows-sandbox-setup \
--bin codex-command-runner
- uses: actions/upload-artifact@v7
with:
name: codex-bin-x86_64-pc-windows-msvc
path: |
codex-rs/target/x86_64-pc-windows-msvc/release/codex.exe
codex-rs/target/x86_64-pc-windows-msvc/release/codex-windows-sandbox-setup.exe
codex-rs/target/x86_64-pc-windows-msvc/release/codex-command-runner.exe
if-no-files-found: error
publish-npm:
needs:
- metadata
- build-unix
- build-windows
name: publish-npm
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
scope: "@loongphy"
- name: Update npm
run: npm install -g npm@latest
- name: Download Linux x64 artifact
uses: actions/download-artifact@v8
with:
name: codex-bin-x86_64-unknown-linux-musl
path: ${{ runner.temp }}/artifacts/linux-x64
- name: Download macOS arm64 artifact
uses: actions/download-artifact@v8
with:
name: codex-bin-aarch64-apple-darwin
path: ${{ runner.temp }}/artifacts/darwin-arm64
- name: Download Windows x64 artifact
uses: actions/download-artifact@v8
with:
name: codex-bin-x86_64-pc-windows-msvc
path: ${{ runner.temp }}/artifacts/win32-x64
- name: Assemble vendor tree
shell: bash
run: |
set -euo pipefail
vendor_root="${RUNNER_TEMP}/npm-root"
mkdir -p \
"${vendor_root}/vendor/x86_64-unknown-linux-musl/codex" \
"${vendor_root}/vendor/aarch64-apple-darwin/codex" \
"${vendor_root}/vendor/x86_64-pc-windows-msvc/codex"
cp "${RUNNER_TEMP}/artifacts/linux-x64/codex" \
"${vendor_root}/vendor/x86_64-unknown-linux-musl/codex/codex"
cp "${RUNNER_TEMP}/artifacts/darwin-arm64/codex" \
"${vendor_root}/vendor/aarch64-apple-darwin/codex/codex"
cp "${RUNNER_TEMP}/artifacts/win32-x64/codex.exe" \
"${vendor_root}/vendor/x86_64-pc-windows-msvc/codex/codex.exe"
cp "${RUNNER_TEMP}/artifacts/win32-x64/codex-windows-sandbox-setup.exe" \
"${vendor_root}/vendor/x86_64-pc-windows-msvc/codex/codex-windows-sandbox-setup.exe"
cp "${RUNNER_TEMP}/artifacts/win32-x64/codex-command-runner.exe" \
"${vendor_root}/vendor/x86_64-pc-windows-msvc/codex/codex-command-runner.exe"
- 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.version }}
run: |
set -euo pipefail
./scripts/stage_npm_packages.py \
--release-version "${VERSION}" \
--package codex \
--vendor-src "${RUNNER_TEMP}/npm-root/vendor"
- name: Publish to npm
env:
VERSION: ${{ needs.metadata.outputs.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)
case "${filename}" in
codex-npm-linux-*-"${VERSION}".tgz)
publish_cmd+=(--tag linux-x64)
;;
codex-npm-darwin-*-"${VERSION}".tgz)
publish_cmd+=(--tag darwin-arm64)
;;
codex-npm-win32-*-"${VERSION}".tgz)
publish_cmd+=(--tag win32-x64)
;;
codex-npm-"${VERSION}".tgz)
publish_cmd+=(--tag latest)
;;
*)
echo "Unexpected npm tarball: ${filename}"
exit 1
;;
esac
echo "+ ${publish_cmd[*]}"
"${publish_cmd[@]}"
done
github-release:
needs:
- metadata
- build-unix
- build-windows
name: github-release
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- name: Download Linux x64 artifact
uses: actions/download-artifact@v8
with:
name: codex-bin-x86_64-unknown-linux-musl
path: dist/linux-x64
- name: Download macOS arm64 artifact
uses: actions/download-artifact@v8
with:
name: codex-bin-aarch64-apple-darwin
path: dist/darwin-arm64
- name: Download Windows x64 artifact
uses: actions/download-artifact@v8
with:
name: codex-bin-x86_64-pc-windows-msvc
path: dist/win32-x64
- name: Package release binaries
shell: bash
env:
VERSION: ${{ needs.metadata.outputs.version }}
run: |
set -euo pipefail
mv dist/linux-x64/codex dist/linux-x64/codext
tar -C dist/linux-x64 -czf "dist/codext-x86_64-unknown-linux-musl-${VERSION}.tar.gz" codext
mv dist/darwin-arm64/codex dist/darwin-arm64/codext
tar -C dist/darwin-arm64 -czf "dist/codext-aarch64-apple-darwin-${VERSION}.tar.gz" codext
mv dist/win32-x64/codex.exe dist/win32-x64/codext.exe
python3 - <<'PY'
import os
import zipfile
from pathlib import Path
version = os.environ["VERSION"]
root = Path("dist/win32-x64")
archive = Path("dist") / f"codext-x86_64-pc-windows-msvc-{version}.zip"
with zipfile.ZipFile(archive, "w", compression=zipfile.ZIP_DEFLATED) as zf:
for name in ["codext.exe", "codex-windows-sandbox-setup.exe", "codex-command-runner.exe"]:
zf.write(root / name, arcname=name)
PY
- name: Create release notes
shell: bash
env:
VERSION: ${{ needs.metadata.outputs.version }}
run: |
set -euo pipefail
cat > release-notes.md <<EOF
Automated main-branch release for Codext.
Version: ${VERSION}
Included binary packages:
- Linux x64
- macOS arm64
- Windows x64
EOF
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.metadata.outputs.release_tag }}
name: ${{ needs.metadata.outputs.version }}
body_path: release-notes.md
files: |
dist/codext-x86_64-unknown-linux-musl-${{ needs.metadata.outputs.version }}.tar.gz
dist/codext-aarch64-apple-darwin-${{ needs.metadata.outputs.version }}.tar.gz
dist/codext-x86_64-pc-windows-msvc-${{ needs.metadata.outputs.version }}.zip