flywheel-bootstrap-staging 0.1.9.202601271835__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bootstrap/__init__.py +3 -0
- bootstrap/__main__.py +48 -0
- bootstrap/artifacts.py +101 -0
- bootstrap/config_loader.py +122 -0
- bootstrap/constants.py +20 -0
- bootstrap/git_ops.py +324 -0
- bootstrap/install.py +129 -0
- bootstrap/orchestrator.py +797 -0
- bootstrap/payload.py +119 -0
- bootstrap/prompts.py +79 -0
- bootstrap/py.typed +1 -0
- bootstrap/runner.py +145 -0
- bootstrap/telemetry.py +147 -0
- flywheel_bootstrap_staging-0.1.9.202601271835.dist-info/METADATA +94 -0
- flywheel_bootstrap_staging-0.1.9.202601271835.dist-info/RECORD +17 -0
- flywheel_bootstrap_staging-0.1.9.202601271835.dist-info/WHEEL +4 -0
- flywheel_bootstrap_staging-0.1.9.202601271835.dist-info/entry_points.txt +2 -0
bootstrap/install.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Codex install/detection helpers (skeleton)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import shutil
|
|
6
|
+
import sys
|
|
7
|
+
import tarfile
|
|
8
|
+
import urllib.request
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
import subprocess
|
|
11
|
+
import tempfile
|
|
12
|
+
import platform
|
|
13
|
+
|
|
14
|
+
from bootstrap.constants import CODEX_RELEASE_BASE, DEFAULT_CODEX_VERSION
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def codex_on_path() -> bool:
|
|
18
|
+
"""Return True if `codex` is already available on PATH."""
|
|
19
|
+
# On Windows, explicitly look for codex.exe to avoid conflicts with
|
|
20
|
+
# other tools named "codex" (e.g., npm packages)
|
|
21
|
+
if sys.platform == "win32":
|
|
22
|
+
return shutil.which("codex.exe") is not None
|
|
23
|
+
return shutil.which("codex") is not None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def codex_login_status_ok(executable: Path | str = "codex") -> bool:
|
|
27
|
+
"""Return True if `codex login status` succeeds."""
|
|
28
|
+
cmd = [str(executable), "login", "status"]
|
|
29
|
+
print(f"[bootstrap] running: {cmd}", file=sys.stderr)
|
|
30
|
+
try:
|
|
31
|
+
result = subprocess.run(
|
|
32
|
+
cmd,
|
|
33
|
+
stdout=subprocess.PIPE,
|
|
34
|
+
stderr=subprocess.PIPE,
|
|
35
|
+
text=True,
|
|
36
|
+
check=False,
|
|
37
|
+
)
|
|
38
|
+
return result.returncode == 0
|
|
39
|
+
except FileNotFoundError:
|
|
40
|
+
return False
|
|
41
|
+
except OSError as e:
|
|
42
|
+
print(f"[bootstrap] OSError running codex: {e}", file=sys.stderr)
|
|
43
|
+
raise
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def ensure_codex(version: str | None = None, download_dir: Path | None = None) -> Path:
|
|
47
|
+
"""Ensure codex binary is available.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
version: Optional explicit version string to install.
|
|
51
|
+
download_dir: Optional directory where the tarball should be unpacked.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Path to the resolved codex executable.
|
|
55
|
+
"""
|
|
56
|
+
if codex_on_path():
|
|
57
|
+
path = shutil.which("codex")
|
|
58
|
+
assert path
|
|
59
|
+
return Path(path)
|
|
60
|
+
|
|
61
|
+
resolved_dir = download_dir or Path(tempfile.mkdtemp())
|
|
62
|
+
resolved_dir.mkdir(parents=True, exist_ok=True)
|
|
63
|
+
|
|
64
|
+
url, archive_type = _build_download_url(version)
|
|
65
|
+
|
|
66
|
+
if archive_type == "exe":
|
|
67
|
+
# Windows: direct .exe download, no extraction needed
|
|
68
|
+
codex_path = resolved_dir / "codex.exe"
|
|
69
|
+
_download(url, codex_path)
|
|
70
|
+
elif archive_type == "tar.gz":
|
|
71
|
+
archive_path = resolved_dir / "codex.tar.gz"
|
|
72
|
+
_download(url, archive_path)
|
|
73
|
+
with tarfile.open(archive_path, "r:gz") as tf:
|
|
74
|
+
tf.extractall(path=resolved_dir)
|
|
75
|
+
# Unix: look for codex binary
|
|
76
|
+
found_codex = next(resolved_dir.rglob("codex"), None)
|
|
77
|
+
if found_codex is None:
|
|
78
|
+
raise RuntimeError("codex binary not found after extraction")
|
|
79
|
+
codex_path = found_codex
|
|
80
|
+
else:
|
|
81
|
+
raise RuntimeError(f"unsupported archive type: {archive_type}")
|
|
82
|
+
|
|
83
|
+
codex_path.chmod(codex_path.stat().st_mode | 0o111)
|
|
84
|
+
return codex_path.resolve()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _build_download_url(version: str | None) -> tuple[str, str]:
|
|
88
|
+
"""Build the download URL for Codex.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Tuple of (url, archive_type) where archive_type is "exe" or "tar.gz".
|
|
92
|
+
"""
|
|
93
|
+
ver = version or DEFAULT_CODEX_VERSION or "latest"
|
|
94
|
+
system = sys.platform
|
|
95
|
+
machine = platform.machine().lower()
|
|
96
|
+
|
|
97
|
+
# Determine architecture tag
|
|
98
|
+
if "arm" in machine or "aarch64" in machine:
|
|
99
|
+
arch = "aarch64"
|
|
100
|
+
else:
|
|
101
|
+
arch = "x86_64"
|
|
102
|
+
|
|
103
|
+
# Build platform-specific URL
|
|
104
|
+
# Windows uses: codex-{arch}-pc-windows-msvc.exe
|
|
105
|
+
# macOS uses: codex-{arch}-apple-darwin.tar.gz
|
|
106
|
+
# Linux uses: codex-{arch}-unknown-linux-gnu.tar.gz
|
|
107
|
+
if system == "win32":
|
|
108
|
+
filename = f"codex-{arch}-pc-windows-msvc.exe"
|
|
109
|
+
archive_type = "exe"
|
|
110
|
+
elif system.startswith("darwin"):
|
|
111
|
+
filename = f"codex-{arch}-apple-darwin.tar.gz"
|
|
112
|
+
archive_type = "tar.gz"
|
|
113
|
+
elif system.startswith("linux"):
|
|
114
|
+
filename = f"codex-{arch}-unknown-linux-gnu.tar.gz"
|
|
115
|
+
archive_type = "tar.gz"
|
|
116
|
+
else:
|
|
117
|
+
raise RuntimeError(f"unsupported platform: {system}")
|
|
118
|
+
|
|
119
|
+
if ver == "latest":
|
|
120
|
+
return f"{CODEX_RELEASE_BASE}/{filename}", archive_type
|
|
121
|
+
return (
|
|
122
|
+
f"https://github.com/openai/codex/releases/download/{ver}/{filename}",
|
|
123
|
+
archive_type,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _download(url: str, dest: Path) -> None:
|
|
128
|
+
with urllib.request.urlopen(url) as resp, dest.open("wb") as fh:
|
|
129
|
+
fh.write(resp.read())
|