mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Stage publishable Python runtime wheels (#18865)
This is PR 2 of the Python SDK PyPI publishing split. [PR 1](https://github.com/openai/codex/pull/18862) refreshed the generated SDK bindings; this PR makes the runtime package itself publishable, and PR 3 will wire the SDK package/version pinning to this runtime package. ## Summary - Rename the runtime distribution to `openai-codex-cli-bin` while keeping the import package as `codex_cli_bin`. - Make the runtime package wheel-only and build `py3-none-<platform>` wheels instead of interpreter-specific wheels. - Add `stage-runtime --codex-version` and `--platform-tag` so release staging can produce the platform wheel matrix from Codex release tags. - Add focused artifact workflow tests for version normalization, platform tag injection, and runtime wheel metadata. ## Why Rename There is already an unofficial PyPI package, [`codex-bin`](https://pypi.org/project/codex-bin/), distributing OpenAI Codex binaries. Publishing the official SDK runtime dependency as `openai-codex-cli-bin` makes the ownership clear, avoids confusing the SDK-pinned runtime wheel with that unowned wrapper, and keeps the import package unchanged as `codex_cli_bin`. ## Tests - `uv run --extra dev pytest tests/test_artifact_workflow_and_binaries.py` -> 21 passed - `uv run --extra dev python scripts/update_sdk_artifacts.py stage-runtime /tmp/codex-python-pr2-rebased/runtime-stage /tmp/codex-python-pr2-rebased/codex --codex-version rust-v0.116.0-alpha.1 --platform-tag macosx_11_0_arm64` - `uv run --with build --extra dev python -m build --wheel /tmp/codex-python-pr2-rebased/runtime-stage` - `uv run --with twine --extra dev twine check /tmp/codex-python-pr2-rebased/runtime-stage/dist/openai_codex_cli_bin-0.116.0a1-py3-none-macosx_11_0_arm64.whl` ## Note - Full `uv run --extra dev pytest` currently fails because regenerating from schemas already on `main` adds new DeviceKey Python types. I left that generated catch-up out of this runtime-only PR.
This commit is contained in:
committed by
GitHub
Unverified
parent
0ebe69a8c3
commit
0127cef5db
@@ -5,5 +5,5 @@ Platform-specific runtime package consumed by the published `codex-app-server-sd
|
||||
This package is staged during release so the SDK can pin an exact Codex CLI
|
||||
version without checking platform binaries into the repo.
|
||||
|
||||
`codex-cli-bin` is intentionally wheel-only. Do not build or publish an sdist
|
||||
for this package.
|
||||
`openai-codex-cli-bin` is intentionally wheel-only. Do not build or publish an
|
||||
sdist for this package.
|
||||
|
||||
@@ -1,15 +1,30 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
||||
|
||||
|
||||
def _platform_tag() -> str:
|
||||
from packaging.tags import sys_tags
|
||||
|
||||
return next(iter(sys_tags())).platform
|
||||
|
||||
|
||||
class RuntimeBuildHook(BuildHookInterface):
|
||||
def initialize(self, version: str, build_data: dict[str, object]) -> None:
|
||||
del version
|
||||
if self.target_name == "sdist":
|
||||
raise RuntimeError(
|
||||
"codex-cli-bin is wheel-only; build and publish platform wheels only."
|
||||
"openai-codex-cli-bin is wheel-only; build and publish platform wheels only."
|
||||
)
|
||||
|
||||
platform_tag = self.config.get("platform-tag") or os.environ.get(
|
||||
"CODEX_CLI_BIN_PLATFORM_TAG"
|
||||
)
|
||||
if not isinstance(platform_tag, str) or not platform_tag:
|
||||
platform_tag = _platform_tag()
|
||||
|
||||
build_data["pure_python"] = False
|
||||
build_data["infer_tag"] = True
|
||||
build_data["infer_tag"] = False
|
||||
build_data["tag"] = f"py3-none-{platform_tag}"
|
||||
|
||||
@@ -3,7 +3,7 @@ requires = ["hatchling>=1.24.0"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "codex-cli-bin"
|
||||
name = "openai-codex-cli-bin"
|
||||
version = "0.0.0-dev"
|
||||
description = "Pinned Codex CLI runtime for the Python SDK"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
PACKAGE_NAME = "codex-cli-bin"
|
||||
PACKAGE_NAME = "openai-codex-cli-bin"
|
||||
|
||||
|
||||
def bundled_codex_path() -> Path:
|
||||
|
||||
@@ -11,7 +11,7 @@ cd sdk/python
|
||||
python -m pip install -e .
|
||||
```
|
||||
|
||||
Published SDK builds pin an exact `codex-cli-bin` runtime dependency. For local
|
||||
Published SDK builds pin an exact `openai-codex-cli-bin` runtime dependency. For local
|
||||
repo development, either pass `AppServerConfig(codex_bin=...)` to point at a
|
||||
local build explicitly, or use the repo examples/notebook bootstrap which
|
||||
installs the pinned runtime package automatically.
|
||||
@@ -53,7 +53,7 @@ python examples/01_quickstart_constructor/async.py
|
||||
|
||||
The repo no longer checks `codex` binaries into `sdk/python`.
|
||||
|
||||
Published SDK builds are pinned to an exact `codex-cli-bin` package version,
|
||||
Published SDK builds are pinned to an exact `openai-codex-cli-bin` package version,
|
||||
and that runtime package carries the platform-specific binary for the target
|
||||
wheel.
|
||||
|
||||
@@ -73,7 +73,7 @@ python scripts/update_sdk_artifacts.py \
|
||||
--runtime-version 1.2.3
|
||||
python scripts/update_sdk_artifacts.py \
|
||||
stage-runtime \
|
||||
/tmp/codex-python-release/codex-cli-bin \
|
||||
/tmp/codex-python-release/openai-codex-cli-bin \
|
||||
/path/to/codex \
|
||||
--runtime-version 1.2.3
|
||||
```
|
||||
@@ -81,14 +81,14 @@ python scripts/update_sdk_artifacts.py \
|
||||
This supports the CI release flow:
|
||||
|
||||
- run `generate-types` before packaging
|
||||
- stage `codex-app-server-sdk` once with an exact `codex-cli-bin==...` dependency
|
||||
- stage `codex-cli-bin` on each supported platform runner with the same pinned runtime version
|
||||
- build and publish `codex-cli-bin` as platform wheels only; do not publish an sdist
|
||||
- stage `codex-app-server-sdk` once with an exact `openai-codex-cli-bin==...` dependency
|
||||
- stage `openai-codex-cli-bin` on each supported platform runner with the same pinned runtime version
|
||||
- build and publish `openai-codex-cli-bin` as platform wheels only; do not publish an sdist
|
||||
|
||||
## Compatibility and versioning
|
||||
|
||||
- Package: `codex-app-server-sdk`
|
||||
- Runtime package: `codex-cli-bin`
|
||||
- Runtime package: `openai-codex-cli-bin`
|
||||
- Current SDK version in this repo: `0.2.0`
|
||||
- Python: `>=3.10`
|
||||
- Target protocol: Codex `app-server` JSON-RPC v2
|
||||
|
||||
@@ -15,7 +15,7 @@ import urllib.request
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
PACKAGE_NAME = "codex-cli-bin"
|
||||
PACKAGE_NAME = "openai-codex-cli-bin"
|
||||
PINNED_RUNTIME_VERSION = "0.116.0-alpha.1"
|
||||
REPO_SLUG = "openai/codex"
|
||||
|
||||
@@ -105,7 +105,7 @@ def _installed_runtime_version(python_executable: str | Path) -> str | None:
|
||||
"try:\n"
|
||||
" from codex_cli_bin import bundled_codex_path\n"
|
||||
" bundled_codex_path()\n"
|
||||
" print(json.dumps({'version': importlib.metadata.version('codex-cli-bin')}))\n"
|
||||
f" print(json.dumps({{'version': importlib.metadata.version({PACKAGE_NAME!r})}}))\n"
|
||||
"except Exception:\n"
|
||||
" sys.exit(1)\n"
|
||||
)
|
||||
|
||||
@@ -54,13 +54,13 @@ This avoids duplicate ways to do the same operation and keeps behavior explicit.
|
||||
|
||||
Common causes:
|
||||
|
||||
- published runtime package (`codex-cli-bin`) is not installed
|
||||
- published runtime package (`openai-codex-cli-bin`) is not installed
|
||||
- local `codex_bin` override points to a missing file
|
||||
- local auth/session is missing
|
||||
- incompatible/old app-server
|
||||
|
||||
Maintainers stage releases by building the SDK once and the runtime once per
|
||||
platform with the same pinned runtime version. Publish `codex-cli-bin` as
|
||||
platform with the same pinned runtime version. Publish `openai-codex-cli-bin` as
|
||||
platform wheels only; do not publish an sdist:
|
||||
|
||||
```bash
|
||||
@@ -72,7 +72,7 @@ python scripts/update_sdk_artifacts.py \
|
||||
--runtime-version 1.2.3
|
||||
python scripts/update_sdk_artifacts.py \
|
||||
stage-runtime \
|
||||
/tmp/codex-python-release/codex-cli-bin \
|
||||
/tmp/codex-python-release/openai-codex-cli-bin \
|
||||
/path/to/codex \
|
||||
--runtime-version 1.2.3
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ python -m pip install -e .
|
||||
Requirements:
|
||||
|
||||
- Python `>=3.10`
|
||||
- installed `codex-cli-bin` runtime package, or an explicit `codex_bin` override
|
||||
- installed `openai-codex-cli-bin` runtime package, or an explicit `codex_bin` override
|
||||
- local Codex auth/session configured
|
||||
|
||||
## 2) Run your first turn (sync)
|
||||
|
||||
@@ -23,11 +23,11 @@ python -m pip install -e .
|
||||
|
||||
When running examples from this repo checkout, the SDK source uses the local
|
||||
tree and does not bundle a runtime binary. The helper in `examples/_bootstrap.py`
|
||||
uses the installed `codex-cli-bin` runtime package.
|
||||
uses the installed `openai-codex-cli-bin` runtime package.
|
||||
|
||||
If the pinned `codex-cli-bin` runtime is not already installed, the bootstrap
|
||||
If the pinned `openai-codex-cli-bin` runtime is not already installed, the bootstrap
|
||||
will download the matching GitHub release artifact, stage a temporary local
|
||||
`codex-cli-bin` package, install it into your active interpreter, and clean up
|
||||
`openai-codex-cli-bin` package, install it into your active interpreter, and clean up
|
||||
the temporary files afterward.
|
||||
|
||||
Current pinned runtime version: `0.116.0-alpha.1`
|
||||
@@ -43,7 +43,7 @@ python examples/<example-folder>/async.py
|
||||
|
||||
The examples bootstrap local imports from `sdk/python/src` automatically, so no
|
||||
SDK wheel install is required. You only need the Python dependencies for your
|
||||
active interpreter and an installed `codex-cli-bin` runtime package (either
|
||||
active interpreter and an installed `openai-codex-cli-bin` runtime package (either
|
||||
already present or automatically provisioned by the bootstrap).
|
||||
|
||||
## Recommended first run
|
||||
|
||||
@@ -17,6 +17,8 @@ from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Sequence, get_args, get_origin
|
||||
|
||||
RUNTIME_DISTRIBUTION_NAME = "openai-codex-cli-bin"
|
||||
|
||||
|
||||
def repo_root() -> Path:
|
||||
return Path(__file__).resolve().parents[3]
|
||||
@@ -76,6 +78,24 @@ def current_sdk_version() -> str:
|
||||
return match.group(1)
|
||||
|
||||
|
||||
def normalize_codex_version(version: str) -> str:
|
||||
normalized = version.strip()
|
||||
if normalized.startswith("rust-v"):
|
||||
normalized = normalized.removeprefix("rust-v")
|
||||
elif normalized.startswith("v"):
|
||||
normalized = normalized.removeprefix("v")
|
||||
|
||||
normalized = re.sub(r"-alpha\.?([0-9]+)$", r"a\1", normalized)
|
||||
normalized = re.sub(r"-beta\.?([0-9]+)$", r"b\1", normalized)
|
||||
normalized = re.sub(r"-rc\.?([0-9]+)$", r"rc\1", normalized)
|
||||
|
||||
if not re.fullmatch(r"[0-9]+(?:\.[0-9]+)*(?:(?:a|b|rc)[0-9]+)?", normalized):
|
||||
raise RuntimeError(
|
||||
f"Could not normalize Codex version {version!r} to a PEP 440 version"
|
||||
)
|
||||
return normalized
|
||||
|
||||
|
||||
def _copy_package_tree(src: Path, dst: Path) -> None:
|
||||
if dst.exists():
|
||||
if dst.is_dir():
|
||||
@@ -110,6 +130,46 @@ def _rewrite_project_version(pyproject_text: str, version: str) -> str:
|
||||
return updated
|
||||
|
||||
|
||||
def _rewrite_runtime_platform_tag(pyproject_text: str, platform_tag: str) -> str:
|
||||
section = "[tool.hatch.build.targets.wheel.hooks.custom]"
|
||||
section_index = pyproject_text.find(section)
|
||||
if section_index == -1:
|
||||
raise RuntimeError("Could not find runtime wheel custom hook config")
|
||||
|
||||
next_section_index = pyproject_text.find("\n[", section_index + len(section))
|
||||
if next_section_index == -1:
|
||||
section_text = pyproject_text[section_index:]
|
||||
tail = ""
|
||||
else:
|
||||
section_text = pyproject_text[section_index:next_section_index]
|
||||
tail = pyproject_text[next_section_index:]
|
||||
|
||||
updated_section, count = re.subn(
|
||||
r'^platform-tag = "[^"]*"$',
|
||||
f'platform-tag = "{platform_tag}"',
|
||||
section_text,
|
||||
count=1,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
if count == 0:
|
||||
updated_section = section_text.rstrip() + f'\nplatform-tag = "{platform_tag}"\n'
|
||||
|
||||
return pyproject_text[:section_index] + updated_section + tail
|
||||
|
||||
|
||||
def _rewrite_project_name(pyproject_text: str, name: str) -> str:
|
||||
updated, count = re.subn(
|
||||
r'^name = "[^"]+"$',
|
||||
f'name = "{name}"',
|
||||
pyproject_text,
|
||||
count=1,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
if count != 1:
|
||||
raise RuntimeError("Could not rewrite project name in pyproject.toml")
|
||||
return updated
|
||||
|
||||
|
||||
def _rewrite_sdk_runtime_dependency(pyproject_text: str, runtime_version: str) -> str:
|
||||
match = re.search(r"^dependencies = \[(.*?)\]$", pyproject_text, flags=re.MULTILINE)
|
||||
if match is None:
|
||||
@@ -119,7 +179,7 @@ def _rewrite_sdk_runtime_dependency(pyproject_text: str, runtime_version: str) -
|
||||
|
||||
raw_items = [item.strip() for item in match.group(1).split(",") if item.strip()]
|
||||
raw_items = [item for item in raw_items if "codex-cli-bin" not in item]
|
||||
raw_items.append(f'"codex-cli-bin=={runtime_version}"')
|
||||
raw_items.append(f'"{RUNTIME_DISTRIBUTION_NAME}=={runtime_version}"')
|
||||
replacement = "dependencies = [\n " + ",\n ".join(raw_items) + ",\n]"
|
||||
return pyproject_text[: match.start()] + replacement + pyproject_text[match.end() :]
|
||||
|
||||
@@ -141,14 +201,21 @@ def stage_python_sdk_package(
|
||||
|
||||
|
||||
def stage_python_runtime_package(
|
||||
staging_dir: Path, runtime_version: str, binary_path: Path
|
||||
staging_dir: Path,
|
||||
codex_version: str,
|
||||
binary_path: Path,
|
||||
platform_tag: str | None = None,
|
||||
) -> Path:
|
||||
package_version = normalize_codex_version(codex_version)
|
||||
_copy_package_tree(python_runtime_root(), staging_dir)
|
||||
|
||||
pyproject_path = staging_dir / "pyproject.toml"
|
||||
pyproject_path.write_text(
|
||||
_rewrite_project_version(pyproject_path.read_text(), runtime_version)
|
||||
)
|
||||
pyproject_text = pyproject_path.read_text()
|
||||
pyproject_text = _rewrite_project_name(pyproject_text, RUNTIME_DISTRIBUTION_NAME)
|
||||
pyproject_text = _rewrite_project_version(pyproject_text, package_version)
|
||||
if platform_tag is not None:
|
||||
pyproject_text = _rewrite_runtime_platform_tag(pyproject_text, platform_tag)
|
||||
pyproject_path.write_text(pyproject_text)
|
||||
|
||||
out_bin = staged_runtime_bin_path(staging_dir)
|
||||
out_bin.parent.mkdir(parents=True, exist_ok=True)
|
||||
@@ -559,7 +626,7 @@ class PublicFieldSpec:
|
||||
class CliOps:
|
||||
generate_types: Callable[[], None]
|
||||
stage_python_sdk_package: Callable[[Path, str, str], Path]
|
||||
stage_python_runtime_package: Callable[[Path, str, Path], Path]
|
||||
stage_python_runtime_package: Callable[[Path, str, Path, str | None], Path]
|
||||
current_sdk_version: Callable[[], str]
|
||||
|
||||
|
||||
@@ -928,7 +995,7 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
stage_sdk_parser.add_argument(
|
||||
"--runtime-version",
|
||||
required=True,
|
||||
help="Pinned codex-cli-bin version for the staged SDK package",
|
||||
help="Pinned openai-codex-cli-bin version for the staged SDK package",
|
||||
)
|
||||
stage_sdk_parser.add_argument(
|
||||
"--sdk-version",
|
||||
@@ -949,10 +1016,23 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
type=Path,
|
||||
help="Path to the codex binary to package for this platform",
|
||||
)
|
||||
stage_runtime_parser.add_argument(
|
||||
"--codex-version",
|
||||
help=(
|
||||
"Codex release version to write into the staged runtime package. "
|
||||
"Accepts PEP 440 versions or release tags such as rust-v0.116.0-alpha.1."
|
||||
),
|
||||
)
|
||||
stage_runtime_parser.add_argument(
|
||||
"--runtime-version",
|
||||
required=True,
|
||||
help="Version to write into the staged runtime package",
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
stage_runtime_parser.add_argument(
|
||||
"--platform-tag",
|
||||
help=(
|
||||
"Optional wheel platform tag override, for example "
|
||||
"macosx_11_0_arm64 or musllinux_1_1_x86_64."
|
||||
),
|
||||
)
|
||||
return parser
|
||||
|
||||
@@ -970,6 +1050,26 @@ def default_cli_ops() -> CliOps:
|
||||
)
|
||||
|
||||
|
||||
def _resolve_runtime_version(args: argparse.Namespace) -> str:
|
||||
versions = [
|
||||
value
|
||||
for value in (
|
||||
getattr(args, "codex_version", None),
|
||||
getattr(args, "runtime_version", None),
|
||||
)
|
||||
if value is not None
|
||||
]
|
||||
if not versions:
|
||||
raise RuntimeError("Pass --codex-version to stage the Python runtime package")
|
||||
|
||||
normalized_versions = [normalize_codex_version(version) for version in versions]
|
||||
if len(set(normalized_versions)) != 1:
|
||||
raise RuntimeError(
|
||||
"Runtime package versions must match; pass one --codex-version"
|
||||
)
|
||||
return normalized_versions[0]
|
||||
|
||||
|
||||
def run_command(args: argparse.Namespace, ops: CliOps) -> None:
|
||||
if args.command == "generate-types":
|
||||
ops.generate_types()
|
||||
@@ -981,10 +1081,12 @@ def run_command(args: argparse.Namespace, ops: CliOps) -> None:
|
||||
args.runtime_version,
|
||||
)
|
||||
elif args.command == "stage-runtime":
|
||||
runtime_version = _resolve_runtime_version(args)
|
||||
ops.stage_python_runtime_package(
|
||||
args.staging_dir,
|
||||
args.runtime_version,
|
||||
runtime_version,
|
||||
args.runtime_binary.resolve(),
|
||||
args.platform_tag,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ from .retry import retry_on_overload
|
||||
|
||||
ModelT = TypeVar("ModelT", bound=BaseModel)
|
||||
ApprovalHandler = Callable[[str, JsonObject | None], JsonObject]
|
||||
RUNTIME_PKG_NAME = "codex-cli-bin"
|
||||
RUNTIME_PKG_NAME = "openai-codex-cli-bin"
|
||||
|
||||
|
||||
def _params_dict(
|
||||
|
||||
@@ -168,6 +168,19 @@ def test_examples_readme_matches_pinned_runtime_version() -> None:
|
||||
)
|
||||
|
||||
|
||||
def test_runtime_distribution_name_is_consistent() -> None:
|
||||
script = _load_update_script_module()
|
||||
runtime_setup = _load_runtime_setup_module()
|
||||
from codex_app_server import client as client_module
|
||||
|
||||
assert script.RUNTIME_DISTRIBUTION_NAME == "openai-codex-cli-bin"
|
||||
assert runtime_setup.PACKAGE_NAME == "openai-codex-cli-bin"
|
||||
assert client_module.RUNTIME_PKG_NAME == "openai-codex-cli-bin"
|
||||
assert "importlib.metadata.version('codex-cli-bin')" not in (
|
||||
ROOT / "_runtime_setup.py"
|
||||
).read_text()
|
||||
|
||||
|
||||
def test_release_metadata_retries_without_invalid_auth(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
runtime_setup = _load_runtime_setup_module()
|
||||
authorizations: list[str | None] = []
|
||||
@@ -222,19 +235,24 @@ def test_runtime_package_is_wheel_only_and_builds_platform_specific_wheels() ->
|
||||
),
|
||||
None,
|
||||
)
|
||||
build_data_assignments = {
|
||||
node.targets[0].slice.value: node.value.value
|
||||
for node in initialize_fn.body
|
||||
if isinstance(node, ast.Assign)
|
||||
and len(node.targets) == 1
|
||||
and isinstance(node.targets[0], ast.Subscript)
|
||||
and isinstance(node.targets[0].value, ast.Name)
|
||||
and node.targets[0].value.id == "build_data"
|
||||
and isinstance(node.targets[0].slice, ast.Constant)
|
||||
and isinstance(node.targets[0].slice.value, str)
|
||||
and isinstance(node.value, ast.Constant)
|
||||
}
|
||||
build_data_assignments = {}
|
||||
for node in initialize_fn.body:
|
||||
if (
|
||||
not isinstance(node, ast.Assign)
|
||||
or len(node.targets) != 1
|
||||
or not isinstance(node.targets[0], ast.Subscript)
|
||||
or not isinstance(node.targets[0].value, ast.Name)
|
||||
or node.targets[0].value.id != "build_data"
|
||||
or not isinstance(node.targets[0].slice, ast.Constant)
|
||||
or not isinstance(node.targets[0].slice.value, str)
|
||||
):
|
||||
continue
|
||||
if isinstance(node.value, ast.Constant):
|
||||
build_data_assignments[node.targets[0].slice.value] = node.value.value
|
||||
elif isinstance(node.value, ast.JoinedStr):
|
||||
build_data_assignments[node.targets[0].slice.value] = "joined-string"
|
||||
|
||||
assert pyproject["project"]["name"] == "openai-codex-cli-bin"
|
||||
assert pyproject["tool"]["hatch"]["build"]["targets"]["wheel"] == {
|
||||
"packages": ["src/codex_cli_bin"],
|
||||
"include": ["src/codex_cli_bin/bin/**"],
|
||||
@@ -244,7 +262,11 @@ def test_runtime_package_is_wheel_only_and_builds_platform_specific_wheels() ->
|
||||
"hooks": {"custom": {}},
|
||||
}
|
||||
assert sdist_guard is not None
|
||||
assert build_data_assignments == {"pure_python": False, "infer_tag": True}
|
||||
assert build_data_assignments == {
|
||||
"pure_python": False,
|
||||
"infer_tag": False,
|
||||
"tag": "joined-string",
|
||||
}
|
||||
|
||||
|
||||
def test_stage_runtime_release_copies_binary_and_sets_version(tmp_path: Path) -> None:
|
||||
@@ -260,9 +282,19 @@ def test_stage_runtime_release_copies_binary_and_sets_version(tmp_path: Path) ->
|
||||
|
||||
assert staged == tmp_path / "runtime-stage"
|
||||
assert script.staged_runtime_bin_path(staged).read_text() == "fake codex\n"
|
||||
assert 'name = "openai-codex-cli-bin"' in (staged / "pyproject.toml").read_text()
|
||||
assert 'version = "1.2.3"' in (staged / "pyproject.toml").read_text()
|
||||
|
||||
|
||||
def test_normalize_codex_version_accepts_release_tags_and_pep440_versions() -> None:
|
||||
script = _load_update_script_module()
|
||||
|
||||
assert script.normalize_codex_version("rust-v0.116.0-alpha.1") == "0.116.0a1"
|
||||
assert script.normalize_codex_version("v0.116.0-beta.2") == "0.116.0b2"
|
||||
assert script.normalize_codex_version("0.116.0rc3") == "0.116.0rc3"
|
||||
assert script.normalize_codex_version("0.116.0") == "0.116.0"
|
||||
|
||||
|
||||
def test_stage_runtime_release_replaces_existing_staging_dir(tmp_path: Path) -> None:
|
||||
script = _load_update_script_module()
|
||||
staging_dir = tmp_path / "runtime-stage"
|
||||
@@ -284,13 +316,30 @@ def test_stage_runtime_release_replaces_existing_staging_dir(tmp_path: Path) ->
|
||||
assert script.staged_runtime_bin_path(staged).read_text() == "fake codex\n"
|
||||
|
||||
|
||||
def test_stage_runtime_release_can_pin_wheel_platform_tag(tmp_path: Path) -> None:
|
||||
script = _load_update_script_module()
|
||||
fake_binary = tmp_path / script.runtime_binary_name()
|
||||
fake_binary.write_text("fake codex\n")
|
||||
|
||||
staged = script.stage_python_runtime_package(
|
||||
tmp_path / "runtime-stage",
|
||||
"0.116.0a1",
|
||||
fake_binary,
|
||||
platform_tag="musllinux_1_1_x86_64",
|
||||
)
|
||||
|
||||
pyproject = (staged / "pyproject.toml").read_text()
|
||||
assert 'platform-tag = "musllinux_1_1_x86_64"' in pyproject
|
||||
|
||||
|
||||
def test_stage_sdk_release_injects_exact_runtime_pin(tmp_path: Path) -> None:
|
||||
script = _load_update_script_module()
|
||||
staged = script.stage_python_sdk_package(tmp_path / "sdk-stage", "0.2.1", "1.2.3")
|
||||
|
||||
pyproject = (staged / "pyproject.toml").read_text()
|
||||
assert 'version = "0.2.1"' in pyproject
|
||||
assert '"codex-cli-bin==1.2.3"' in pyproject
|
||||
assert '"openai-codex-cli-bin==1.2.3"' in pyproject
|
||||
assert '"codex-cli-bin==1.2.3"' not in pyproject
|
||||
assert not any((staged / "src" / "codex_app_server").glob("bin/**"))
|
||||
|
||||
|
||||
@@ -329,7 +378,10 @@ def test_stage_sdk_runs_type_generation_before_staging(tmp_path: Path) -> None:
|
||||
return tmp_path / "sdk-stage"
|
||||
|
||||
def fake_stage_runtime_package(
|
||||
_staging_dir: Path, _runtime_version: str, _runtime_binary: Path
|
||||
_staging_dir: Path,
|
||||
_runtime_version: str,
|
||||
_runtime_binary: Path,
|
||||
_platform_tag: str | None,
|
||||
) -> Path:
|
||||
raise AssertionError("runtime staging should not run for stage-sdk")
|
||||
|
||||
@@ -358,8 +410,10 @@ def test_stage_runtime_stages_binary_without_type_generation(tmp_path: Path) ->
|
||||
"stage-runtime",
|
||||
str(tmp_path / "runtime-stage"),
|
||||
str(fake_binary),
|
||||
"--runtime-version",
|
||||
"1.2.3",
|
||||
"--codex-version",
|
||||
"rust-v0.116.0-alpha.1",
|
||||
"--platform-tag",
|
||||
"musllinux_1_1_x86_64",
|
||||
]
|
||||
)
|
||||
|
||||
@@ -372,9 +426,12 @@ def test_stage_runtime_stages_binary_without_type_generation(tmp_path: Path) ->
|
||||
raise AssertionError("sdk staging should not run for stage-runtime")
|
||||
|
||||
def fake_stage_runtime_package(
|
||||
_staging_dir: Path, _runtime_version: str, _runtime_binary: Path
|
||||
_staging_dir: Path,
|
||||
codex_version: str,
|
||||
_runtime_binary: Path,
|
||||
platform_tag: str | None,
|
||||
) -> Path:
|
||||
calls.append("stage_runtime")
|
||||
calls.append(f"stage_runtime:{codex_version}:{platform_tag}")
|
||||
return tmp_path / "runtime-stage"
|
||||
|
||||
def fake_current_sdk_version() -> str:
|
||||
@@ -389,7 +446,7 @@ def test_stage_runtime_stages_binary_without_type_generation(tmp_path: Path) ->
|
||||
|
||||
script.run_command(args, ops)
|
||||
|
||||
assert calls == ["stage_runtime"]
|
||||
assert calls == ["stage_runtime:0.116.0a1:musllinux_1_1_x86_64"]
|
||||
|
||||
|
||||
def test_default_runtime_is_resolved_from_installed_runtime_package(
|
||||
|
||||
Reference in New Issue
Block a user