Files
codex/.github/workflows/python-sdk-release.yml
Ahmed Ibrahim 26ce6649a2 Build Python SDK artifacts before publishing the runtime (#44061)
## Why

The SDK release workflow published the runtime before building the SDK, so an SDK build failure could leave the runtime published on its own.

## What changed

- Extract a reusable SDK build workflow that packages checked-in generated code and runs alongside runtime preparation. Require both builds before publishing the runtime, and verify runtime availability before publishing the SDK.
- Add `stage-sdk --codex-version` to set an explicit runtime dependency independently of the SDK version, retaining the checked-in pin by default and rejecting missing or duplicate pins.
- Accept Codex release tags in the runtime version resolver and use its normalized Python version for standalone runtime PyPI verification.

## Testing

Add coverage for wheel and source distribution metadata, preservation of checked-in code, independent beta SDK versions, runtime tag normalization, and invalid versions or dependency pins.

GitOrigin-RevId: feb572fadcf5d148814b26b480b4bae5ef6a39c5
2026-09-09 05:14:27 +00:00

173 lines
5.8 KiB
YAML

name: python-sdk-release
on:
push:
tags:
- "python-v*"
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
resolve-python-release:
if: github.repository == 'openai/codex'
name: resolve-python-release
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
runtime_version: ${{ steps.python_release.outputs.runtime_version }}
sdk_version: ${{ steps.python_release.outputs.sdk_version }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Validate SDK tag and resolve pinned runtime
id: python_release
shell: bash
run: |
set -euo pipefail
python3 - <<'PY'
import os
import re
import tomllib
from pathlib import Path
sdk_version = os.environ["GITHUB_REF_NAME"].removeprefix("python-v")
if not re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+(?:b[0-9]+)?", sdk_version):
raise SystemExit(
"Python SDK release tags must identify a stable or beta release, "
"for example python-v0.147.0 or python-v0.1.0b1."
)
pyproject = tomllib.loads(Path("sdk/python/pyproject.toml").read_text())
prefix = "openai-codex-cli-bin=="
runtime_versions = [
dependency.removeprefix(prefix)
for dependency in pyproject["project"]["dependencies"]
if dependency.startswith(prefix)
]
if len(runtime_versions) != 1:
raise SystemExit(
f"Expected exactly one pinned {prefix} dependency, found {runtime_versions}"
)
if "b" not in sdk_version and sdk_version != runtime_versions[0]:
raise SystemExit(
f"Stable SDK version {sdk_version} must match pinned runtime {runtime_versions[0]}."
)
with Path(os.environ["GITHUB_OUTPUT"]).open("a") as output:
print(f"runtime_version={runtime_versions[0]}", file=output)
print(f"sdk_version={sdk_version}", file=output)
PY
prepare-python-runtime:
name: prepare-python-runtime
needs: resolve-python-release
permissions:
contents: read
uses: ./.github/workflows/python-runtime-build.yml
with:
runtime_version: ${{ needs.resolve-python-release.outputs.runtime_version }}
build-python-sdk:
name: build-python-sdk
needs: resolve-python-release
permissions:
contents: read
uses: ./.github/workflows/python-sdk-build.yml
with:
sdk_version: ${{ needs.resolve-python-release.outputs.sdk_version }}
runtime_version: ${{ needs.resolve-python-release.outputs.runtime_version }}
# Publish from the top-level workflow: PyPI does not support reusable
# workflows as Trusted Publishers. The runtime must be available before
# publishing the SDK that depends on it.
publish-python-runtime:
if: github.repository == 'openai/codex'
name: publish-python-runtime
needs:
- prepare-python-runtime
- build-python-sdk
- resolve-python-release
runs-on: ubuntu-latest
environment: pypi
permissions:
contents: read
id-token: write # Required for PyPI trusted publishing.
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Download Python runtime wheels
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: python-runtime-wheels
path: dist/python-runtime
- name: Publish Python runtime wheels to PyPI
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
packages-dir: dist/python-runtime
skip-existing: true
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.11.3"
- name: Verify Python runtime wheels are available on PyPI
env:
PYTHON_RUNTIME_VERSION: ${{ needs.resolve-python-release.outputs.runtime_version }}
run: |
uv run --no-project --with packaging==26.2 python .github/scripts/verify_pypi_release.py \
openai-codex-cli-bin "$PYTHON_RUNTIME_VERSION"
publish-python-sdk:
name: publish-python-sdk
needs:
- build-python-sdk
- publish-python-runtime
- resolve-python-release
runs-on: ubuntu-latest
environment: pypi
permissions:
contents: read
id-token: write # Required for PyPI trusted publishing.
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Download Python SDK package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: python-sdk-package
path: dist/python-sdk
- name: Publish Python SDK to PyPI
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
packages-dir: dist/python-sdk
skip-existing: true
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.11.3"
- name: Verify Python SDK is available on PyPI
env:
SDK_VERSION: ${{ needs.resolve-python-release.outputs.sdk_version }}
run: uv run --no-project --with packaging==26.2 python .github/scripts/verify_pypi_release.py openai-codex "$SDK_VERSION"