name: build-codex-packages description: Build and smoke-test unsigned Codex CLI and app-server release packages. inputs: target: description: Rust release target triple to build and test. required: true package-version: description: Semantic version to record in both packages. required: true build-mode: description: Use release optimizations (release) or disable them for faster smoke coverage (debug). required: true build-system: description: Build package binaries with Cargo or Bazel. default: cargo # Resolve package sources relative to the action so it works in both repository layouts. runs: using: composite steps: - name: Select release binaries id: package_setup shell: bash working-directory: codex-rs env: BASE_BINARIES: "codex codex-app-server codex-code-mode-host codex-exec-server" WINDOWS_ONLY_BINARIES: "codex-command-runner codex-windows-sandbox-setup" BUILD_MODE: ${{ inputs.build-mode }} BUILD_SYSTEM: ${{ inputs.build-system }} PACKAGE_ACTION_PATH: ${{ github.action_path }} run: | set -euo pipefail package_source_root="$(cd "${PACKAGE_ACTION_PATH}/../../.." && pwd)" echo "source_root=$package_source_root" >> "$GITHUB_OUTPUT" needed_binaries="$BASE_BINARIES" if [[ "$RUNNER_OS" == "Windows" ]]; then needed_binaries+=" $WINDOWS_ONLY_BINARIES" fi echo "NEEDED_BINARIES=$needed_binaries" >> "$GITHUB_ENV" case "$BUILD_SYSTEM" in cargo|bazel) ;; *) echo "Unsupported build system: $BUILD_SYSTEM" >&2; exit 1 ;; esac case "$BUILD_MODE" in release|debug) ;; *) echo "Unsupported build mode: $BUILD_MODE" >&2; exit 1 ;; esac - name: Set up Python 3.12 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" - name: Install uv uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2 with: version: "0.13.5" - name: Install Linux build dependencies if: ${{ runner.os == 'Linux' }} shell: bash working-directory: codex-rs run: | set -euo pipefail sudo apt-get update -y sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends binutils make pkg-config libcap-dev - name: Build Cargo package binaries if: inputs.build-system == 'cargo' uses: ./.github/actions/build-cargo-package-binaries with: target: ${{ inputs.target }} binaries: ${{ env.NEEDED_BINARIES }} build-mode: ${{ inputs.build-mode }} - name: Build Bazel package binaries if: inputs.build-system == 'bazel' uses: ./.github/actions/build-bazel-package-binaries with: target: ${{ inputs.target }} build-mode: ${{ inputs.build-mode }} - name: Normalize Windows PDB filenames if: ${{ runner.os == 'Windows' }} shell: bash working-directory: codex-rs env: TARGET: ${{ inputs.target }} run: | set -euo pipefail release_dir="${CARGO_TARGET_DIR}/${TARGET}/release" for binary in $NEEDED_BINARIES; do expected_pdb="${release_dir}/${binary}.pdb" if [[ -f "$expected_pdb" ]]; then continue fi underscored_pdb="${release_dir}/${binary//-/_}.pdb" if [[ ! -f "$underscored_pdb" ]]; then echo "PDB for ${binary} not found at ${expected_pdb} or ${underscored_pdb}" >&2 exit 1 fi cp "$underscored_pdb" "$expected_pdb" done - name: Archive symbols and strip binaries shell: bash working-directory: codex-rs env: TARGET: ${{ inputs.target }} PACKAGE_SOURCE_ROOT: ${{ steps.package_setup.outputs.source_root }} run: | set -euo pipefail bash "${PACKAGE_SOURCE_ROOT}/.github/scripts/archive-release-symbols-and-strip-binaries.sh" \ --target "${TARGET}" \ --artifact-name "${TARGET}" \ --release-dir "${CARGO_TARGET_DIR}/${TARGET}/release" \ --archive-dir "../symbols-dist/${TARGET}" \ --binaries "$NEEDED_BINARIES" - name: Build Codex package archives shell: bash working-directory: codex-rs env: TARGET: ${{ inputs.target }} CODEX_PACKAGE_VERSION: ${{ inputs.package-version }} PACKAGE_SOURCE_ROOT: ${{ steps.package_setup.outputs.source_root }} run: | set -euo pipefail target="${TARGET}" release_dir="${CARGO_TARGET_DIR}/${target}/release" archive_dir="${GITHUB_WORKSPACE}/dist/${target}" exe_suffix="" if [[ "$RUNNER_OS" == "Windows" ]]; then exe_suffix=".exe" fi package_args=( --target "$target" --code-mode-host-bin "${release_dir}/codex-code-mode-host${exe_suffix}" --exec-server-bin "${release_dir}/codex-exec-server${exe_suffix}" --cargo-profile release --package-version "$CODEX_PACKAGE_VERSION" --force ) if [[ "$RUNNER_OS" == "Linux" ]]; then package_args+=(--bwrap-bin "${release_dir}/bwrap") fi if [[ "$RUNNER_OS" == "Windows" ]]; then package_args+=( --codex-command-runner-bin "${release_dir}/codex-command-runner.exe" --codex-windows-sandbox-setup-bin "${release_dir}/codex-windows-sandbox-setup.exe" ) fi python3 "${PACKAGE_SOURCE_ROOT}/scripts/build_codex_package.py" \ "${package_args[@]}" \ --variant codex \ --entrypoint-bin "${release_dir}/codex${exe_suffix}" \ --package-dir "${RUNNER_TEMP}/codex-package-${target}" \ --archive-output "${archive_dir}/codex-package-${target}.tar.gz" \ --archive-output "${archive_dir}/codex-package-${target}.tar.zst" python3 "${PACKAGE_SOURCE_ROOT}/scripts/build_codex_package.py" \ "${package_args[@]}" \ --variant codex-app-server \ --entrypoint-bin "${release_dir}/codex-app-server${exe_suffix}" \ --package-dir "${RUNNER_TEMP}/codex-app-server-package-${target}" \ --archive-output "${archive_dir}/codex-app-server-package-${target}.tar.gz" \ --archive-output "${archive_dir}/codex-app-server-package-${target}.tar.zst" - name: Smoke-test assembled packages shell: bash working-directory: codex-rs env: TARGET: ${{ inputs.target }} PYTHONPATH: ${{ github.workspace }}/sdk/python/src${{ runner.os == 'Windows' && ';' || ':' }}${{ github.workspace }}/sdk/python/tests PACKAGE_SOURCE_ROOT: ${{ steps.package_setup.outputs.source_root }} run: | set -euo pipefail cd "${PACKAGE_SOURCE_ROOT}/scripts/codex_package/smoke_tests" target="${TARGET}" archive_dir="${GITHUB_WORKSPACE}/dist/${target}" mkdir -p "${GITHUB_WORKSPACE}/codex-rs/target" pytest_args=( -v --package-target "$target" --symbols-archive "${GITHUB_WORKSPACE}/symbols-dist/${target}/codex-symbols-${target}.tar.gz" ) # CI must exercise packaged tools; local smoke runs may use host tools. if command -v rg || { [[ "$RUNNER_OS" == "Linux" ]] && command -v bwrap; }; then echo "Host rg (or bwrap on Linux) is on PATH; CI must use packaged tools." >&2 exit 1 fi # Windows setup helpers can finish background ACL work after pytest exits. # Separate roots keep the next run from deleting their executables. uv run --frozen pytest "${pytest_args[@]}" \ --basetemp "${GITHUB_WORKSPACE}/codex-rs/target/package-smoke-gzip-tmp" \ --compression gzip \ --cli-archive "${archive_dir}/codex-package-${target}.tar.gz" \ --app-server-archive "${archive_dir}/codex-app-server-package-${target}.tar.gz" \ test_codex_package.py uv run --frozen pytest "${pytest_args[@]}" \ --basetemp "${GITHUB_WORKSPACE}/codex-rs/target/package-smoke-zstd-tmp" \ --compression zstd \ --cli-archive "${archive_dir}/codex-package-${target}.tar.zst" \ --app-server-archive "${archive_dir}/codex-app-server-package-${target}.tar.zst" \ test_codex_package.py