mirror of
https://github.com/openai/codex.git
synced 2026-11-03 19:53:25 +00:00
148 lines
4.2 KiB
Python
Executable File
148 lines
4.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Install Codex native binaries (Rust CLI plus ripgrep helpers)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import importlib.util
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
|
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
CODEX_CLI_ROOT = SCRIPT_DIR.parent
|
|
DEFAULT_WORKFLOW_URL = "https://github.com/openai/codex/actions/runs/17952349351" # rust-v0.40.0
|
|
CODEX_TARGETS = (
|
|
"x86_64-unknown-linux-musl",
|
|
"aarch64-unknown-linux-musl",
|
|
"x86_64-apple-darwin",
|
|
"aarch64-apple-darwin",
|
|
"x86_64-pc-windows-msvc",
|
|
"aarch64-pc-windows-msvc",
|
|
)
|
|
|
|
|
|
def _load_rg_utils():
|
|
spec = importlib.util.spec_from_file_location("rg_utils", SCRIPT_DIR / "rg_utils.py")
|
|
if spec is None or spec.loader is None:
|
|
raise RuntimeError("Unable to load rg_utils module")
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
rg_utils = _load_rg_utils()
|
|
fetch_rg = rg_utils.fetch_rg
|
|
extract_archive = rg_utils.extract_archive
|
|
DEFAULT_RG_TARGETS = rg_utils.DEFAULT_RG_TARGETS
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description="Install native Codex binaries.")
|
|
parser.add_argument(
|
|
"--workflow-url",
|
|
help=(
|
|
"GitHub Actions workflow URL that produced the artifacts. Defaults to a "
|
|
"known good run when omitted."
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
"root",
|
|
nargs="?",
|
|
type=Path,
|
|
help=(
|
|
"Directory containing package.json for the staged package. If omitted, the "
|
|
"repository checkout is used."
|
|
),
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def main() -> int:
|
|
args = parse_args()
|
|
|
|
codex_cli_root = (args.root or CODEX_CLI_ROOT).resolve()
|
|
bin_dir = codex_cli_root / "bin"
|
|
bin_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
workflow_url = (args.workflow_url or DEFAULT_WORKFLOW_URL).strip()
|
|
if not workflow_url:
|
|
workflow_url = DEFAULT_WORKFLOW_URL
|
|
|
|
_prepare_bin_layout(bin_dir, CODEX_TARGETS)
|
|
|
|
workflow_id = workflow_url.rstrip("/").split("/")[-1]
|
|
|
|
with tempfile.TemporaryDirectory(prefix="codex-native-artifacts-") as artifacts_dir_str:
|
|
artifacts_dir = Path(artifacts_dir_str)
|
|
_download_artifacts(workflow_id, artifacts_dir)
|
|
install_codex_binaries(artifacts_dir, bin_dir, CODEX_TARGETS)
|
|
|
|
fetch_rg(bin_dir, DEFAULT_RG_TARGETS)
|
|
|
|
print(f"Installed native dependencies into {bin_dir}")
|
|
return 0
|
|
|
|
|
|
def _prepare_bin_layout(bin_dir: Path, targets: Iterable[str]) -> None:
|
|
for legacy in bin_dir.glob("codex-*"):
|
|
if legacy.is_file():
|
|
legacy.unlink()
|
|
for legacy in bin_dir.glob("rg-*"):
|
|
if legacy.is_file():
|
|
legacy.unlink()
|
|
|
|
for target in targets:
|
|
shutil.rmtree(bin_dir / target, ignore_errors=True)
|
|
|
|
|
|
def _download_artifacts(workflow_id: str, dest_dir: Path) -> None:
|
|
cmd = [
|
|
"gh",
|
|
"run",
|
|
"download",
|
|
"--dir",
|
|
str(dest_dir),
|
|
"--repo",
|
|
"openai/codex",
|
|
workflow_id,
|
|
]
|
|
subprocess.run(cmd, check=True)
|
|
|
|
|
|
def install_codex_binaries(
|
|
artifacts_dir: Path, bin_dir: Path, targets: Iterable[str]
|
|
) -> list[Path]:
|
|
installed: list[Path] = []
|
|
for target in targets:
|
|
artifact_subdir = artifacts_dir / target
|
|
archive_name = _archive_name_for_target(target)
|
|
archive_path = artifact_subdir / archive_name
|
|
if not archive_path.exists():
|
|
raise FileNotFoundError(f"Expected artifact not found: {archive_path}")
|
|
|
|
dest_dir = bin_dir / target / "codex"
|
|
dest_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
binary_name = "codex.exe" if "windows" in target else "codex"
|
|
dest = dest_dir / binary_name
|
|
dest.unlink(missing_ok=True)
|
|
extract_archive(archive_path, "zst", None, dest)
|
|
if "windows" not in target:
|
|
dest.chmod(0o755)
|
|
installed.append(dest)
|
|
return installed
|
|
|
|
|
|
def _archive_name_for_target(target: str) -> str:
|
|
if "windows" in target:
|
|
return f"codex-{target}.exe.zst"
|
|
return f"codex-{target}.zst"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|