chore: automate codext packaging release #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |