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"